Розробка додатку “Магазин”
У даній статті описано покроковий процес розробки повноцінного завершеного додатку “Магазин” обліку поступленого та реалізованого товару.
Пройшовши покрокову інструкцію, Ви навчитесь створювати додатки подібного типу, які для збереження даних використовують базу даних Microsoft Access.
Аналогічно до даного, можна створювати додатки, які взаємодіють з іншими базами даних.
Зміст
- Умова задачі
- Виконання
- 1. Створення додатку типу VCL Form Application.
- 2. Створюємо базу даних в MS Access.
- 3. Збереження проекту.
- 4. Створення головного меню.
- 5. Задаємо назву програми.
- 6. Організація роботи з базою даних.
- 7. Налаштування відображення даних.
- 8. Створення таблиці Tovar.
- 9. Створення таблиць Postupl та Realiz.
- 10. Створення підписів таблиць.
- 11. Програмне формування значень розрахункових полів.
- 12. Встановлення фільтру в таблицях.
- 13. Налаштування маски виведення в полях таблиць.
- 14. Налаштування захисту комірок таблиць від випадкової зміни.
- 15. Проектування форм діалогових вікон.
- 15.1. Проектування та підключення форми “Курс валют”.
- 15.2. Проектування форми додавання нової групи.
- 15.3. Проектування форми зміни (редагування) активної групи.
- 15.4. Форма вікна додавання товару.
- 15.5. Форма вікна редагування даних товару.
- 15.6. Форма вікна додавання нового поступлення.
- 15.7. Форма вікна редагування поступлення.
- 15.8. Додавання нової реалізації.
- 15.9. Редагування реалізації.
- 16. Підключення форм до головного модуля програми.
- 17. Робота з групою.
- 18. Команди меню “Товар”.
- 19. Команди меню “Поступлення”.
- 20. Встановлення курсу валют.
- 21. Команди меню “Реалізація”.
- 22. Команда “Вихід”.
- Схожі теми
Умова задачі
Розробити програмну систему, яка здійснює облік реалізації товарів у магазині, що займається продажем автозапчастин.
Програмна система повинна:
- забезпечувати облік поступлених та реалізованих товарів;
- здійснювати об’єднання подібних товарів за групами;
- враховувати плаваючий щоденний курс грошової одиниці країни (гривні, рубля);
- забезпечувати усі необхідні операції для зручного керування базою даних, а саме: фільтрування даних за заданими полями, сортування даних за заданими полями;
- мати засоби формування підсумкових звітів.
База даних повинна бути розроблена в системі Microsoft Access.
Програмну систему розробити в системі Embarcadero Delphi 2010.
Виконання
1. Створення додатку за шаблоном VCL Forms Application
Створити новий додаток за шаблоном VCL Forms Application. Приклад створення наведено тут.
2. Створення бази даних в MS Access
В Microsoft Access створити базу даних з іменем “auto.mdb“. Готову (раніше створену) базу даних можна завантажити тут.
Рекомендовано заповнити таблиці бази даних деякими значеннями, щоб легше можна було протестувати програму.
3. Збереження проекту
Рекомендовано зберігати проект в тій самій папці, що й файл бази даних. Приклад збереження проекту наведено тут.
Наприклад, можна створити окрему папку:
C:\Programs\Avto
і в ній зберегти увесь проект.
Ім’я головного модуля (форми) задаємо Main.pas.
4. Створення головного меню
Виносимо на форму компонент TMainMenu з палітри компонентів Standard (рис. 1). Формується об’єкт (змінна) з іменем MainMenu1.
Рис. 1. Головна форма програми з компонентом MainMenu1
Викликаємо режим формування меню (рис. 2).
Це здійснюється двома способами:
- подвійний клік мишкою на компоненті MainMenu1;
- виклик команди “Menu Designer…” з контекстного меню.
Рис. 2. Команда вибору вікна створення меню
У результаті виклику “Menu Designer…” відкривається вікно формування меню (рис. 3).
Рис. 3. Вікно для створення меню
У комірки меню вводимо назви елементів меню. Можна утворювати складну структуру з випадаючих меню. У нашому випадку створюємо меню так як показано на рисунку 4.
Рис. 4. Головне меню програми
Елемент “Курс валют…” містить команду “Змінити…“.
Елемент “Група” головного меню містить команди (рис. 5):
- “Додати…” – додавання нової групи в базу даних;
- “Редагувати…” – редагування даних виділеної групи в базі даних;
- “Видалити” – видалення групи з бази даних.
Рис. 5. Команди меню «Група»
Елемент “Товар“, “Поступлення” та “Реалізація” головного меню містять такі самі команди (рис. 6):
- «Додати…» – додавання нового товару, поступлення або реалізації;
- «Редагувати…» – редагування нового товару, поступлення або реалізації;
- «Видалити» – видалення товару, поступлення або реалізації.
Рис. 6. Команди меню «Товар», «Поступлення», «Реалізація»
У програмі використовується два звіти, опис яких буде дано нижче. Тому меню звіт має такий вигляд (рис. 7):
Рис. 7. Команди меню «Звіт»
Після закриття “Menu Designer…” форма програми матиме вигляд як показано на рисунку 8.
Рис. 8. Головна форма програми з створеним меню команд
5. Задавання назви програми
Для цього виділимо форму Form1 та встановимо в Object Inspector у властивості Caption назву “Магазин“.
Для зручного виведення основної форми програми додатково налаштовуємо такі властивості:
- опцію biMaximize властивості BorderIcons встановлюємо у значення false;
- властивість Position=poScreenCenter (центрування вікна програми).
Можна протестувати програму і запустити її на виконання. Вікно програми матиме вигляд як показано на рис. 9.
Рис. 9. Програма в режимі виконання
6. Організація роботи з базою даних
6.1. Компоненти для роботи з базою даних
Для зв’язку програми з базою даних на початку використаємо такі компоненти:
- TDataSource (вкладка Data Access);
- TADOConnection (вкладка dbGo);
- TADOQuery (вкладка dbGo).
Після винесення цих компонент на форму створиться три об’єкти (змінні) з іменами DataSource1, ADOConnection1, ADOQuery1.
Після змін у розмірах форми вікно програми у режимі проектування матиме вигляд, як показано на рисунку (10).
Рис. 10. Головна форма програми з компонентами для роботи з базою даних
Компоненти з палітри dbGo призначені для роботи з базами даних за технологією ADO, яка добре підходить для бази даних Microsoft Access.
Замість компонента TADOQuery можна використовувати компонент TADOTable. Можна поєднувати ці компоненти. У нашій програмі читання та зміни в базі даних будемо здійснювати шляхом формування запитів на мові SQL, тому, в цьому випадку краще підходить компонент TADOQuery, в якому ці запити зручно задавати. Також даний компонент добре підходить у випадку сортування даних в базі даних за деяким полем.
Для візуалізації даних з таблиць використовується компонент TDBGrid з палітри Data Controls. Він відображає дані в деякій таблиці бази даних. Спочатку відобразимо дані в таблиці Groups. Після винесення цього компонента на форму, вигляд вікна проектування матиме приблизно такий вигляд (рис. 11).
Рис. 11. Додавання компонента типу TDBGrid на форму
6.2. Підключення програми до бази даних.
Наступним кроком є підключення програми до бази даних auto.mdb.
Це здійснюється з допомогою компонента ADOConnection1, в якому задається рядок (шлях) до файлу бази даних та деякі інші параметри. Сам процес підключення складається з послідовності кроків у вигляді майстра підключень і детально описаний тут.
6.3. Налаштування зв’язків між ADO компонентами
Першочергово підключаємо таблицю Groups. Цій таблиці відповідають компоненти ADOQuery1, DataSource1 та DBGrid1. Компонент ADOConnection1 є спільним для всіх інших компонент, які ще будуть використані в програмі, і потрібний для безпосереднього зв’язку з базою даних.
Зв’язуємо компоненти ADOConnection1, DataSource1, ADOQuery1 та DBGrid1 між собою за такою схемою (рис. 12).
Рис. 12. Схема зв‘язків між компонентами програми і базою даних
Компонент DBGrid1 призначений для відображення даних в деякій таблиці бази даних. У нашому випадку це таблиця Groups.
Зв’язок компонента ADOConnection1 з базою даних вже встановлено.
Для утворення інших зв’язків між компонентами, зображеними на рисунку виконуємо такі дії.
Властивість Connection компонента ADOQuery1 встановлюємо у значення ADOConnection1, вибираючи його зі спадного меню (в списку меню буде тільки один цей компонент).
Так само властивість Dataset компонента DataSource1 встановлюємо у значення ADOQuery1.
Наступним кроком налаштовуємо властивість DataSource компонента DBGrid1 у значення DataSource1 шляхом вибору його зі спадного списку.
6.4. Формування SQL-запиту
Як уже було сказано раніше, в нашій програмі робота з базою даних базуватиметься на використанні запитів на мові SQL. Запити на мові SQL у програмі формуються в компоненті ADOQuery1 з допомогою однойменної властивості з назвою “SQL” (рис. 13).
Рис. 13. Властивість SQL компонента ADOQuery1
Вибором мишкою кнопки “…” поблизу назви властивості відкриється вікно редактора, в якому задамо код команди на мові SQL (рис. 14).
Рис. 14. Редактор команд SQL компонента ADOQuery1
Рядок виду
SELECT * FROM [Group]
означає вивести значення усіх полів таблиці Group бази даних. Ця таблиця відповідає за дані про групи товарів. Назва таблиці Group береться у квадратні дужки.
6.5. Активація ADOQuery1
Наступним кроком встановлюємо значення властивості Active компонента ADOQuery1 у значення true. Як тільки змінюється ця властивість у значення true, автоматично у DBGrid1 відображаються усі записи усіх полів таблиці Group (рис. 15).
Рис. 15. Встановлення властивості Active у значення true
7. Налаштування відображення даних
Основним компонентом, що відображає дані у базі даних у вигляді таблиці є компонент типу TDBGrid. Система Embarcadero Delphi 2010 дає програмісту також й інші компоненти для відображення даних.
У нашій програмі для відображення таблиці Group використовується компонент DBGrid1. Здійснимо його налаштування.
Таблиця Group складається з трьох полів: ID_Group, Name та Code. Значимими в таблиці є поля Name та Code. Поле ID_Group можна приховати.
Це робиться двома способами.
7.1. Приховування поля ID_Group з допомогою SQL-запиту
Мова SQL дозволяє виводити дані визначених полів в таблиці бази даних. У нашому випадку SQL-запит в компоненті ADOQuery1 (властивість SQL) матиме вигляд:
SELECT [Name], [Code] FROM [Group]
Цей запит означає, що потрібно вивести значення усіх записів полів Name та Code.
Після встановлення властивості SQL та активізації компонента ADOQuery1 (властивість Active компонента після змін SQL-запиту стане false) поле ID_Group зникне.
7.2. Приховування поля ID_Group з допомогою редактора полів
Редактор полів (Columns Editor) викликається в контекстному меню (правий клік мишкою) компонента DBGrid1.
Рис. 16. Виклик редактора полів з контекстного меню компонента DBGrid1
У результаті відкриється вікно “Editing DBGrid1.Columns” (рис. 17).
Рис. 17. Вікно редактора полів компонента DBGrid1
Вибираємо команду “Add All Fields” з контекстного меню або з панелі інструментів (рис. 18).
Рис. 18. Додавання усіх полів для відображення в компоненті DBGrid1
У вікні з’являються усі поля таблиці Group (рис. 19).
Рис. 19. Поля таблиці Group в редакторі полів компонента DBGrid1
Для того, щоб приховати поле ID_Group в компоненті DBGrid1 потрібно вибрати команду “Delete” з контекстного меню цього поля (рис. 20). Одразу ж поле ID_Group в таблиці DBGrid1 зникне. Після цього закриваємо редактор полів.
Рис. 20. Видалення поля ID_Group
Даний спосіб дає нам доступ до полів таблиці як об’єктів. У нашому випадку поле Name у редакторі є об’єктом з іменем DBGrid1.Columns[0] типу TColumn (відображається в Object Inspector). Це означає, що Delphi дає можливість редагувати деякі параметри цього поля, наприклад, ширину, центрування заголовку і т.д. Тому цей спосіб нам підходить краще.
Якщо використовувати тільки SQL-запити для відображення даних, то, наприклад, таку операцію як центрування заголовку потрібно виконувати програмно.
7.3. Налаштування параметрів полів
Здійснимо налаштування поля Name компонента DBGrid1.
Для цього відкриємо редактор полів і виділемо поле Name. У результаті в інспекторі об’єктів активізується об’єкт DBGrid1.Columns[0].
Налаштуємо ширину поля (властивість Width), наприклад у значення 150.
Здійснимо налаштування назви в полі Name (рис. 21), для цього розкриємо (знак “+“) властивість Title і встановимо
- значення властивості Alignment в taCenter;
- значення властивості Caption у “Група“.
Рис. 21. Налаштування параметрів поля Name таблиці Group в DBGrid1
Так само налаштовуємо параметри поля Code відповідними значеннями.
Після виконаних дій вікно програми в режимі проектування матиме вигляд, як показано на рисунку 22.
Рис. 22. Вікно основної форми після налаштування полів
7.4. Встановлення опції “тільки для читання” в компоненті DBGrid1
У нашій програмі компонент DBGrid1 призначений для відображення даних в таблиці Group. Меню програми “Група” містить три команди, які забезпечують усі необхідні операції з таблицею “Group“. Це команди “Додати…“, “Редагувати…” та “Видалити“. Тому, логічним є встановлення компонента DBGrid1 у режим тільки для читання щоб випадково не змінювати значення комірок.
Для цього потрібно виділити компонент DBGrid1 і встановити в Object Inspector опцію ReadOnly в значення true.
Після тестувального запуску програми на виконання, є можливість переміщуватись по полях таблиці Group, але немає можливості випадково змінювати значення комірок.
8. Створення таблиці Tovar
Після успішного створення таблиці Group перейдемо до створення таблиці Tovar.
Таблиця Tovar в базі даних має такі поля:
- ID_Tovar – унікальний ідентифікатор запису для одного товару;
- ID_Group – унікальний ідентифікатор запису групи, до якої належить товар;
- Name – назва товару;
- Code – код товару;
- Text – опис товару (необов’язкове поле);
- N_Post – кількість поступлень даного товару, виражена в штуках;
- Suma_Post – сума, виражена в грошових одиницях, поступлень даного товару;
- N_Real – кількість реалізацій даного товару, виражена в штуках;
- Suma_Real – сума, виражена в грошових одиницях, реалізацій даного товару;
- Zal – залишок в штуках одиниць даного товару.
8.1. Компоненти для роботи з таблицею Tovar
В таблиці Tovar є ряд полів, які будуть обчислюватись в процесі роботи програми. Поля, що обчислюються, можуть бути сформовані з допомогою відповідного SQL-запиту (компонент типу TADOQuery) або з допомогою програмного обчислення з використанням компонента типу TADOTable. Для нас другий спосіб підходить краще, оскільки, в цьому випадку, Delphi створює відповідні об’єкти, якими зручно оперувати. Тому, для доступу до таблиці Tovar використаємо компонент типу TADOTable замість TADOQuery (як було описано в п. 7) з палітри компонент DBGo.
Для відображення таблиці Tovar виносимо на основну форму програми ще три компоненти з іменами ADOTable1, DataSource2 та DBGrid2. Компонент DBGrid2 призначений для безпосереднього відображення таблиці Tovar.
8.2. Зв’язування компонент між собою та з базою даних
Здійснюємо зв’язування цих компонент з базою даних так як в п. 6.3. В компоненті ADOTable1 властивість Connection встановлюємо у значення ADOConnection1. В компоненті DataSource2 властивість Dataset рівна ADOTable1. В компоненті DBGrid2 властивість DataSource встановлюємо в DataSource2.
Окремо задаємо таблицю, з якою зв’язується компонент ADOTable1. У компоненті ADOQuery1 цієї властивості немає і не може бути, оскільки ADOQuery1 є запитом до бази даних, а не таблицею.
Для задавання таблиці Tovar в компоненті ADOTable1 необхідно у властивості TableName встановити значення Tovar (вибрати зі спадного списку).
Взаємодія компонент з базою даних зображена на рисунку 23.
Рис. 23. Взаємодія компонент з базою даних
8.3. Налаштування ADOTable1
Після активації (властивість Active встановлюється в true) ADOTable1 форма програми матиме вигляд як зображено на рис. 24.
Рис. 24. Вигляд головного вікна програми після додавання таблиці Tovar
8.4. Створення полів у ADOTable1
Щоб зручно оперувати полями ADOTable1 рекомендовано сформувати їх в програмі в редакторі полів «Fields Editor…» з контекстного меню, що відкривається при натиску правою кнопкою мишки на компоненті ADOTable1 (рис. 25).
Рис. 25. Виклик редактора полів компонента ADOTable1
У результаті відкриється вікно Form1.ADOTable1 редактора полів, зображене на рисунку 26.
Рис. 26. Редактор полів компонента ADOTable1
Додаємо поля, клацнувши праву кнопку мишки. Відкриється контекстне меню. Вибираємо команду “Add all fields” (рис. 27).
Рис. 27. Додавання усіх полів для обробки в ADOTable1
Вікно редактора полів прийме вигляд як показано на рисунку 28.
Рис. 28. Вікно редактора полів ADOTable1
Додаються усі поля, що є в таблиці Tovar бази даних “auto.mdb”.
Маємо 10 полів з іменами ID_Tovar, ID_Group, Name, Code, Text, N_Post, Suma_Post, N_Real, Suma_Real, Zal. Для кожного поля Delphi створює компонент-об’єкт з різного роду властивостями. Так, наприклад, для поля ID_Tovar створюється компонент ADOTable1ID_Tovar. Для поля ID_Group створюється компонент ADOTable1ID_Group і т.д.
Поля N_Post, Suma_Post, N_Real, Suma_Real та Zal є розрахунковими полями, тобто їх значення розраховуються в міру внесень даних в базу даних. Ці поля будуть формуватися програмно.
Види полів таблиці Tovar наведено нижче.
Закриваємо редактор полів ADOTable1.
8.5. Створення відображення таблиці Tovar в DBGrid2
Таблиця Tovar відображатиметься в компоненті DBGrid2.
Нам не потрібно відображати усі поля з таблиці Tovar, що є у компоненті ADOTable1.
Поля ID_Tovar та ID_Group призначені для зв’язування з зовнішіми таблицями. Тому, їх можна приховати на екрані.
Для цього формуємо відображення у компоненті DBGrid2.
Процес створення полів для відображення у DBGrid2 такий самий як описано в п.7.2. Викликаємо редактор полів “Editing DBGrid2.Columns” з контекстного меню “Columns Editor…” компонента DBGrid2. Шляхом команд додавання (Add All Fields) та видалення (Delete) полів ID_Tovar та ID_Group отримаємо наступне вікно редактора полів (рис. 29).
Рис. 29. Сформовані поля в редакторі полів компонента DBGrid2
Таким чином, таблиця Tovar відображає тільки значимі поля (8 полів). Для кожного поля, що відображене в вікні створюється компонент (об’єкт). В цьому компоненті можна більш детально сформувати відображення того чи іншого поля. Так, наприклад, для поля “0-Name” система Delphi створить об’єкт DBGrid2.Columns[0]. Для поля “1-Code” система створить об’єкт DBGrid2.Columns[1] і т.д.
8.6. Модифікація відображення таблиці Tovar в DBGrid2
На даний момент таблиця Tovar, що відображається в компоненті DBGrid2 має не дуже коректний вигляд. Так, заголовки таблиці можна змінити на українську мову а також відцентрувати їх. Також можна зробити центрування даних в деяких полях.
Перетворимо таблицю в такий вигляд.
8.6.1. Зміна порядку слідування полів
Поміняємо місцями поля Name та Code. Для цього в редакторі “Editing DBGrid2.Columns” перетягнемо поле “1-Code” на самий верх. Вікно редактора прийме вигляд (рис. 30).
Рис. 30. Зміна порядку слідування полів у таблиці Tovar
Тепер поле “0-Code” йде самим першим в списку полів і йому відповідає об’єкт DBGrid2.Columns[0].
8.6.2. Центрування заголовків полів
Процес центрування заголовків в DBGrid2 такий самий як в DBGrid1, описаний в п. 7.3.
Для центрування заголовку спочатку треба виділити “0-Code” в вікні “Editing DBGrid2.Columns”. Потім перейти в Object Inspector і в ньому розкрити властивість Title (знак +). Встановити властивість Alignment в значення taCenter, властивість Caption в значення “Код“. Можна, за бажанням, навести кольори заголовку, параметри шрифту та інше.
Також формуємо ширину кожного поля (властивість Width) таким чином, щоб вмістились усі поля у видиму частину вікна компонента DBGrid2.
Подібним чином формуємо усі заголовки таблиці.
Після внесених змін вікно програми в режимі проектування матиме вигляд, як зображено на рисунку 31.
Рис. 31. Головна форма програми після налаштування таблиці Tovar
Для заповнення розрахункових полів (N_Post, Suma_Post, N_Real, Suma_Real, Zal) в таблиці Tovar (ADOTable1) потрібно мати доступ до двох інших таблиць з бази даних:
- таблиці Postupl поступлень заданого товару;
- таблиці Realiz реалізацій кожного поступлення для заданого товару.
Для цього потрібно створити ці таблиці так як описано в п. 8.
9. Створення таблиць Postupl і Realiz
9.1. Компоненти для доступу до таблиць Postupl и Realiz
Процес створення таблиць Postupl та Realiz такий самий як і таблиці Tovar і є описаний в п. 8.
Для створення таблиці Postupl виносимо на форму компоненти з такими іменами: ADOTable2, DataSource3, DBGrid3. Зв’язуємо ці компоненти між собою (див. п.п. 6.3 та 8.2) та базою даних через компонент ADOConnection1.
Властивість TableName компонента ADOTable2 встановлюємо в значення Postupl.
Для створення таблиці поступлень так само виносимо компоненти з іменами ADOTable3, DataSource4, DBGrid4. Зв’язуємо ці компоненти (див. п.п. 6.3 та 8.2) між собою та базою даних через компонент ADOConnection1.
Властивість TableName компонента ADOTable3 встановлюємо в значення Realiz.
Загальна схема взаємодії між компонентами програми та базою даних має вигляд (рис. 32):
Рис. 32. Схема взаємодії між компонентами програми і базою даних
Таблиця Postupl в базі даних складається з таких полів.
Таблиця Realiz в базі даних складається з таких полів.
Додаємо в таблиці ADOTable2 та ADOTable3 поля з допомогою редактора Fields Editor… за зразком, описаним в п. 8.4.
Після активації таблиць ADOTable2 та ADOTable3 (властивість Active=true) програма в режимі проектування матиме наступний вигляд (рис. 33).
Рис. 33. Головна форма програми після налаштування ADOTable2 і ADOTable3
9.2. Налаштування відображення таблиць Postupl и Realiz в компонентах DBGrid3 та DBGrid4
Для відображення таблиця Postupl у програмі повинна мати приблизно такий вигляд.
Для відображення таблиця Realiz повинна мати приблизно такий вигляд.
Процес налаштування відображення таблиць в компоненті DBGrid1 описаний в п. 7. Таким самим чином налаштовуємо поля компонент DBGrid3 та DBGrid4.
В компоненті DBGrid3 в редакторі DBGrid3.Columns (команда контекстного меню “Columns Editor…“) спочатку додаємо усі поля (команда “Add All Fields“) а потім видаляємо поля ID_Postupl та ID_Tovar.
Остаточний вид вікна редактора “Editing DBGrid3.Columns” (рис. 34).
Рис. 34. Налаштування полів компонента DBGrid3
Аналогічно в компоненті DBGrid4 в редакторі DBGrid4.Columns після додавання усіх полів видаляємо поля ID_Realiz, ID_Postupl. Остаточний вигляд вікна редактора “Editing DBGrid4.Columns” (рис. 35).
Рис. 35. Налаштування полів компонента DBGrid4
З допомогою Object Inspector налаштовуємо потрібний нам вигляд таблиць, що відображаються в компонентах DBGrid3 та DBGrid4 (див. п. 7.3). Вносимо зміни в назви заголовків та вирівнювання полів.
Корегуємо розміри основної форми та компонент DBGrid3 та DBGrid4 таким чином, щоб усі поля таблиць коректно відображались на екрані (рис. 36).
Рис. 36. Головна форма програми після додавання та налаштування
таблиць Postupl і Realiz в компонентах ADOTable2, ADOTable3, DBGrid3, DBGrid4.
10. Створення підписів таблиць
З допомогою компонента Tlabel з палітри компонент Standart встановлюємо підписи кожної таблиці. В нашому випадку виносимо на форму 4 компоненти, які мають імена Label1, Label2, Label3, Label4. Властивість Caption кожного з цих компонент стає рівною назві відповідної таблиці.
Вікно основної форми в режимі проектування має такий вигляд (рис. 37).
Рис. 37. Головна форма програми після додавання підписів
11. Програмне формування значень розрахункових полів
На даний момент розрахункові поля таблиць Tovar, Postupl та Realiz є пустими. Вони повинні заповнюватись у процесі виконання програми.
Для заповнення даними таблиці Tovar створимо дві процедури:
- Calc_Tovar_Row – заповнює один рядок таблиці Tovar;
- Calc_Tovar – заповнює усі рядки (записи) таблиці Tovar.
Ці процедури включимо у розділ public (або private – не має значення) класу форми TForm1.
Аналогічно створюємо процедури заповнення розрахункових полів таблиць Postupl та Realiz:
- Calc_Postupl_Row – заповнює один рядок таблиці Postupl;
- Calc_Postupl – заповнює усі рядки таблиці Postupl;
- Calc_Realiz_Row – заповнює один рядок таблиці Realiz;
- Calc_Realiz.
Фрагмент програмного коду опису класу TForm1 має вигляд:
type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
ADOTable1: TADOTable;
...
private
{ Private declarations }
public
{ Public declarations }
procedure Calc_Tovar_Row(RecNo:word);
procedure Calc_Postupl_Row(RecNo:word);
procedure Calc_Realiz_Row(RecNo:word);
procedure Calc_Realiz; // заповнення таблиці Realiz
procedure Calc_Postupl; // заповнення таблиці Postupl
procedure Calc_Tovar; // заповнення таблиці Tovar
procedure Show_Tovar;
procedure Show_Postupl;
procedure Show_Realiz;
end;
Лістинги усіх шести процедур обчислення розрахункових полів подано нижче.
Лістинг процедури, яка заповнює один рядок таблиці Realiz.
procedure TForm1.Calc_Realiz_Row(RecNo:word);
begin
ADOTable3.DisableControls;
ADOTable3.RecNo := RecNo;
ADOTable3.Edit;
ADOTable3.Fields[5].AsFloat := ADOTable3.Fields[3].AsFloat * ADOTable3.Fields[4].AsInteger;
ADOTable3.Post;
ADOTable3.EnableControls;
end;
Пояснимо деякі фрагменти коду.
Доступ до розрахункового поля Suma_Real таблиці Realiz здійснюється через об’єкт
ADOTable3.Fields[5].AsFloat
Число 5 означає порядковий номер поля в ADOTable3 (можна переглянути через редактор полів “Fields Editor“). Закінчення AsFloat означає, що тип поля є дійсним числом. Тип поля в компоненті ADOTable3 повинен співпадати з типом поля таблиці Realiz в базі даних auto.mdb. В базі даних цей тип встановлений як “двойное с плавающей точкой”. Так само типи полів інших таблиць між компонентами і відповідними їм таблицями повинні співпадати.
Існують й інші способи доступу до полів бази даних в таблицях в системі Delphi.
Лістинг процедури, яка заповнює усі рядки таблиці Realiz має вигляд.
procedure TForm1.Calc_Realiz;
begin
ADOTable3.DisableControls;
ADOTable3.First;
for i := 1 to ADOTable3.RecordCount do
begin
Calc_Realiz_Row(ADOTable3.RecNo);
ADOTable3.Next;
end;
ADOTable3.EnableControls;
end;
На початку та в кінці процедури викликаються два методи (процедури) DisableControls та EnableControls компонента ADOTable3. Ці методи відповідають за підключення та відключення до набору даних візуальних елементів управління (у нашому випадку це компонент DBGrid4). Виклик методу DisableControls на початку дозволяє значно пришвидшити процес перебору записів, так як звільнить нашу програму від необхідності постійного (з кожною зміною запису) перемальовування вмісту елементу управління DBGrid4. В кінці процедури обов’язково потрібно викликати EnableControls.
Доступ до полів таблиці Postupl здійснюється через компонент ADOTable2.
Лістинг процедури Calc_Postupl_Row заповнення одного рядка таблиці Postupl наведено нижче. Процедура Calc_Postupl_Row викликається з процедури Calc_Postupl.
procedure TForm1.Calc_Postupl_Row(RecNo: Word);
var
i:integer;
id_post1, id_post2:integer;
n_real:integer;
suma_real:real;
begin
ADOTable2.RecNo := RecNo;
ADOTable2.Edit;
// Сума поступлення (закупівлі)
ADOTable2.Fields[7].AsFloat :=
ADOTable2.Fields[3].AsFloat * ADOTable2.Fields[6].AsInteger;
// розраховуємо кількість та суму реалізацій для даного поступлення
n_real := 0;
suma_real := 0;
id_post1 := ADOTable2.Fields[0].AsInteger; // Postupl.ID_Postupl
ADOTable3.First;
for i:=1 to ADOTable3.RecordCount do
begin
id_post2 := ADOTable3.Fields[1].AsInteger; // Realiz.ID_Postupl
if id_post1 = id_post2 then
begin
n_real := n_real + ADOTable3.Fields[4].AsInteger;
suma_real := suma_real + ADOTable3.Fields[5].AsFloat;
end;
ADOTable3.Next;
end;
// к-сть реалізацій (сума)
ADOTable2.Fields[8].AsInteger := n_real;
// сума реалізацій
ADOTable2.Fields[9].AsFloat := suma_real;
// залишок
ADOTable2.Fields[10].AsInteger :=
ADOTable2.Fields[6].AsInteger - ADOTable2.Fields[8].AsInteger;
ADOTable2.Post;
end;
Лістинг процедури Calc_Postupl для заповнення полів таблиці Postupl наступний.
procedure TForm1.Calc_Postupl;
var
i:integer;
begin
ADOTable2.First;
for i:=1 to ADOTable2.RecordCount do // перебір усіх полів таблиці Postupl
begin
Calc_Postupl_Row(ADOTable2.RecNo);
ADOTable2.Next;
end;
end;
Доступ до полів таблиці Tovar здійснюється через компонент ADOTable1.
Програмний код процедури заповнення одного рядка таблиці Tovar має вигляд.
procedure TForm1.Calc_Tovar_Row(RecNo:word);
var
n_post:integer;
suma_post:real;
n_real:integer;
suma_real:real;
zal:integer;
id_tovar1, id_tovar2:word;
i:integer;
begin
ADOTable1.DisableControls;
ADOTable2.DisableControls;
ADOTable1.RecNo := RecNo;
ADOTable1.Edit;
id_tovar1 := ADOTable1.Fields[0].AsInteger; // Tovar.ID_Tovar
n_post := 0; // кількість поступлень
suma_post := 0; // сума усіх поступлень
n_real := 0; // кількість реалізацій
suma_real := 0; // сума реалізацій
zal := 0; // залишок
ADOTable2.First;
for i:=1 to ADOTable2.RecordCount do
begin
// взяли код товару з таблиці Postupl
id_tovar2 := ADOTable2.Fields[1].AsInteger; // Postupl.ID_Tovar
if id_tovar1 = id_tovar2 then
begin
n_post := n_post + ADOTable2.Fields[6].AsInteger;
suma_post := suma_post + ADOTable2.Fields[7].AsFloat;
n_real := n_real + ADOTable2.Fields[8].AsInteger;
suma_real := suma_real + ADOTable2.Fields[9].AsFloat;
zal := zal + ADOTable2.Fields[10].AsInteger;
end;
ADOTable2.Next;
end;
// заповнюємо розрахункові поля таблиці Tovar
ADOTable1.Fields[5].AsInteger := n_post;
ADOTable1.Fields[6].AsFloat := suma_post;
ADOTable1.Fields[7].AsInteger := n_real;
ADOTable1.Fields[8].AsFloat := suma_real;
ADOTable1.Fields[9].AsInteger := zal;
ADOTable1.Post;
ADOTable1.EnableControls;
ADOTable2.EnableControls;
end;
У цьому коді програмно підраховуються суми поступлень, реалізацій та залишок на складі. Процедура Calc_Tovar_Row викликається з процедури Calc_Tovar.
Лістинг процедури Calc_Tovar обчислення усіх рядків (записів) таблиці Tovar наведено нижче.
procedure TForm1.Calc_Tovar;
var
i:integer;
begin
ADOTable1.First;
// перебір усіх полів таблиці Tovar
for i := 1 to ADOTable1.RecordCount do
begin
Calc_Tovar_Row(ADOTable1.RecNo);
ADOTable1.Next;
end;
end;
12. Встановлення фільтру в таблицях
При роботі з програмою користувач має можливість здійснювати переміщення по записах таблиць бази даних. При переході на інший запис (зміна активної групи) в таблиці Group автоматично повинно відбуватись перемальовування записів таблиці Tovar які відносяться до активної групи. При зміні активного запису в таблиці Tovar мають виводитись тільки ті записи таблиці Postupl, які відповідають даному товару. Те саме відноситься і до записів таблиці Postupl від яких залежить вигляд таблиці Realiz.
Напишемо програмний код обробників подій, які реагуватимуть на зміну групи в таблиці Group, товару в таблиці Tovar і поступлення в таблиці Postupl. Щоб відфільтрувати потрібні нам записи в компоненті ADOTable1 є властивість Filter, яка подібна до SQL-запиту. Наприклад, для виведення записів з таблиці Tovar, які відносяться до групи з ідентифікатором рівним 3, потрібно виконата такі дії:
- у властивість Filter внести рядок “ID_Group = 3“;
- властивість Filtered встановити в значення true.
Першочергово в класі форми TForm1 створюємо три процедури (див. п.11):
- Show_Tovar;
- Show_Postupl;
- Show_Realiz.
Лістинг реалізації цих процедур має вигляд.
// перемальовування таблиці Tovar
procedure TForm1.Show_Tovar;
var
id_group:word;
begin
id_group := ADOQuery1.Fields[0].AsInteger;
ADOTable1.Filter := 'ID_Group = ' + IntToStr(id_group);
ADOTable1.Filtered := true;
ADOTable1.First;
ADOTable1.Refresh;
end;
// перемальовування таблиці Postupl
procedure TForm1.Show_Postupl;
var
id_tovar:integer;
begin
id_tovar := ADOTable1.Fields[0].AsInteger;
ADOTable2.Filter := 'ID_Tovar = ' + IntToStr(id_tovar);
ADOTable2.Filtered := true;
ADOTable2.First;
ADOTable2.Refresh;
end;
// перемальовування таблиці Realiz
procedure TForm1.Show_Realiz;
var
id_postupl:integer;
begin
id_postupl := ADOTable2.Fields[0].AsInteger;
ADOTable3.Filter := 'ID_Postupl = ' + IntToStr(id_postupl);
ADOTable3.Filtered := true;
ADOTable3.First;
ADOTable3.Refresh;
end;
У кожній з процедур виконуються такі дії:
- Визначається унікальний ідентифікатор головної таблиц id_… .
- Заповнюється властивість Filter таблиці з одночасним встановленням опції Filtered у значення true.
- Відбувається перемотування на перший запис таблиці (метод First).
- Відбувається перемальовування зображення в компонентах відображення DBGrid (метод Refresh).
В обробник події OnCellClick компонента DBGrid1 вписуємо наступний код.
// Зміна активної групи
procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
Show_Tovar;
Show_Postupl;
Show_Realiz;
end;
Такий самий код вписуємо і в обробник події OnKeyUp цього ж компонента.
Цей код встановлює фільтр в компоненті ADOTable1, завдяки якому в таблиці Tovar відображаються тільки ті товари, що відносяться до групи, яка є активною в компоненті DBGrid1.
Лістинг процедури обробки події OnCellClick компонента DBGrid2 описано нижче. Такий самий код вписуємо і в обробник події OnKeyUp цього компонента.
// Зміна товару - перемалювати таблиці Postupl, Realiz
procedure TForm1.DBGrid2CellClick(Column: TColumn);
begin
Show_Postupl;
Show_Realiz;
end;
Лістинг процедури обробки події OnCellClick компонента DBGrid3 описано нижче. Цей код вписуємо в обробник події OnKeyUp цього компонента.
// Зміна активного поступлення - перемалювати таблицю Realiz
procedure TForm1.DBGrid2CellClick(Column: TColumn);
begin
Show_Postupl;
Show_Realiz;
end;
Після запуску проекту на виконання можна пересвідчитись, що при виборі записів таблиць Tovar, Postupl та Realiz виводяться тільки потрібні записи відповідних підпорядкованих таблиць.
13. Налаштування маски виведення в полях таблиць
На даний момент форма програми в режимі проектування має вигляд (рис. 38).
Рис. 38. Головна форма програми
В деяких полях таблиць Tovar, Postupl та Realiz там де фігурують грошові одиниці доцільно виводити значення з точністю 2 знаки після коми.
Встановимо точність виведення для таких полів таблиці Tovar (компонент ADOTable1):
- поле “Пост., грн.“, якому відповідає поле Suma_Post таблиці;
- поле “Реал., грн.“, якому відповідає поле Suma_Real таблиці.
Послідовність кроків заповнення поля “Пост., грн.” наступна.
- відкриваємо редактор полів “Fields Editor…” (див. п.8.3) компонента ADOTable1;
- вибираємо мишкою поле Suma_Post;
- в Object Inspector встановлюємо властивість “Display Format“ в значення “0.00“.
Автоматично в таблиці Tovar усі рядки будуть відображатися в зручному грошовому вигляді. Можна поекспериментувати з полем “Display Format” встановивши, наприклад, значення “0.00 грн“.
Таким самим чином налаштовуємо й інші поля:
- поле Suma_Real компонента ADOTable1;
- поля Prise_Zak, Exchange, Price_Rek, Suma_Zak, Suma_Real компонента ADOTable2;
- поля Price_Real, Suma_Real компонента ADOTable3.
У результаті виконаних дій поля усіх таблиць, що відповідають грошовим одиницям, будуть виводитись у більш читабельному вигляді.
14. Налаштування захисту комірок таблиць від випадкової зміни
При виділенні полів таблиць є ймовірність випадкової зміни значення виділеної комірки.
З метою уникнення цієї ситуації здійснимо такі кроки для компонента DBGrid1:
- виділити компонент DBGrid1;
- в Object Inspector властивість “ReadOnly” встановити в значення true;
- розкрити властивість Options (знак “+“) і в розкритому списку встановити опцію dgRowSelect в значення true.
Ці операції дозволяють виділяти цілий рядок в таблиці та запобігають випадковій зміні окремих комірок таблиці.
Такі самі дії проробляємо для компонент DBGrid2, DBGrid3, DBGrid4.
15. Проектування форм діалогових вікон
На даний момент маємо можливість зручно переглядати дані таблиць бази даних auto.mdb, яка заважується в програму автоматично.
Наступним кроком є створення форм діалогових вікон, що викликаються командами головного меню MainMenu1
15.1. Проектування і підключення форми “Курс валют”
Форма “Курс валют” викликається командою “Змінити…” з меню “Курс валют” головного меню програми.
Після створення форми об’єкт-змінна форми має ім’я Form2. Залишимо це ім’я без змін.
15.1.1. Налаштування компонент форми “Курс валют”
Послідовність кроків зі створення форми така.
- Створити нову форму в програмі. Задати ім’я модуля (файлу) форми “Form_Exchange“.
- Підключити нову форму до програми.
- Налаштувати такі властивості нової форми:
- властивість Caption = “Курс валют”;
- властивість BorderStyle = bsDialog (стиль як діалогове вікно);
- властивість Position = poScreenCenter (форма буде відображатись в центрі екрану).
4. Винести на форму компоненти (елементи управління) типу TLabel, TButton, TEdit та розмістити їх так як показано на рисунку. Маємо компоненти з іменами Label1, Button1, Button2, Edit1. Формуємо розміри та положення компонент таким чином, щоб форма мала привабливий вигляд (рис. 39).
Рис. 39. Вікно форми «Курс валют»
Встановлюємо такі властивості компонент:
- у компоненті Button1 властивість Caption=”Підтвердити”.
- у компоненті Button2 властивість Caption=”Відмінити”.
- у компоненті Edit1 власитвість Text=” (пустий рядок).
Встановлюємо порядок зміни активності елементів управління з допомогою клавіші Tab шляхом виклику контекстного меню форми “Tab Order…“. Встановлюємо такий порядок зміни:
- Edit1;
- Button1;
- Button2.
15.1.2. Реалізація подій форми
Обробник події активізації форми Form2 має вигляд.
procedure TForm2.FormActivate(Sender: TObject);
begin
Edit1.Text := '';
Edit1.SetFocus;
end;
В обробнику події активізації форми очищується поле рядка вводу та фокус керування передається компоненту Edit1.
Обробники подій клацання мишкою на кнопках “Підтвердити” та “Відмінити” мають такий вигляд. Результат повернення з форми заноситься в зовнішню змінну ModalResult.
procedure TForm2.Button1Click(Sender: TObject);
begin
ModalResult := mrOk;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
ModalResult := mrNo;
end;
15.2. Проектування форми додавання нової групи
Після створення форму додавання нової групи зберігаємо в модулі Form_Add_Group.pas. Об’єкт-змінна даної форми має ім’я Form3.
Формуємо форму за зразком, як показано на рисунку (рис. 40).
Рис. 40. Вікно додавання групи товарів
Для форми Form3 формуємо властивості подібно до того, як описано в п. 15.1.1.
Встановлюємо наступний порядок зміни фокусу введення для елементів управління з допомогою клавіші Tab:
- Edit1;
- Edit2;
- Button1;
- Button2.
Програмуємо події вибору команд «Підтвердити» та «Відмінити» так само, як описано в п. 15.1.2.
Лістинг обробника події активізації форми Form3 наступний.
procedure TForm3.FormActivate(Sender: Tobject);
begin
Edit1.Text := '';
Edit2.Text := '';
Edit1.SetFocus;
end;
15.3. Проектування форми зміни (редагування) активної групи
Вікно форми викликається після вибору команди «Змінити…» в меню «Група».
Форма зміни активної групи має ім’я (за замовчуванням) Form4. Компоненти, що розміщуються на формі такі самі як у формі Form3.
Програмний код обробників подій такий самий як у Form3 за виключенням того, що обробник події активізації форми має вигляд.
procedure Tform4.FormActivate(Sender: Tobject);
begin
Edit1.SetFocus;
end;
Значення полів (Edit1, Edit2, Edit3) про виділену на даний момент групу буде встановлюватись в основній формі Form1 програми, з якої ця форма буде викликатись (рис. 41).
Рис. 41. Форма редагування інформації про групу
15.4. Форма вікна додавання товару
Додавання нового товару в таблицю Tovar здійснюється командою “Додати…” з меню “Товар“. Файл форми зберігаємо під іменем “Form_Add_Tovar.pas“. Компонент-змінна форми має ім’я Form5.
Процес створення форми додавання товару подібний до процесу створення форми додавання групи (Form3). Форма додавання нового товару має вигляд, як зображено на рис. 42.
Рис. 42. Форма додавання нового товару
15.5. Форма вікна редагування даних товару
Форма вікна редагування даних товару зберігається в програмі в модулі “Form_Chg_Tovar.pas“. Компонент форми має ім’я Form6.
Послідовність дій зі створення форми така сама як при створенні форми додавання нового товару (Form5). Форма редагування інформації про товар зображена на рис. 43.
Рис. 43. Редагування даних про товар
15.6. Форма вікна додавання нового поступлення
Модуль форми зберігається у файлі Form_Add_Postupl.pas.
Вікно додавання нового поступлення має вигляд (рис. 44).
Рис. 44. Вікно додавання нового поступлення
Змінна-компонент, що відповідає формі поступлення має назву Form8.
Поле «Дата поступлення» – це є компонент типу TDateTimePicker, що розміщується на палітрі Win32.
Обробник події активізації форми дещо відрізняється від обробників подій попередніх форм.
procedure Tform8.FormActivate(Sender: Tobject);
begin
DateTimePicker1.DateTime := Date;
Edit1.Text := '';
Edit3.Text := '';
Edit4.Text := '';
Edit1.SetFocus;
end;
У першому рядку значенню компонента DateTimePicker1.DateTime присвоюється результат функції Date. Функція Date повертає дату, яка на даний момент встановлена в операційній системі.
Крім функції Date в Delphi є ще функція Time, яка повертає поточний час.
15.7. Форма вікна редагування поступлення
Форма вікна редагування поступлення у програмі має ім’я Form9 і зберігається у файлі «Form_Chg_Postupl.pas». Вікно редагування поступлення зображено на рисунку 45.
Рис. 45. Вікно редагування поступлення
15.8. Додавання нової реалізації
Компонент-змінна форми додавання нової реалізації в програмі має ім’я Form7. Вихідний код форми зберігається в модулі “Form_Add_Realiz.pas“.
Вікно додавання нової реалізації зображено на рисунку 46.
Рис. 46. Вікно додавання нового поступлення
Програмний код процедури події активізації форми наступний.
procedure TForm7.FormActivate(Sender: TObject);
begin
DateTimePicker1.DateTime := Date;
Edit2.Text := '';
DateTimePicker1.SetFocus;
end;
В обробнику подій активізації форми змінюємо тільки значення рядка вводу Edit2.Text. Інші рядки вводу будуть формуватись з основної форми програми.
15.9. Редагування реалізації
Форма редагування одного рядка реалізації зображена на рисунку 47. У результаті створення форми сформована змінна з іменем Form10. Модуль форми має назву “Form_Chg_Realiz.pas“.
Рис. 47. Вікно редагування рядка реалізації
Лістинг події активізації форми має вигляд.
procedure Tform10.FormActivate(Sender: Tobject);
begin
DateTimePicker1.DateTime := Date;
end;
Таким чином, на даному етапі ми спроектували 9 форм та запрограмували їх коректну поведінку. Усі форми будуть відкриватись з основного модуля Main.pas.
16. Підключення форми до головного модуля додатку
Для того, щоб мати доступ з головного модуля програми до модулів форм, створених у п. 15, потрібно здійснити відповідне підключення оператором uses.
Переходимо в модуль Main.pas (основна форма програми). Після слова implementation набираємо рядок підключення модулів форм.
Лістинг фрагменту коду програми має вигляд.
...
implementation
{$R *.dfm}
uses Form_Add_Group, Form_Add_Postupl, Form_Add_Realiz, Form_Add_Tovar, Form_Chg_Group, Form_Chg_Postupl, Form_Chg_Realiz, Form_Chg_Tovar, Form_Exchange;
...
Після цього до форм, що були створені у п. 15 можна доступатись за іменами їхніх змінних (компонент). Так, наприклад, до властивостей та методів форми додавання нової групи можна доступитись за іменем Form3.
17. Робота з групою
У цьому пункті напишемо програмний код, що реалізує операції з групою товарів. В головному меню програми передбачено три операції над групою товарів (меню «Група»):
- «Додати…»;
- «Редагувати…»;
- «Видалити».
17.1. Додавання нової групи
Доступ до полів форми, що використовується для додавання нової групи, здійснюється з допомогою змінної Form3.
Для того, щоб викликати додавання нової групи в програмі, треба запрограмувати обробник події вибору команди «Додати…» з меню «Група».
Спочатку знайдемо (викличемо) об’єкт-змінну, що відповідає цій команді. Для цього викличемо «Menu Designer…» компонента MainMenu1 (див. п. 4) і виділимо команду «Додати…» з меню «Група», як показано на рисунку 48.
Рис. 48. Команда «Додати…» з меню «Група»
В Object Inspector відобразиться назва елементу меню (об’єкту) типу TMenuItem. У нашому випадку це об’єкт з іменем N4. Після цього в Object Inspector переходимо на вкладку Events (події) і активуємо подію OnClick (рис. 49). Подія OnClick генерується у випадку, коли користувач вибрав елемент меню (з допомогою мишки, клавіатури чи гарячої клавіші).
Рис. 49. Обробник події OnClick команди «Додати…» з меню «Група»
Лістинг обробника події N4Click вибору команди додавання групи наступний.
// Вибір команди Група -> "Додати..."
procedure TForm1.N4Click(Sender: TObject);
begin
if Form3.ShowModal = mrOk then
begin
ADOQuery1.Close; // закриваємо з’єднання з базою даних
// Формуємо SQL-запит для компонента ADOQuery1
ADOQuery1.SQL.Clear; // очищаємо рядок попереднього SQL-запиту
ADOQuery1.SQL.Add('INSERT INTO [Group] '); // формуємо новий запит
ADOQuery1.SQL.Add('([Name], [Code]) ');
ADOQuery1.SQL.Add('VALUES ("' + Form3.Edit1.Text + '", ');
ADOQuery1.SQL.Add('"' + Form3.Edit2.Text + '") ');
// виконуємо новий запит - група додається в базу даних
ADOQuery1.ExecSQL;
// відновлюємо старий SQL-запит
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM [Group]');
ADOQuery1.Open; // відкриваємо доступ до бази даних
ADOQuery1.Last; // виділення доданої групи
end;
end;
Пояснимо деякі моменти в програмі.
Після виклику команди “Додати…” відкривається форма Form3 з модуля “Form_Add_Group.pas” з допомогою виклику функції Form3.ShowModal. Якщо у вікні форми додавання групи користувач вибрав кнопку “Підтвердити“, то результатом повернення з форми буде константа mrOk. У нашому випадку при виборі “Підтвердити” хід виконання програми переходить в область операторних дужок begin … end (з допомогою оператора умовного переходу if).
В операторних дужках формується SQL-запит до бази даних, який має вигляд:
INSERT INTO [Group] ([Name], [Code]) VALUES ("value1", "value2")
де значення value1 береться з рядка вводу Form3.Edit1.Text, а значення value2 з рядка Form3.Edit2.Text. Даний SQL-запит додає рядок в таблицю Group бази даних.
Оскільки, таблиця Group з’єднана з програмою з допомогою компонента ADOQuery1 системи Delphi, то цей запит формуємо у однойменній властивості ADOQuery1.SQL. Ця властивість є масивом рядків типу TStrings.
Обов’язковим є попереднє очищення рядка SQL-запиту. Додавання нових рядків виконується з допомогою методу Add, який в якості параметра приймає рядок, що додається.
Для виконання SQL-запиту використовується функція ExecSQL компонента ADOQuery1. Після виклику функції нова група з заданими параметрами буде додана до бази даних.
Так як з компонентом ADOQuery1 зв’язаний елемент управління відображенням даних DBGrid1, то обов’язковим в даному коді є відновлення старого SQL-запиту, який був до цього. Старий SQL-запит просто виводив усі записи таблиці Group і мав наступний вигляд:
SELECT * FROM [Group]
Назву таблиці Group в SQL-запитах потрібно брати в квадратні дужки, тому що в мові SQL є команда GROUP BY. Це робиться з метою уникнення неоднозначностей.
Протестуємо роботу системи. Запускаємо проект на виконання (клавіша F9). Викликаємо команду “Додати…” з меню “Група“. Вносимо дані, як показано на рисунку 50 (або інші дані).
Рис. 50. Вікно додавання нової групи товарів в режимі виконання
Після підтвердження група з заданими даними додається до бази даних (рис. 51).
Рис. 51. Результат додавання нової групи
17.2. Редагування групи
Редагування даних про групу викликається командою “Редагувати…” меню “Група“.
При редагуванні даних групи так само, як і при додаванні групи використаємо SQL-запит.
Вигляд SQL-запиту наступний.
UPDATE [Group] SET [Name] = value1, [Code] = value2 WHERE [Group].ID_Group = id_gr
де value1 – значення рядка Form4.Edit1.Text, а value2 – значення рядка Form4.Edit2.Text.
Вихідний код обробки події вибору команди “Редагувати…” з меню “Група” має вигляд.
// Група -> Редагувати...
procedure TForm1.N5Click(Sender: TObject);
var
id_gr:word;
old_rec:word;
begin
//
Form4.Edit1.Text := ADOQuery1.Fields[1].AsString; // взяли назву виділеної групи
Form4.Edit2.Text := ADOQuery1.Fields[2].AsString; // код групи
if Form4.ShowModal = mrOk then
begin
old_rec := ADOQuery1.RecNo;
id_gr := ADOQuery1.Fields[0].AsInteger; // взяли код ID_Group
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('UPDATE [Group] ');
ADOQuery1.SQL.Add('SET [Name] = "' + Form4.Edit1.Text + '", ');
ADOQuery1.SQL.Add('[Code] = "' + Form4.Edit2.Text + '" ');
ADOQuery1.SQL.Add('WHERE [Group].ID_Group = ' + IntToStr(id_gr));
ADOQuery1.ExecSQL;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM [Group]');
ADOQuery1.Open;
ADOQuery1.RecNo := old_rec;
end;
end;
Як видно з коду формуємо SQL-запит в компоненті ADOQuery1 та виконуємо його. Змінна old_rec призначена для запам’ятовування номеру позиції активного запису до виконання запиту та його відновлення після виконання запиту (для коректної роботи).
17.3. Видалення групи
Видалення групи викликається командою “Видалити” з меню “Група“. SQL-запит видалення активного рядка (групи) має вигляд
DELETE FROM [Group] WHERE ID_Group = id_gr
де num_gr – унікальний ідентифікатор виділеної групи.
Лістинг обробника події видалення групи має такий вигляд.
// Група -> Видалити
procedure TForm1.N6Click(Sender: TObject);
var
id_gr:word;
begin
if MessageDlg('Ви дійсно хочете видалити дану групу?',mtConfirmation,mbYes,mbNo],0,mbYes)=mrYes then
begin
id_gr := ADOQuery1.Fields[0].AsInteger; // взяли код ID_Group
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('DELETE FROM [Group]');
ADOQuery1.SQL.Add('WHERE ID_Group = ' + IntToStr(id_gr));
ADOQuery1.ExecSQL;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM [Group]');
ADOQuery1.Open;
end;
end;
У вищенаведеному лістингу для підтвердження запиту про видалення рядка поточної групи використовується метод MessageDlg, який представляє собою звичайне діалогове вікно підтвердження, що зображене на рисунку 52. Метод MessageDlg має ряд власних параметрів, що дозволяють маніпулювати виглядом вікна та кількістю кнопок у вікні.
Можна піти й іншим шляхом, створивши власну форму запиту на видалення.
Рис. 52. Вікно, що відкривається при виклику методу MessageDlg
18. Команди меню “Товар”
В меню “Товар” міститься три команди:
- додавання товару (команда “Додати…“);
- редагування поточного товару (команда “Редагувати…“);
- видалення товару (команда “Видалити“).
З товарами у програмі зв’язана таблиця Tovar бази даних. Для доступу до записів таблиці Tovar в базі даних використовується компонент ADOTable1. Тому, всі операції з додавання, редагування чи видалення даних будуть виконуватись в компоненті ADOTable1. Автоматично усі зміни відображатимуться в компоненті DBGrid2, що зв’язаний з ADOTable1.
18.1. Додавання товару
Додавання нового товару здійснюється командою “Додати…” з меню “Товар“. У результаті виклику команди повинно відкритись вікно додавання товару, яке було сформоване в
п. 15.4.
Обробник події додавання товару має такий вигляд.
// Товар -> Додати...
procedure TForm1.N8Click(Sender: TObject);
var
id_group:word;
begin
// додавання нового товару
if Form5.ShowModal=mrOk then
begin
// взяли ID_Group з таблиці Group
id_group := ADOQuery1.Fields[0].AsInteger;
ADOTable1.Append;
ADOTable1.Fields[1].AsInteger := id_group;
ADOTable1.Fields[2].AsString := Form5.Edit1.Text;
ADOTable1.Fields[3].AsString := Form5.Edit2.Text;
ADOTable1.Fields[4].AsString := Form5.Edit3.Text;
ADOTable1.Post;
Show_Tovar;
end;
end;
Доступ до полів таблиці Tovar компонента ADOTable1 здійснюється через масив-властивість Fields. Нумерація елементів масиву Fields починається з 0.
Елемент масиву ADOTable1.Fields[0] – це є унікальний ідентифікатор рядка товару ID_Tovar, що є типу лічильник. Цей елемент масиву не змінюється в базі даних (формується автоматично, збільшуючись щоразу на 1).
Елемент масиву ADOTable1.Fields[1] є ідентифікатором групи, до якої належить даний товар. Він заповнюється зі значення ідентифікатора групи ID_Group компонента ADOQuery1, що зв’язаний з таблицею Group.
Елементи масиву ADOTable1.Fields[2], ADOTable1.Fields[3], ADOTable1.Fields[4] є даними про товар що додається (назва, код та опис товару).
При заповненні значень полів важливо дотримуватись сумісності типів. Так, якщо поле ADOTable1.Fields[2] (назва товару) є рядком символів, то в програмі необхідно прямо вказувати його тип:
ADOTable1.Fields[2].AsInteger
Для додавання нового рядка в компоненті ADOTable1 є метод Append. Після заповнення значень кожного поля рядка (за виключенням поля рядка з індексом 0) внесені дані фіксуються з допомогою методу ADOTable1.Post.
18.2. Редагування товару
Редагування даних про товар здійснюється командою “Редагувати…” з меню “Товар“. Лістинг обробника події виклику команди “Редагувати…” має вигляд.
// Товар -> Редагувати
procedure TForm1.N9Click(Sender: TObject);
begin
// чи є запииси в таблиці товарів
if ADOTable1.RecordCount<=0 then exit;
// перед викликом заповнюємо поля форми Form6
Form6.Edit1.Text := ADOTable1.Fields[2].AsString;
Form6.Edit2.Text := ADOTable1.Fields[3].AsString;
Form6.Edit3.Text := ADOTable1.Fields[4].AsString;
if Form6.ShowModal=mrOk then
begin
ADOTable1.Edit; // переведення таблиці в режим редагування
ADOTable1.Fields[2].AsString := Form6.Edit1.Text;
ADOTable1.Fields[3].AsString := Form6.Edit2.Text;
ADOTable1.Fields[4].AsString := Form6.Edit3.Text;
ADOTable1.Post;
end;
end;
Форма редагування в програмі має ім’я Form6.
Перед викликом форми Form6 дані про виділений (активний) товар отримуються з полів ADOTable1.Fields. Ці дані копіюються у поля форми Form6.Edit1.Text (назва товару), Form6.Edit2.Text (код товару), Form6.Edit3.Text (опис товару). На момент виклику команди поля ADOTable1.Fields (таблиця Tovar) містять значення виділеного в DBGrid2 запису.
Після виклику форми і вибору користувачем підтвердження всі внесені зміни заносяться в таблицю бази даних через ADOTable1.Fields. Переведення таблиці в режим редагування здійснюється методом ADOTable1.Edit. Фіксування даних в таблиці бази даних здійснюється методом ADOTable1.Post.
18.3. Видалення товару
Видалення товару з даної групи здійснюється командою “Видалити” з меню “Товар“.
Лістинг обробника події видалення товару має такий вигляд.
// Товар -> Видалити
procedure TForm1.N10Click(Sender: TObject);
begin
if ADOTable1.RecordCount<=0 then exit;
if MessageDlg('Ви дійсно хочете видалити дану групу?', mtConfirmation, mbYes,mbNo],0,mbYes)=mrYes then
ADOTable1.Delete;
end;
Для видалення товару викликається метод ADOTable1.Delete.
19. Команди меню “Поступлення”
В меню “Поступлення” міститься три команди:
- додавання нового поступлення (команда “Додати…“);
- редагування поточного поступлення (команда “Редагувати…“);
- видалення поступлення (команда “Видалити“).
З поступленнями товарів у програмі зв’язана таблиця Postupl бази даних. Для доступу до записів таблиці Postupl в базі даних використовується компонент ADOTable2. Через цей компонент будуть виконуватись усі операції з таблицею Postupl. Автоматично усі зміни відображатимуться у компоненті DBGrid3, що зв’язаний з ADOTable2 (див. схему в п.9.1).
19.1. Додавання нового поступлення
Вікно, що викликається при додаванні нового поступлення, було сформоване в п. 15.6. Форма, що відповідає вікну додавання нового поступлення, має ім’я Form8.
Обробник події додавання нового поступлення у програмі має наступний вигляд.
// Поступлення -> Додати...
procedure TForm1.N12Click(Sender: TObject);
var
id_tovar:integer;
begin
// заповнили поле поточного курсу грошової одиниці
Form8.Edit2.Text :=
FloatToStrF(ADOTable2.FieldByName('Exchange').AsFloat, ffFixed, 8, 2);
if Form8.ShowModal = mrOk then
begin
id_tovar := ADOTable1.Fields[0].AsInteger;
ADOTable2.Append;
ADOTable2.Fields[1].AsInteger := id_tovar;
ADOTable2.Fields[2].AsDateTime := Form8.DateTimePicker1.DateTime;
ADOTable2.Fields[3].AsFloat := StrToFloat(Form8.Edit1.Text);
ADOTable2.Fields[4].AsFloat := StrToFloat(Form8.Edit2.Text);
ADOTable2.Fields[5].AsFloat := StrToFloat(Form8.Edit3.Text);
ADOTable2.Fields[6].AsInteger := StrToInt(Form8.Edit4.Text);
ADOTable2.Post;
Calc_Postupl_Row(ADOTable2.RecNo); // перерехунок рядка поступлення
Calc_Tovar_Row(ADOTable1.RecNo); // перерахунок рядка товару
end;
end;
19.2. Редагування поступлення
Вікно редагування поступлення було описано в п. 15.7. Доступ до форми редагування виділеного поступлення здійснюється через ім’я Form9.
Лістинг обробника події редагування поступлення має вигляд.
// редагування поступлення
procedure TForm1.N13Click(Sender: TObject);
var
old_rec:word;
begin
// якщо поступлень немає, то вихід
if ADOTable2.RecordCount<=0 then exit;
Form9.DateTimePicker1.Date := ADOTable2.FieldByName('Date').AsDateTime;
Form9.Edit1.Text := FloatToStr(ADOTable2.FieldByName('Prise_zak').AsFloat);
Form9.Edit2.Text := FloatToStr(ADOTable2.FieldByName('Exchange').AsFloat);
Form9.Edit3.Text := FloatToStr(ADOTable2.FieldByName('Price_rek').AsFloat);
Form9.Edit4.Text := FloatToStr(ADOTable2.FieldByName('Count').AsFloat);
if Form9.ShowModal = mrOk then
begin
old_rec := ADOTable2.RecNo; // запам'ятали номер
ADOTable2.Edit;
ADOTable2.FieldByName('Date').AsDateTime := Form9.DateTimePicker1.Date;
ADOTable2.FieldByName('Prise_zak').AsFloat := StrToFloat(Form9.Edit1.Text);
ADOTable2.FieldByName('Exchange').AsFloat := StrToFloat(Form9.Edit2.Text);
ADOTable2.FieldByName('Price_rek').AsFloat := StrToFloat(Form9.Edit3.Text);
ADOTable2.FieldByName('Count').AsInteger := StrToInt(Form9.Edit4.Text);
ADOTable2.Post;
Calc_Postupl_Row(ADOTable2.RecNo);
Calc_Tovar_Row(ADOTable1.RecNo);
ADOTable2.RecNo:=old_rec;
end;
end;
Додаткова змінна old_rec призначена для запам’ятовування старої позиції під час редагування. Значення порядкового номеру виділеного рядка (запису) бази даних отримується з властивості ADOTable2.RecNo.
У цій процедурі доступ до полів бази даних здійснюється з допомогою виклику методу FieldByName компонента ADOTable2. Параметром входу в процедуру FieldByName є рядок назви поля, в яке вноситься інформація. Наприклад, для доступу до поля ‘Exchange‘ таблиці Postupl, яке має дійсний тип даних (дані з плаваючою комою), потрібно вказати такий рядок:
ADOTable2.FieldByName('Exchange').AsFloat
Це є ще один спосіб доступу до виділеного рядка (запису) заданого поля бази даних. У попередніх процедурах ми використовували доступ шляхом виклику властивості ADOTable2.Fields[i], де і – порядковий номер поля. Відлік номерів полів починається з 0.
19.3. Видалення поступлення
Програмний код обробника події видалення поступлення має вигляд.
// Поступлення -> Видалити
procedure TForm1.N14Click(Sender: TObject);
begin
if ADOTable2.RecordCount<=0 then exit;
if MessageDlg('Ви дійсно хочете видалити дане поступлення?',mtConfirmation,[mbYes,mbNo],0,mbYes)=mrYes then
begin
ADOTable2.Delete;
Calc_Tovar_Row(ADOTable1.RecNo); // перерахунок рядка товару
end;
end;
20. Встановлення курсу валют
В умові задачі стоїть вимога забезпечення врахування плаваючого курсу валют при проведенні реалізації товару. Для забезпечення цього в програмі внесено додаткові команди, а в таблицях бази даних введено спеціальні поля.
20.1. Зміна поточного курсу
Для встановлення курсу валют потрібно викликати команду “Змінити…” з меню “Курс валют“. Форма вікна задавання поточного курсу основної валюти була спроектована в п. 15.1. У програмі доступ до форми вікна здійснюється через об’єкт-змінну з іменем Form2.
Обробник події, що забезпечує виведення форми Form2 має вигляд.
// Курс валют -> Змінити...
procedure TForm1.N2Click(Sender: TObject);
var
old_value:real;
begin
//
old_value := StrToFloat(Form2.Edit1.Text);
if Form2.ShowModal = mrNo then
Form2.Edit1.Text := FloatToStrF(old_value, ffFixed, 8, 2);
end;
Зміна значення курсу грошової одиниці можлива, якщо у вікні Form2 користувач її підтвердить. В іншому випадку повернеться попереднє значення. У програмному коді попереднє значення курсу грошової одиниці попередньо запам’ятовується в змінній old_value.
20.2. Зміна активізації головної форми
Зробимо так, щоб при першому завантаженні програми (перед початком роботи) користувач вводив поточний курс грошової одиниці, з яким будуть проводитись фінансові операції з товарами.
Для цього в подію активізації основної форми OnActivate помістимо відповідні фрагменти коду. Після внесених змін обробник події активізації форми Form1 має вигляд.
procedure TForm1.FormActivate(Sender: TObject);
begin
// задаємо поточний курс валют
if Form2.ShowModal=mrNo then
Form2.Edit1.Text := '1'
else
if Form2.Edit1.Text = '' then
Form2.Edit1.Text := '1';
// Заповнюємо розрахункові поля таблиць
Calc_Realiz;
Calc_Postupl;
Calc_Tovar;
// відображення усіх таблиць
Show_Tovar;
Show_Postupl;
Show_Realiz;
end;
21. Команди меню “Реалізація“
Меню “Реалізація” містить команди, що відносяться до реалізації товару:
- “Додати…” – додає нову реалізацію (продаж) товару;
- “Редагувати…” – змінює дані раніше внесеної реалізації;
- “Видалити” – видаляє рядок реалізації, що був внесений раніше.
Реалізація товарів у базі даних відображається в таблиці Realiz. Таблиця Realiz бази даних зв’язана з програмою з допомогою компонента ADOTable3. Таким чином, корегуючи значення записів компонента ADOTable3 можна вносити зміни в таблицю Realiz бази даних.
21.1. Додавання нової реалізації
Додавання нової реалізації викликається командою “Додати…” з меню “Реалізація“. Форма відповідного вікна була спроектована в п. 15.8.
Обробник події додавання нової реалізації має вигляд.
// Реалізація -> Додати...
procedure TForm1.N16Click(Sender: TObject);
var
id_postupl:word;
price:real;
ex1, ex2:real;
price_rek:real;
begin
// розраховуємо ціну реалізації
ex1 := StrToFloat(Form2.Edit1.Text); // поточний курс
ex2 := ADOTable2.FieldByName('Exchange').AsFloat; // курс поступлення
price_rek := ADOTable2.FieldByName('Price_rek').AsFloat; // ціна рекомендована
price := ex1/ex2*price_rek; // ціна реалізації
// заповнюємо поля - підказки
Form7.Edit1.Text := FloatToStrF(price,ffFixed,8,2); // ціна реалізації
Form7.Edit3.Text := Form2.Edit1.Text; // поточний курс
Form7.Edit4.Text := FloatToStrF(ex2, ffFixed, 8, 2); // курс поступлення
if Form7.ShowModal = mrOk then
begin
id_postupl := ADOTable2.Fields[0].AsInteger;
ADOTable3.Append;
ADOTable3.Fields[1].AsInteger := id_postupl;
ADOTable3.Fields[2].AsDateTime := Form7.DateTimePicker1.DateTime;
ADOTable3.Fields[3].AsFloat := StrToFloat(Form7.Edit1.Text);
ADOTable3.Fields[4].AsInteger := StrToInt(Form7.Edit2.Text);
ADOTable3.Fields[5].AsFloat := ADOTable3.Fields[3].AsFloat * ADOTable3.Fields[4].AsInteger;
ADOTable3.Post;
Calc_Postupl_Row(ADOTable2.RecNo);
Calc_Tovar_Row(ADOTable1.RecNo);
end;
end;
21.2. Редагування реалізації
Редагування рядка реалізації викликається командою “Редагувати…” меню “Реалізація“.
Форма вікна, що відкривається для редагування даних реалізації товару, має ім’я Form10 (див. п. 15.9). Програмний код обробника події редагування одного рядка реалізації наступний.
// Реалізація - "Редагувати..."
procedure TForm1.N17Click(Sender: TObject);
var
id_postupl:word;
price:real;
ex:real;
price_rek:real;
begin
if ADOTable3.RecordCount<=0 then exit;
// розраховуємо ціну реалізації
ex := ADOTable2.FieldByName('Exchange').AsFloat; // курс поступлення
// заповнюємо поля - підказки
Form10.DateTimePicker1.DateTime := ADOTable3.FieldByName('Date').AsDateTime;
// ціна реалізації
Form10.Edit1.Text := FloatToStrF(ADOTable3.FieldByName('Price_Real').AsFloat, ffFixed, 8, 2);
// кількість
Form10.Edit2.Text := IntToStr(ADOTable3.FieldByName('Count').AsInteger);
Form10.Edit3.Text := Form2.Edit1.Text; // поточний курс
Form10.Edit4.Text := FloatToStrF(ex, ffFixed, 8, 2); // курс поступлення
if Form10.ShowModal=mrOk then
begin
id_postupl := ADOTable2.Fields[0].AsInteger;
ADOTable3.Edit;
ADOTable3.Fields[1].AsInteger := id_postupl;
ADOTable3.Fields[2].AsDateTime := Form10.DateTimePicker1.DateTime;
ADOTable3.Fields[3].AsFloat := StrToFloat(Form10.Edit1.Text);
ADOTable3.Fields[4].AsInteger := StrToInt(Form10.Edit2.Text);
ADOTable3.Fields[5].AsFloat := ADOTable3.Fields[3].AsFloat *
ADOTable3.Fields[4].AsInteger;
ADOTable3.Post;
Calc_Postupl_Row(ADOTable2.RecNo);
Calc_Tovar_Row(ADOTable1.RecNo);
end;
end;
21.3. Видалення рядка реалізації
Лістинг обробника події, що викликається командою “Видалити” меню “Реалізація“.
// Реалізація -> Видалити
procedure TForm1.N18Click(Sender: TObject);
var
p,t:word;
begin
if ADOTable3.RecordCount<=0 then exit;
if MessageDlg('Ви дійсно хочете видалити дану реалізацію?', mtConfirmation,[mbYes,mbNo],0,mbYes)=mrYes then
begin
ADOTable3.Delete;
ADOTable3.First;
p:=ADOTable2.RecNo;
t:=ADOTable1.RecNo;
Calc_Postupl_Row(ADOTable2.RecNo);
Calc_Tovar_Row(ADOTable1.RecNo);
ADOTable1.RecNo := t;
ADOTable2.RecNo := p;
end;
end;
22. Команда “Вихід“
Останньою командою, що ще не була розглянута є команда закриття програми.
Обробник події, що викликається при виборі команди меню “Вихід” має такий вигляд.
// Вихід
procedure TForm1.N20Click(Sender: TObject);
begin
Close;
end;