Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
Министерство образования и науки Республики Дагестан
ГПОБУ "Республиканский инженерный колледж имени С. Орджоникидзе"
Методическая разработкапо учебной практике МДК 02.02
«Технология разработки и защиты баз данных»
Руководитель практики:
Рамазанова М. Г.
г. Каспийск, 2014
Лабораторная работа № 1Создание базы в MS Access
Напишем программу учета продуктов на складе по средней цене прихода. База данных будет включать в себя следующие возможности:
1. Справочник продуктов, справочник групп продуктов, справочник поставщиков, справочник единиц измерения.
2. Форму прихода продуктов на склад.3. Форму расхода продуктов.4. Возможность во всех формах, которые описаны выше добавлять,
редактировать и удалять записи.5. Форму просмотра продуктов на складе.6. Печать данных прихода, расхода и состояния склада.А для этого нам нужно научиться работать с базами данных. Начнем работу с
создания базы в MS Access 2007. Создадим базу с названием storage.mdb, для этого запустим MSAcceсss 2007.
Выбираем, новая база данных и вводим имя файла storage.
Выбираем путь для сохранения базы данных и тип файла Базы данных Microsoft Office 2002-2003, жмем ОК, а затем
нажимаем кнопку Создать и видим следующее окно.
Теперь создадим таблицу storage, для этого щелкнем правой кнопкой мыши на вкладке Таблица1 и выберем Конструктор.
Затем вводим имя таблицы storage и жмем ОК.
Далее создаем следующие поля таблицы: id (счетчик) – нужно задать как ключевое, id_product (тип данных – числовой, в свойствах поля- размер поля- Длинное
целое) – код продукта, id_product_group (тип данных – числовой, в свойствах поля- размер поля-
Длинное целое) – код группы продуктов, quantity (тип данных – денежный, в свойствах поля- формат поля- основной,
число десятичных знаков – 3) – количество, price (тип данных – денежный, в свойствах поля- формат поля- основной,
число десятичных знаков – 4) – цена, id_prihod (тип данных – числовой, в свойствах поля – размер поля – Длинное
целое) – код прихода, date_realization (тип данных – Дата/время) – дата реализации, id_ed_izmer (тип данных – числовой, в свойствах поля – размер поля –
Длинное целое) – код единицы измерения.затем нажимаем на крестик и подтверждаем сохранение.
Далее переходим на вкладку создание, выбираем конструктор таблиц и создаем еще пять таблиц.
1. Таблица product_group, которая содержит следующие поля: id (счетчик) – нужно задать как ключевое, product_name (текстовый) – наименование категории продукта.
Данная таблица будет справочником по категориям продуктов.
2. Таблица products, которая содержит следующие поля: id (счетчик) – нужно задать как ключевое, product_name (текстовый) – наименование продукта, id_product_group (тип данных – числовой, в свойствах поля- размер поля-
Длинное целое) – код группы продуктов, time_hraneniya (тип данных – числовой, в свойствах поля- размер поля- Длинное
целое) – время хранения продукта, id_ed_izmer (тип данных – числовой, в свойствах поля- размер поля- Длинное
целое) – код единицы измерения по умолчанию.Эта таблица будет справочником продуктов.
3. Таблица prihod, которая содержит следующие поля: id (счетчик) – нужно задать как ключевое, number_docum (текстовый, в свойствах поля – размер поля – 20) – номер
накладной id_postav_ik (тип данных – числовой, в свойствах поля – размер поля – Длинное
целое) – код поставщика, date_prihoda (тип данных – Дата/время) – дата прихода, sum (тип данных – денежный, в свойствах поля – формат поля – основной,
число десятичных знаков – 4) – сумма прихода.Таблица прихода продуктов на склад.
4. Таблица ed_izmer, которая содержит следующие поля: id (счетчик) – нужно задать как ключевое, ed_name (текстовый, в свойствах поля – размер поля – 50) – наименование
единицы измерения.Таблица справочник по единицам измерения.
5. Таблица postav_ik, которая содержит следующие поля: id (счетчик) – нужно задать как ключевое, postav_ik_name (текстовый, в свойствах поля – размер поля – 255) –
наименование организации поставщика, phone (текстовый, в свойствах поля – размер поля – 50) – телефон организации, address (текстовый, в свойствах поля – размер поля – 255) – адрес организации, director (текстовый, в свойствах поля – размер поля – 255) – руководитель
организации.Таблица будет справочником поставщиков.
Лабораторная работа № 2Создание главной формы программы склад.
Для того, чтобы создать главную форму для нашего склада необходимо создать подключение, к базе, используя компонент TADOConnection.
Запускаем Delphi, выбираем File -> New-> VCL Forms Application - Delphi
и получаем на экране
Сохраните ваш проект в нужную папку (sclad) и назовите файл (модуля pas) как general, а файл проекта storage. Для этого выбираем File->Save ProjectAs…
Далее размещаем на форме компонент TADOConnection вкладки dbGo (старое название ADO).
Перед настройкой подключения к базе, необходимо скопировать файл базы данных (storage.mdb), созданный на работе в папку с проектом.
Выделяем компонент TADOConnection и в свойстве LoginPromt ставим на False. Это делаем для того, чтобы при подключении к БД пароль у нас не запрашивался, дальше в свойстве ConnectionString нажимаем на кнопку с «…» и видим:
В окне нажмите на кнопку «Build…» и появится следующее окно:
Выбирите провайдера, а именно Microsoft Jet 4.0 OLE DB Provaider и нажимаем кнопку «Далее».
В данном окне укажите путь к вашей БД и имя пользователя по умолчанию Admin , нажмите кнопку «Ок». Если ваша БД находится в корневом каталоге с программой, то в данном поле достаточно указать ее имя с расширением, примерно так storage.mdb.
В свойстве компонента TADOConnection – Mode выберите из выпадающего списка cmShareDenyNone, а свойство TADOConnection – Connected ставим True. Все подключение к базе активировано.
Лабораторная работа № 3Создание главной формы программы склад.
Сделайте форму главной MDI формой, для этого в инспекторе объектов в свойствах Form1 свойство FormStyle установите в fsMDIForm.
Добавьте на форму компонент TMainMenu из вкладки Standard.
Щелкнем дважды мышкой на компоненте MainMenu1 и увидим окно для создания меню.
В свойстве Caption инспектора объектов задаем следующие пункты меню:Справочники
Единицы измерения Категории продуктов Продукты Поставщики
Склад Приход Расход Просмотр склада
Заканчиваем создание меню и жмем на крестик.Далее из панели компонентов dbGo (ADO) размещаем на форме четыре
компонента TADOTable, к ним мы подключим наши справочники из базы данных, но для начала мы их переименуем
ADOTable1 – table_ed_izmer,ADOTable2 – table_product_group,ADOTable3 – table_products,ADOTable4 – table_postav_ik.
Для этого в инспекторе объектов ADOTable1 в свойство Name записываем table_ed_izmer и так делаем для ADOTable2, ADOTable3, ADOTable4. Должно получиться следующее:
Подключим наши таблицы к компоненту ADOConnection1 и к одноименным таблицам нашей БД.
Для этого в инспекторе объектов: для таблицы table_ed_izmer (TADOTable) свойства Connection
устанавливаем -> ADOConnection1, TableName-> ed_izmer, Active-> True; для таблицы table_product_group (TADOTable) свойства Connection устан
авливаем -> ADOConnection1, TableName-> product_group, Active-> True; для таблицы table_products (TADOTable) свойства Connection устанавлив
аем -> ADOConnection1, TableName-> products, Active-> True; для таблицы table_postav_ik (TADOTable) свойства Connection устанавли
ваем -> ADOConnection1, TableName-> postav_ik , Active-> True; Свойство Active -> True устанавливайте в последнюю очередь.
В последнюю очередь изменим в инспекторе объектов свойство Caption главной формы (Form1) на Склад, а свойство Name ->на Form_general.
А чтобы форма разворачивалась на весь экран Align -> alClient.
Лабораторная работа № 4Создание подчиненных форм для справочников программы склад
Создадим форму для справочника единицы измерения нашего склада. Запускает наш проект, и создаем новую форму File->New->Form –Delphi.
В инспекторе объектов устанавливаем следующие свойства для новой формы: Caption -> Единицы измерения; FormStyle -> fsMDIChild; Name -> Form_ed_izmer;
Сохраните модуль с именем ed_izmer.Пропишем Uses general после раздела implementation в программном модуле
unit ed_izmer как показано на рисунке.
А программном модуле unit general главной формы пропишем Uses ed_izmer.
Это делается для того, чтобы установить связь между формами, иначе нельзя будет обращаться из одной формы к компонентам другой формы.
Далее размещаем на форме следующие компоненты три кнопки TButton из вкладки Standart.
В инспекторе объектов для Button1 устанавливаем свойство Caption -> Новая запись; для Button2 устанавливаем свойство Caption -> Удалить запись; для Button3 устанавливаем свойство Caption -> Закрыть;
Из вкладки Data Access помещаем на форму компонент TDataSource. В инспекторе объектов для него устанавливаем следующие свойства:
DataSet -> Form_general.table_ed_izmer; Name -> ed_izmer.
А из вкладки Data Controls помещаем на форму компонент TDBGrid. В инспекторе объектов для него устанавливаем следующие свойства:DataSource -> ed_izmer.
Если вы все правильно сделали, то должны на форме увидеть следующее:
Если поля таблицы не отображаются в DBGrid,возможно у вас отключено (False) свойство Active главной форме в инспекторе объектов компонента table_ed_izmer (TADOtable), установите Active -> True.
Сейчас мы переименуем поля нашей таблице. Для этого перейдем на главную форму проекта.
Выберем компонент table_ed_izmer (ADOTable) и в структуре (Structure) -> ed_izmer -> Fields -> щелкнем правой кнопкой мыши и выберем Add all fields.
У вас должно получиться следующее:
Далее выбираем поле id и в инспекторе объектов устанавливаем у него свойство Visible->False, затем выбираем поле ed_name и в инспекторе объектов устанавливаем у него свойства DisplayLabel -> Единица измерения и DisplayWidth -> 30;
После этого видим для формы «Единицы измерения»:
Теперь пишем обработчики событий для кнопок. Щелкнем дважды мышкой по кнопке «Новая запись» и пишем следующий код:
procedure TForm_ed_izmer.Button1Click(Sender: TObject);begin//новая записьform_general.table_ed_izmer.Append;dbgrid1.SetFocusend;
Щелкнем дважды мышкой по кнопке «Удалить запись» и пишем следующий код:procedure TForm_ed_izmer.Button2Click(Sender: TObject);//удаление записиbegin//если записи отсутствуют то выводим сообщение, иначе удаляем запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin
if (MessageBox(Handle, 'Удаление записей может привести к нарушению работы всей базы данных. Удалить запись?', 'Внимание !!!', MB_YESNO)= IDYES) then form_general.table_ed_izmer.Delete end else ShowMessage('Нет записей для удаления');end;
Щелкнем дважды мышкой по кнопке «Закрыть» и пишем следующий код:procedure TForm_ed_izmer.Button3Click(Sender: TObject);begin//закрытие формыClose;end;
В инспекторе объектов для Form_ed_izmer событие FormActivate пишем:
procedure TForm_ed_izmer.FormActivate(Sender: TObject);begin//установка фокуса при активации формыdbgrid1.SetFocus;end;
В инспекторе объектов для Form_ed_izmer событие FormClose пишем:procedure TForm_ed_izmer.FormClose(Sender: TObject; var Action: TCloseAction);begin//процедура закрытия формы Action:=cafree;end;
В инспекторе объектов для Form_ed_izmer событие FormCloseQuery пишем:procedure TForm_ed_izmer.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
//проверка на наличие пустых записей перед закрытием, если такие записи найдены то отменяем //закрытие формыbegin if dbgrid1.DataSource.DataSet.RecordCount<>0 then beginif not (form_general.table_ed_izmer.Locate('ed_name', '', [loCaseInsensitive,loPartialKey])) then begin form_general.table_ed_izmer.edit; form_general.table_ed_izmer.post; end else begin ShowMessage('У Вас есть не заполненные записи');CanClose:=false;dbgrid1.SetFocus;end; end; end;
Сейчас сделаем запуск справочника «Единиц измерения» из главной формы. Для этого выбираем в меню Project -> Options…
и видим следующее окно:
Выбираем Forms и перемещаем Form_ed_izmer из Auto-create forms в Avalable forms.
Переходим на главную форму, щелкаем мышкой по компоненту MainMenu1, а затем по пункту Единицы измерения
И пишем следующий обработчик события:procedure TForm_general.N2Click(Sender: TObject);begin f:=0;//проверяем, активна ли наша формаif ActiveMDIChild.Caption<>'Единицы измерения' then begin//если нет то ищем ее среди неактивных и если находим, то показываем ееfor i:=0 to form_general.MDIChildCount-1 doif form_general.MDIChildren[i].Caption='Единицы измерения' then beginMDIChildren[i].Show;f:=1;end; end else f:=1;//если форма еще не создана, то создаем ееif f<>1 then Tform_ed_izmer.Create(Application);end;
Переменные f и I описываем в разделе varVar Form_general: TForm_general; f,i:integer; //f:=1 если подчиненная форма уже запущена и f:=0 если нет.
Вот и все готово, запускаем проект и заполняем справочник данными, например, так:
Лабораторная работа № 5Создание подчиненных форм для справочников программы склад (продолжение).
Создадим форму для справочника «Категории продуктов» и «Поставщики» нашего склада. Процесс создания данных форм аналогичен созданию формы для справочника «Единицы измерения», смотри предыдущий урок. Поэтому описывать буду достаточно кратко.
Создаем новую форму File->New->Form –Delphi. В инспекторе объектов устанавливаем следующие свойства для новой формы:
Caption -> Категории продуктов;FormStyle -> fsMDIChild;Name -> Form_product_group;
Сохраните модуль с именем product_group.Пропишем Uses general; после раздела implementation в программном
модуле unit product_group как показано на рисунке.
А программном модуле unit general главной формы пропишем Uses ed_izmer, product_group;
Далее размещаем на форме следующие компоненты.Три кнопки TButton из вкладки Standart – в инспекторе объектов
для Button1 устанавливаем свойство Caption -> Новая запись; для Button2 устанавливаем свойство Caption -> Удалить запись; для Button3 устанавливаем свойство Caption -> Закрыть.
Из вкладки Data Access помещаем на форму компонент TDataSource – в инспекторе объектов для него устанавливаем следующие свойства: DataSet -> Form_general.table_product_group; Name -> product_group.
А из вкладки Data Controls помещаем на форму компонент TDBGrid – в инспекторе объектов для него устанавливаем следующие свойства: DataSource -> product_group.
Если поля таблицы не отображаются в DBGrid,возможно у вас отключено (False) свойство Active главной форме в инспекторе объектов компонента table_product_group(TADOtable), установите Active -> True.
Теперь переименуем поля нашей таблице. Для этого перейдем на главную форму проекта.
Выберем компонент table_product_group (ADOTable) и в структуре (Structure) -> product_group -> Fields -> щелкнем правой кнопкой мыши и выберем Add all fields.
Далее выбираем поле id и в инспекторе объектов устанавливаем у него свойство Visible->False, затем выбираем поле product_name и в инспекторе объектов устанавливаем у него свойства DisplayLabel -> Категория продуктов; DisplayWidth -> 30.
После этого у вас должна получится такая форма «Категория продуктов».
Теперь напишем обработчики событий для кнопок. Для этого щелкнем дважды мышкой по кнопке «Новая запись» и пишем следующий код:
procedure TForm_product_group.Button1Click(Sender: TObject);begin//новая записьform_general.table_product_group.Append;dbgrid1.SetFocus;end;
Щелкнем дважды мышкой по кнопке «Удалить запись» и напишите следующий код:
procedure TForm_product_group.Button2Click(Sender: TObject); //удаление записиbegin//если записи отсутствуют то выводим сообщение, иначе удаляем запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удаление записей может привести к нарушению работы всей базы данных. Удалить запись?', 'Внимание !!!', MB_YESNO)= IDYES) then form_general.table_product_group.Delete end else ShowMessage('Нет записей для удаления'); end;
Щелкнем дважды мышкой по кнопке «Закрыть» и напишите следующий код:procedure TForm_product_group.Button3Click(Sender: TObject);begin//закрытие формыClose;end;
В инспекторе объектов для Form_product_group событие FormActivate напишите:
procedure TForm_product_group.FormActivate(Sender: TObject);begin//установка фокуса при активации формыdbgrid1.SetFocus;end;В инспекторе объектов для Form_product_group событие FormClose напишите:procedure TForm_product_group.FormClose(Sender: TObject; var Action: TCloseAction);begin//процедура закрытия формы Action:=cafree;end;
В инспекторе объектов для Form_product_group событие FormCloseQuery напишите:
procedure TForm_product_group.FormCloseQuery(Sender: TObject; var CanClose: Boolean);//проверка на наличие пустых записей перед закрытием, если такие записи найдены то отменяем закрытие формыbegin if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if not (form_general.table_product_group.Locate('product_name','',[loCaseInsensitive,loPartialKey])) then begin form_general.table_product_group.edit;form_general.table_product_group.post; end
else begin ShowMessage('У Вас есть не заполненные записи'); CanClose:=false;dbgrid1.SetFocus;end; end;end;
Сделайте запуск справочника «Категории продуктов» из главной формы. Для этого выбирите в меню Project -> Options…
Выбирите Forms и перемещаем Form_product_group из Auto-create forms в Avalable forms.
Перейдите на главную форму, щелкните мышкой по компоненту MainMenu1, а затем по пункту Категории продуктов
Напишите следующий обработчик события:procedure TForm_general.N3Click(Sender: TObject);beginf:=0;//проверяем, активна ли наша формаif ActiveMDIChild.Caption<>'Категории продуктов' then begin//если нет то ищем ее среди неактивных и если находим, то показываем ееfor i:=0 to form_general.MDIChildCount-1 doif form_general.MDIChildren[i].Caption='Категории продуктов' then begin MDIChildren[i].Show;f:=1;end;end else f:=1;//если форма еще не создана, то создаем ееif f<>1 then Tform_product_group.Create(Application);end;Вот и все готово, запускаем проект и заполняем справочник данными,
например, так:
Создадим форму для справочника «Поставщики»Создадим новую форму File->New->Form – Delphi – в инспекторе
объектов устанавливаем следующие свойства для новой формы: Caption -> Поставщики; FormStyle -> fsMDIChild; Name -> Form_postav_ik;
Сохраните модуль с именем postav_ik.
Пропишем Uses general; после раздела implementation в программном модуле unit postav_ik,а в программном модуле unit general главной формы пропишем Uses ed_izmer,product_group, postav_ik;
Разместите на форме компоненты как показано на рисунке:
Далее все делаем аналогично, как для предыдущего справочника. А я приведу лишь код для обработки событий.
Для кнопки «Новая запись» введите код:procedure TForm_postav_ik.Button1Click(Sender: TObject);begin //новая записьform_general.table_postav_ik.Append;dbgrid1.SetFocusend;
Для кнопки «Удалить запись» введите код: procedure TForm_postav_ik.Button2Click(Sender: TObject);//удаление записиbegin//если записи отсутствуют то выводим сообщение, иначе удаляем запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удаление записей может привести к нарушению работы всей базы данных. Удалить запись?', 'Внимание !!!', MB_YESNO)= IDYES) then form_general.table_postav_ik.Delete end else ShowMessage('Нет записей для удаления');end;
Для кнопки «Закрыть»procedure TForm_postav_ik.Button3Click(Sender: TObject);begin//закрытие формы
Close;end;
Для события FormActivate формы Form_postav_ikprocedure TForm_postav_ik.FormActivate(Sender: TObject);begin//установка фокуса при активации формыdbgrid1.SetFocus;end;
Для события FormClose формы Form_postav_ik procedure TForm_postav_ik.FormClose(Sender: TObject; var Action: TCloseAction);begin//процедура закрытия формы Action:=cafree;end;
Для события FormCloseQuery формы Form_postav_ik procedure TForm_postav_ik.FormCloseQuery(Sender: TObject; var CanClose: Boolean);//проверка на наличие пустых записей перед закрытием, если такие записи найдены то отменяем закрытие формыbegin if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if not (form_general.table_postav_ik.Locate('postav_ik_name','',[loCaseInsensitive,loPartialKey])) then begin form_general.table_postav_ik.edit;form_general.table_postav_ik.post; end else begin ShowMessage('У Вас есть не заполненные записи');CanClose:=false;dbgrid1.SetFocus;end; end;end;
Для главной формы Form_general при нажатии на кнопку Категории продуктов выпадающего меню
procedure TForm_general.N5Click(Sender: TObject);beginf:=0;//проверяем, активна ли наша формаif ActiveMDIChild.Caption<>'Поставщики' then begin//если нет то ищем ее среди неактивных и если находим, то показываем ееfor i:=0 to form_general.MDIChildCount-1 doif form_general.MDIChildren[i].Caption='Поставщики' then begin MDIChildren[i].Show;f:=1;end;end else f:=1;//если форма еще не создана, то создаем ееif f<>1 then Tform_postav_ik.Create(Application);end;
Запускаем проект и заполняем справочник данными.
Лабораторная работа № 6Создание подчиненных форм для справочников программы склад. Создание
справочника «Продукты» с использованием полей Lookup.
Создадим форму для справочника «Продукты» нашего склада c использованием поле Lookup из других таблиц.
Процесс создания данных форм аналогичен созданию формы для справочника «Единицы измерения», смотри предыдущие уроки. Поэтому описывать буду достаточно кратко.
Создаем новую форму File->New->Form –DelphiВ инспекторе объектов устанавливаем следующие свойства для новой формы:
Caption -> Продукты; FormStyle -> fsMDIChild; Name -> Form_products;
Сохраните модуль с именем products.Пропишем Uses
general; после раздела implementation в программном модуле unit products.А программном модуле unit general главной формы пропишем Uses ed_izmer,
product_group, products;Далее размещаем на форме следующие компоненты:Три кнопки TButton из вкладки Standart – в инспекторе объектов
для Button1 устанавливаем свойство Caption -> Новая запись; для Button2 устанавливаем свойство Caption -> Удалить запись; для Button3 устанавливаем свойство Caption -> Закрыть.
Из вкладки Data Access помещаем на форму компонент TDataSource – в инспекторе объектов для него устанавливаем следующие свойства: DataSet -> Form_general.table_products; Name -> products.
А из вкладки Data Controls помещаем на форму компонент TDBGrid.В инспекторе объектов для него устанавливаем следующие свойства:
DataSource -> products.Если поля таблицы не отображаются в DBGrid,возможно у вас отключено
(False) свойство Active главной форме в инспекторе объектов компонента table_products (TADOtable),установите Active -> True.
Сейчас переименуем поля нашей таблице. Для этого перейдем на главную форму проекта. Выберем компонент table_products (ADOTable) и в структуре (Structure) -> products -> Fields -> щелкнем правой кнопкой мыши и выберем Add all fields.
Для полей id, id_product_group, id_ed_izmer в инспекторе объектов устанавливаем свойство Visible->False, затем выбираем поле product_name и в инспекторе объектов устанавливаем у него свойства DisplayLabel -> Продукт; DisplayWidth -> 30; затем выбираем поле time_hraneniya и в инспекторе объектов устанавливаем у него свойства DisplayLabel -> Время хранения; DisplayWidth -> 20.
Далее создаем выпадающее поле Lookup для просмотра данных из справочника «Категории продуктов». Для этого в структуре (Structure) -> products -> Fields -> щелкнем правой кнопкой мыши и выберем New field….
После этого видим:
В поле Name: пишем product_group; в поле Type: выбираем String; выбираем поле Lookup; в Key Fields:выбираем id_product_group; в Dataset: выбираем table_ product_group; в Lookup Keys: выбираем id; а в Result Field: выбираем product_ name жмем ОК
В инспекторе объектов для созданного поля свойство DisplyLabel-> Категория продукта, DisplyWidth-> 24 и перемещаем поле мышкой в позицию после поля product_name.
Далее создаем выпадающее поле Lookup для просмотра данных из справочника «Единицы измерения».
Для этого в структуре (Structure) -> products -> Fields -> щелкнем правой кнопкой мыши и выберем New field…. и заполняем, как показано на рисунке:
В поле Name: пишем ed_izmer; в поле Type: выбираем String; выбираем поле Lookup; в Key Fields:выбираем id_ed_izmer; в Dataset: выбираем table_ed_izmer; в Lookup Keys: выбираем id; а в Result Field: выбираем ed_name жмем ОК.
В инспекторе объектов для созданного поля свойство DisplyLabel-> Единица измерения, DisplyWidth-> 24 и перемещаем поле мышкой в позицию после поля product_group.
После этого видим для формы «Продукты»:
Теперь пишем обработчики событий для кнопок.Щелкнем дважды мышкой по кнопке «Новая запись» и пишем следующий код:
procedure TForm_products.Button1Click(Sender: TObject);begin //новая записьform_general.table_products.Append;
dbgrid1.SetFocusend;
Щелкнем дважды мышкой по кнопке «Удалить запись» и пишем следующий код:
procedure TForm_products.Button2Click(Sender: TObject);//удаление записиbegin//если записи отсутствуют то выводим сообщение, иначе удаляем запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удаление записей может привести к нарушению работы всей базы данных. Удалить запись?', 'Внимание !!!', MB_YESNO)= IDYES) then form_general.table_products.Delete end else ShowMessage('Нет записей для удаления');end;
Щелкнем дважды мышкой по кнопке «Закрыть» и пишем следующий код:procedure TForm_products.Button3Click(Sender: TObject);begin//закрытие формыClose;end;
В инспекторе объектов для Form_products событие FormActivate пишем:procedure TForm_products.FormActivate(Sender: TObject);begin//так как таблица продукты использует данные из таблиц единицы измерения и категории продуктов//то мы должны проверить заполнены они или нетif form_general.table_ed_izmer.RecordCount=0 then begin ShowMessage('У Вас не заполнен справочник "Единиц измерения". Для продолжения работы Вам необходимо заполнить справочник.');close;endelse beginif form_general.table_product_group.RecordCount=0 then begin ShowMessage('У Вас не заполнен справочник "Категории продуктов". Для продолжения работы Вам необходимо заполнить справочник.'); close;endelse begin//обновляем данныеform_general.table_ed_izmer.Refresh;form_general.table_product_group.Refresh;//установка фокуса при активации формыdbgrid1.SetFocus; end; end; end;
В инспекторе объектов для Form_products событие FormClose пишем:procedure TForm_products.FormClose(Sender: TObject; var Action: TCloseAction);begin//процедура закрытия формы
Action:=cafree;end;
В инспекторе объектов для Form_products событие FormCloseQuery пишем: procedure TForm_products.FormCloseQuery(Sender: TObject; var CanClose: Boolean);begin//проверка на наличие пустых записей перед закрытием, если такие записи найдены то отменяем закрытие //формы if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin //по полю продукт if (form_general.table_products.Locate('product_name','', [loCaseInsensitive,loPartialKey])) then begin ShowMessage('У Вас есть не заполненные записи в поле"Продукт"');CanClose:=false; dbgrid1.SetFocus;end else begin //по полю категория продукта if (form_general.table_products.Locate('id_product_group',null, [loCaseInsensitive,loPartialKey])) then begin ShowMessage('У Вас есть не заполненные записи в поле "Категория продукта"'); CanClose:=false;dbgrid1.SetFocus;end else begin //по полю единица измерения if (form_general.table_products.Locate('id_ed_izmer',null, [loCaseInsensitive,loPartialKey])) then begin ShowMessage('У Вас есть не заполненные записи в поле "Единицы измерения"'); CanClose:=false;dbgrid1.SetFocus;end else begin //по полю дата хранения if (form_general.table_products.Locate('time_hraneniya',null,[loCaseInsensitive,loPartialKey])) then begin ShowMessage('У Вас есть не заполненные записи в поле "Время хранения"');CanClose:=false;dbgrid1.SetFocus;end else begin form_general.table_products.edit;form_general.table_products.post; end; end; end; end; end; end;
Сделаем запуск справочника «Продуктов» из главной формы. Для этого выбираем в меню Project -> Options…
Выбираем Forms и перемещаем Form_products из Auto-create forms в Avalable forms.
Переходим на главную форму, щелкаем мышкой по компоненту MainMenu1, а затем по пункту Продукты
И пишем следующий обработчик события: procedure TForm_general.N4Click(Sender: TObject);beginf:=0;//проверяем, активна ли наша формаif ActiveMDIChild.Caption<>'Продукты' then begin//если нет то ищем ее среди неактивных и если находим, то показываем ее
for i:=0 to form_general.MDIChildCount-1 doif form_general.MDIChildren[i].Caption='Продукты' then begin MDIChildren[i].Show;f:=1;end;end else f:=1;//если форма еще не создана, то создаем ееif f<>1 then Tform_products.Create(Application);end;
Вот и все, запускаем проект и заполняем справочник данными.Но теперь возникает другая проблема, так наш справочник «Продуктов» связан
с другими справочниками, то при удалении из них данных возникнут проблемы и со справочником «Продуктов». Поэтому в справочниках «Категории продуктов» и «Единицы измерения», пред удаление записи мы должны проверить используется ли эта запись в справочнике «Продуктов» и если используется то запретить удаление.
Изменим процедуру удаления записи в справочнике «Категории продуктов»Щелкнем дважды мышкой по кнопке «Удалить запись» на форме «Категории
продуктов» и пишем следующий код:procedure TForm_product_group.Button2Click(Sender: TObject); //удаление записиbegin//если записи отсутствуют то выводим сообщение, иначе удаляем запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удаление записей может привести к нарушению работы всей базы данных. Удалить запись?', 'Внимание !!!', MB_YESNO)= IDYES) then if (form_general.table_products.Locate('id_product_group', form_general.table_product_group.FieldByName('id').Value, [loCaseInsensitive, loPartialKey])) then ShowMessage('Нельзя удалить данную категорию продуктов, так как она используется в справочнике продуктов.') else form_general.table_product_group.Delete end else ShowMessage('Нет записей для удаления');end;
Изменим процедуру удаления записи в справочнике «Единицы измерения»Щелкнем дважды мышкой по кнопке «Удалить запись» на форме «Единицы
измерения» и пишем следующий код:procedure TForm_ed_izmer.Button2Click(Sender: TObject);//удаление записиbegin//если записи отсутствуют то выводим сообщение, иначе удаляем запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удаление записей может привести к нарушению работы всей базы данных. Удалить запись?', 'Внимание !!!', MB_YESNO)= IDYES) then if (form_general.table_products.Locate('id_ed_izmer',
form_general.table_ed_izmer.FieldByName('id').Value, [loCaseInsensitive, loPartialKey])) then ShowMessage('Нельзя удалить данную единицу измерения, так как она используется в справочнике продуктов.') else form_general.table_ed_izmer.Delete end else ShowMessage('Нет записей для удаления');end;
Лабораторная работа № 7Создание формы прихода продуктов на склад.
Создадим формы прихода продуктов на склад. Приход продуктов будет состоять из трех форм. В первой мы будем хранить данные о приходе. Во второй, данные о продуктах для каждого прихода. Третья – форма для выбора продуктов.
Приступим к созданию первой формы.Создаем новую форму File->New->Form –Delphi – в инспекторе объектов
устанавливаем следующие свойства для новой формы Caption -> Приход; FormStyle -> fsMDIChild; Name -> Form_prihod. Сохраните модуль с именем prihod.
Пропишем Uses general; после раздела implementation в программном модуле unit prihod. В программном модуле unit general главной формы пропишем Uses ed_izmer, product_group, products, prihod.
Далее размещаем на форме следующие компоненты:Три кнопки TButton из вкладки Standart – в инспекторе объектов
для Button1 устанавливаем свойство Caption -> Новая запись; для Button2 устанавливаем свойство Caption -> Удалить запись; для Button3 устанавливаем свойство Caption -> Закрыть. Из вкладки Data Controls помещаем на форму компонент TDBGrid.
Сейчас сделаем запуск через меню Склад-> Приход из главной формы. Для этого выбираем в меню Project -> Options…
Выбираем Forms и перемещаем Form_prihod из Auto-create forms в Avalable forms.
Переходим на главную форму, щелкаем мышкой по компоненту MainMenu1, а затем по пункту Приход
И напишем следующий обработчик события: procedure TForm_general.N7Click(Sender: TObject);beginf:=0;
//проверяем, активна ли наша формаif ActiveMDIChild.Caption<>'Приход' then begin//если нет то ищем ее среди неактивных и если находим, то показываем ееfor i:=0 to form_general.MDIChildCount-1 doif form_general.MDIChildren[i].Caption='Приход' then begin MDIChildren[i].Show;f:=1;end;end else f:=1;//если форма еще не создана, то создаем ееif f<>1 then Tform_prihod.Create(Application);end;
Далее создаем Data Module, в нем мы будем создавать подключения к таблице прихода.
File->New->Form –Other…
Delphi Files-> Data Module
В инспекторе объектов устанавливаем для него следующие свойства Name -> dm. Сохраните модуль с именем unit_dm.
Пропишем Uses general, prihod; после раздела implementation в программном модуле unit_dm.
Пропишем Uses general, unit_dm; после раздела implementation в программном модуле unit prihod.
Далее из панели компонентов dbGo (ADO) размещаем на форме компоненты TADOTable и TADOQuery.
В инспекторе объектов для TADOQuery в свойство Name записываем ADOQuery_delete, Connection устанавливаем -> form_ general.ADOConnection1.
В инспекторе объектов ADOTable1 в свойство Name записываем table_prihod,Connection устанавливаем -> form_general.ADOConnection1 – TableName-
> prihod, Active-> True;Из вкладки Data Access помещаем на форму компонент TDataSource – в
инспекторе объектов свойство Name записываем prihod, DataSet->table_prihod.На форме Приход для DBGrid1 в инспекторе объектов свойство DataSource-
> dm.prihod, а свойство Options->dgRowSelect->True.После этого в DBGrid1 должны отобразиться поля таблицы table_prihod.Переходим в DataModule и (unit_dm) выбираем table_prihod и в структуре
(Structure) -> prihod -> Fields -> щелкнем правой кнопкой мыши и выберем Add all fields.
Должно получиться следующее:
Далее выбираем поле id и в инспекторе объектов устанавливаем у него свойство Visible->False.
Для поля id_postav_ik устанавливаем свойство Visible->False. Для поля number_docum DisplayLabel -> Номер документа; иDisplayWidth -> 15. Для поля date_prihoda DisplayLabel -> Дата прихода; DisplayWidth -> 18. Для поля sumDisplayFormat->0.00; DisplayLabel -> Сумма; DisplayWidth -> 10.
Далее создаем выпадающее поле Lookup для просмотра данных из справочника «Поставщики». Для этого в структуре (Structure) -> prihod -> Fields -> щелкнем правой кнопкой мыши и выберем New field….
и заполняем следующее окно:
В поле Name: пишем postav_ik; в поле Type: выбираем String; выбираем поле Lookup; в Key Fields:выбираем id_postav_ik; в Dataset: выбираем form_general. table_postav_ik; в Lookup Keys: выбираем id; а в Result Field: выбираем postav_ik_name жмем ОК
В инспекторе объектов для созданного поля свойство DisplyLabel-> Поставщик, DisplyWidth-> 24 и перемещаем поле мышкой в позицию после поля id_postav_ik. После этого должно получится для формы «Приход»:
Лабораторная работа № 8Создание формы прихода продуктов на склад
Создадим вторую форму, в которой будут отражаться данные о продуктах для каждого прихода.
Приступим к созданию формы.Создаем новую форму File->New->Form –Delphi – в инспекторе объектов
устанавливаем следующие свойства для новой формы Name -> Form_prihod_prod; Visible->False.
Сохраните модуль с именем prihod_prod.Пропишем uses general, prihod, unit_dm; после раздела implementation в
программном модуле unit prihod_prod.В программном модуле unit general главной формы пропишем Uses ed_izmer,
product_group, postav_ik, products, prihod, prihod_prod.В программном модуле unit prihod формы прихода (form_prihod) пропишем
uses general, unit_dm, prihod_prod.Далее размещаем на форме следующие компоненты:Три кнопки TButton, компонент TEdit и пять компонентов TLable из
вкладки Standart – в инспекторе объектов для Button1 устанавливаем свойство Caption -> Новая запись; для Button2 устанавливаем свойство Caption -> Удалить запись; для Button3 устанавливаем свойство Caption -> Закрыть; для Edit1 устанавливаем свойство Name-> docum_number, NumbersOnly->True; для Label1 устанавливаем свойство Caption -> Документ номер; для Label2 устанавливаем свойство Caption -> от; для Label3 устанавливаем свойство Caption -> Поставщик; для Label4 устанавливаем свойство Caption ->Итого на сумму для Label5 устанавливаем свойство Caption -> руб.
Из вкладки Win32, компонент TDateTimePicker – в инспекторе объектов для него устанавливаем свойство Format -> dd.MM.yyyy, Time -> 0:00:00.
Далее из панели компонентов dbGo (ADO) размещаем на форме компоненты два TADOTable и TADOQuery. Для ADOTable1 в инспекторе объектов свойство Name записываем table_copy_prihod, Connection устанавливаем -> form_general. ADOConnection1 TableName-> prihod, Active-> True. Для ADOTable2 в инспекторе объектов свойство Name записываем table_storage, Connection устанавливаем -> form_ general.ADOConnection1 TableName-> strorage, Active-> True.
Выбираем table_storage и в структуре (Structure) -> storage -> Fields -> щелкнем правой кнопкой мыши и выберем Add all fields.
У вас должно получиться следующее:
Далее выбираем поле id и в инспекторе объектов устанавливаем у него свойство Visible->False.
Для поля id_product устанавливаем свойство Visible->False. Для поля id_product_group устанавливаем свойство Visible->False.
Для поля id_prihod устанавливаем свойство Visible->False. Для поля id_ed_izmer устанавливаем свойство Visible->False. Для поля quantity – DisplayFormat->0.000; DisplayLabel -> Количество; DisplayWidth -> 10.
Для поля price – DisplayFormat->0.00; DisplayLabel -> Цена; DisplayWidth -> 10;Для поля date_realization – DisplayLabel -> Реализовать до:; DisplayWidth -> 18;Далее создаем выпадающее поле Lookup (поле подстановки) для просмотра
данных из справочника «Продукты». Для этого в структуре (Structure) -> Storage -> Fields -> щелкнем правой
кнопкой мыши и выберем New field….
и заполняем следующее окно
В поле Name: пишем product; в поле Type: выбираем String; выбираем поле Lookup; в Key Fields:выбираем id_product; в Dataset: выбираем form_ general.table_products; в Lookup Keys: выбираем id; а в Result Field: выбираем product_name жмем ОК.
В инспекторе объектов для созданного поля свойство DisplyLabel-> Продукт, DisplyWidth-> 20 и перемещаем поле мышкой в позицию после поля id_product.
Далее создаем выпадающее поле Lookup (поле подстановки) для просмотра данных из справочника «Единицы измерения».
Для этого в структуре (Structure) -> Storage -> Fields -> щелкнем правой кнопкой мыши и выберем New field…. и делаем аналогично предыдущему …
В поле Name: пишем ed_izmer; в поле Type: выбираем String; выбираем поле Lookup; в Key Fields:выбираем id_ed_izmer; в Dataset: выбираем form_general. table_ed_izmer; в Lookup Keys: выбираем id; а в Result Field: выбираем ed_name жмем ОК
В инспекторе объектов для созданного поля свойство DisplyLabel-> Ед.изм., DisplyWidth-> 20 и перемещаем поле мышкой в позицию после поля product.
Далее создаем вычисляемое поле summa. Для этого в структуре (Structure) -> Storage -> Fields -> щелкнем правой кнопкой мыши и выберем New field…. и делаем аналогично предыдущему …
В поле Name: пишем summa; в поле Type: выбираем Float; выбираем поле Calculated; и жмем ОК
В инспекторе объектов для созданного поля свойство DisplyLabel-> Сумма., DisplyWidth->10, DisplayFormat->0.00.
Свяжем таблицу table_storage с таблицей table_prihod в Datamodule (dm) для этого выбираем компонент table_storage и в инспекторе объектов свойство MasterSource -> dm.prihod, MasterFields->… и в открывшемся окне выбираем в левом окне id_prihod а в правом окне id нажимаем Add.
В окне JoinedFields должна появиться связь
Нажимаем ОК и связь между таблицами установлена.Для table_storage устанавливаем свойство Active-> True; для ADOQuery1 в
инспекторе объектов свойство Name записываем ADOQuery_summa, Connection устанавливаем -> form_general.ADOConnection1; DataSource-> dm.prihod; SQL (TString) -> в открывшемся окне вводим следующий запрос:
SELECT storage.id_prihod, Sum([storage].[quantity]*[storage].[price]) AS [sum]FROM storageGROUP BY storage.id_prihodHAVING (((storage.id_prihod)=:id));
далее выбираем свойство Parameters((TParameters)
Создаем новый параметр Name->id – Value->Type->Integer; Выбираем ADOQuery_summa и в структуре (Structure) -> ADOQuery_summa -> Fields -> щелкнем правой кнопкой мыши и выберем Add all fields.
Для поля sum DisplayFormat->0.00; DisplayLabel -> sum; DisplayWidth -> 10.Из вкладки Data Access помещаем на форму три компонента TDataSource –
для DataSource1 в инспекторе объектов свойство Name записываем summa, DataSet-> ADOQuery_summa; для DataSource2 в инспекторе объектов свойство Name записываем postav_ik, DataSet-> Form_general.table_postav_ik; для DataSource3 в инспекторе объектов свойство Name записываем storage, DataSet-> table_storage.
Из вкладки Data Controls помещаем на форму компоненты TDBLookup ComboBox, TDBGrid и TDBEdit. Для DBGrid1 в инспекторе объектов свойство DataSource-> storage, а свойство Options->dgRowSelect->True. Для DBEdit1 в Name-> DBEdit_summ, DataSource->summa, DataField->sum, ReadOnly->True. Для DBLookupComboBox1 в инспекторе объектов свойство Name записываем DBLookup_postav_ik, ListSource->postav_ik, ListField->postav_ik_name, KeyField->id, DataSource->dm.prihod, DataField->id_postav_ik. Далее приводим нашу форму к следующему виду:
Лабораторная работа № 9Создание формы прихода продуктов на склад
Создадим последнюю форму для прихода продуктов. В ней будет происходить выбор продуктов прихода.
Приступим к созданию формы.Создайте новую форму File->New->Form –Delphi. В инспекторе
объектов устанавливаем следующие свойства для новой формы – Name -> Form_select_prod; Visible->False; Caption->Выбор продуктов.
Сохраните модуль с именем select_prod.Пропишем uses general, prihod_prod; после раздела implementation {$R *.dfm} в
программном модуле unit select_prod.В программном модуле unit select_prod формы prihod_prod пропишем uses
general, prihod, unit_dm, select_prod;Далее размещаем на форме следующие компоненты – две
кнопки TButton шесть компонентов TLable из вкладки Standart, в инспекторе объектов для Button1 устанавливаем свойство Caption -> ОК; для Button2 устанавливаем свойство Caption -> Отмена; для Label1 устанавливаем свойство Caption -> Группа; для Label2 устанавливаем свойство Caption -> Ед.изм.; для Label3 устанавливаем свойство Caption -> Количество; для Label4 устанавливаем свойство Caption -> Цена; для Label5 устанавливаем свойство Caption -> Сумма; для Label6 устанавливаем свойство Caption ->Срок реализации.
Из вкладки Win32, компонент TDateTimePicker – в инспекторе объектов для него устанавливаем свойство Format -> dd.MM.yyyy, Time -> 0:00:00;
Из вкладки Data Access помещаем на форму три компонента TDataSource. Для DataSource1 в инспекторе объектов свойство Name записываем product_group, DataSet-> Form_general.table_product_group; для DataSource2 в инспекторе объектов свойство Name записываем products, DataSet-> Form_general.table_products; для DataSource3 в инспекторе объектов свойство Name записываем ed_izmer, DataSet-> Form_general.table_ed_izmer.
Из вкладки Data Controls помещаем на форму три компонента TDBLookupComboBox и три TDBEdit. Для DBLookupComboBox1 в инспекторе объектов свойство Name записываем DBLookup_product_group, ListSource -> product _group, ListField-> product_name, KeyField->id, DataSource-> Form_prihod_prod.storage, DataField-> id_product_group. Для DBLookupComboBox2 в инспекторе объектов свойство Name записываем DBLookup_products, DataSource-> Form_prihod_ prod. storage, DataField-> product. Для DBLookupComboBox3 в инспекторе объектов
свойство Name записываем DBLookup_ed_izmer, DataSource-> Form_prihod_ prod. storage, DataField-> ed_izmer. Для DBEdit1 в Name-> quantity, DataSource-> Form_ prihod_prod.storage, DataField-> quantity. Для DBEdit2 в Name-> price, DataSource-> Form_prihod_prod.storage, DataField-> price; Для DBEdit3 в Name-> summ, Data Source-> Form_prihod_prod.storage, DataField-> summa, ReadOnly->True. Далее располагаем компоненты формы, как показано на рисунке:
Лабораторная работа № 10Создание формы прихода продуктов на склад
Напишем процедуры для обработки событий для наших форм прихода, созданных на предыдущих лабораторных занятиях.Открываем форму прихода модуль (prihod) и пишем для события OnClick кнопки Button1 (Новая запись):
procedure TForm_prihod.Button1Click(Sender: TObject);begin//новая запись form_prihod_prod.Caption:='Приход: новое' ; dm.table_prihod.Edit; dm.table_prihod.append; form_prihod_prod.DateTimePicker1.Date:=sysutils.Date; form_prihod_prod.docum_number.Text:=''; form_prihod_prod.Showmodal;end;
Для события OnClick кнопки Button2 (Удалить запись):procedure TForm_prihod.Button2Click(Sender: TObject);begin//удаление записи if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удалить запись?', 'Внимание !!!', MB_YESNO) = IDYES) then begin
dm.table_prihod.Edit; form_prihod_prod.table_storage.Edit; //из таблицы storage dm.ADOQuery_delete.SQL.Clear; dm.ADOQuery_delete.DataSource:=dm.prihod; dm.ADOQuery_delete.SQL.Add('DELETE storage.*, storage.id FROM storage WHERE (((storage.id_prihod)=:id));'); dm.ADOQuery_delete.ExecSQL; dm.ADOQuery_delete.Active:=false; //из таблицы prihod dm.table_prihod.Edit; dm.table_prihod.Delete; end; end else ShowMessage('Нет записей для удаления');end;
Для события OnClick кнопки Button3 (Закрыть):procedure TForm_prihod.Button3Click(Sender: TObject);begin //закрытие формыClose;end;
Для события OnDblClick компонента DBGrid1:procedure TForm_prihod.DBGrid1DblClick(Sender: TObject);begin//Двойной клик на записи, если записей еще нет, то создаем новуюif dbgrid1.DataSource.DataSet.RecordCount=0 then begin form_prihod_prod.Caption:='Приход: новое' ; dm.table_prihod.Edit; dm.table_prihod.append; form_prihod_prod.docum_number.Text:=''; form_prihod_prod.DateTimePicker1.Date:=sysutils.Date; end//иначе заполняем форму prihod_prod текущими данными else begin dm.table_prihod.Edit; form_prihod_prod.table_storage.Edit; form_prihod_prod.table_storage.First; form_prihod_prod.docum_number.Text:= dm.table_prihod.FieldByName('number_docum').value; form_prihod_prod.DateTimePicker1.Date:= dm.table_prihod.FieldByName('date_prihoda').Value; end;//показываем форму prihod_prod form_prihod_prod.Caption:='Приход: '+dm.table_prihod.FieldByName('number_docum').AsString;
form_prihod_prod.Showmodal;end;
Для события OnActivate формы прихода form_prihod:procedure TForm_prihod.FormActivate(Sender: TObject);begin//так как таблица приход использует данные из таблиц единицы измерения, категории продуктов, поставщики //и продукты//то мы должны проверить заполнены они или нетif form_general.table_ed_izmer.RecordCount=0 then begin ShowMessage('У Вас не заполнен справочник "Единиц измерения". Для продолжения работы Вам необходимо заполнить справочник.');close;endelse beginif form_general.table_product_group.RecordCount=0 then begin ShowMessage('У Вас не заполнен справочник "Категории продуктов". Для продолжения работы Вам необходимо заполнить справочник.');close;endelse beginif form_general.table_postav_ik.RecordCount=0 then begin ShowMessage('У Вас не заполнен справочник "Поставщики". Для продолжения работы Вам необходимо заполнить справочник.');close;endelse beginif form_general.table_products.RecordCount=0 then begin ShowMessage('У Вас не заполнен справочник "Продукты". Для продолжения работы Вам необходимо заполнить справочник.');close;endelse begin//обновляем данныеform_general.table_ed_izmer.Refresh;form_general.table_product_group.Refresh;form_general.table_postav_ik.Refresh;form_general.table_products.Refresh;//установка фокуса при активации формыdbgrid1.SetFocus; end; end; end; end; end;
Для события OnClose формы прихода form_prihod:procedure TForm_prihod.FormClose(Sender: TObject; var Action: TCloseAction);begin//процедура закрытия формыAction:=cafree;end;
Открываем форму прихода продуктов модуль (prihod_prod) и пишем для события OnClick кнопки Button1 (Новая запись):
procedure TForm_prihod_prod.Button1Click(Sender: TObject);begin //новая запись if docum_number.Text='' then begin ShowMessage('Не заполнено поле "Номер документа"'); docum_number.SetFocus; end else begin if (table_copy_prihod.Lookup('number_docum', docum_number.text, 'number_docum')<>null) and
(dm.table_prihod.FieldByName('number_docum').AsString<>docum_number.Text) then begin ShowMessage('Такой номер уже существует');docum_number.Text:=''; docum_number.SetFocus; end else begin if dblookup_postav_ik.Text='' then begin ShowMessage('Не заполнено поле "Поставщик"'); dblookup_postav_ik.SetFocus;end else begin if DateTimePicker1.ToString='' then begin ShowMessage('Не заполнено поле "Дата прихода"'); DateTimePicker1.SetFocus;end else begin dm.table_prihod.FieldByName('date_prihoda').Value:=DateTimePicker1.Date; dm.table_prihod.FieldByName('number_docum').Value:=docum_number.text; dm.table_prihod.Post; dm.table_prihod.edit; table_storage.Edit; table_storage.append; table_storage.FieldByName('id_prihod').Value:= dm.table_prihod.FieldByName('id').AsInteger; form_select_prod.Showmodal; end; end; end; end; end;
для события OnClick кнопки Button2 (Удалить запись):procedure TForm_prihod_prod.Button2Click(Sender: TObject);begin//удалить запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удалить запись?', 'Внимание !!!', MB_YESNO) = IDYES) then begin table_storage.Edit; table_storage.Delete; adoquery_summa.Active:=false; adoquery_summa.Active:=true; end; end else ShowMessage('Нет записей для удаления');end;
для события OnClick кнопки Button3 (Закрыть):procedure TForm_prihod_prod.Button3Click(Sender: TObject);begin//закрытие формыClose;end;
для события OnDblClick компонента DBGrid1:procedure TForm_prihod_prod.DBGrid1DblClick(Sender: TObject);begin
//двойной клик для редактирования записи if docum_number.Text='' then begin ShowMessage('Не заполнено поле "Номер документа"'); docum_number.SetFocus; end else begin if (table_copy_prihod.Lookup('number_docum', docum_number.text, 'number_docum')<>null) and (dm.table_prihod.FieldByName('number_docum').AsString<>docum_number.Text) then begin ShowMessage('Такой номер уже существует'); docum_number.Text:=''; docum_number.SetFocus; end else begin if dblookup_postav_ik.Text='' then begin ShowMessage('Не заполнено поле "Поставщик"'); dblookup_postav_ik.SetFocus;end else begin if DateTimePicker1.ToString='' then begin ShowMessage('Не заполнено поле "Дата прихода"'); DateTimePicker1.SetFocus;end else begin dm.table_prihod.FieldByName('date_prihoda').Value:= DateTimePicker1.Date; dm.table_prihod.FieldByName('number_docum').Value:= docum_number.text; dm.table_prihod.Post; dm.table_prihod.edit; table_storage.Edit; table_storage.FieldByName('id_prihod').Value:= dm.table_prihod.FieldByName('id').AsInteger; if table_storage.FieldByName('id_product_group').AsInteger<>0 then form_select_prod.DBLookup_product_group.KeyValue:= table_storage.FieldByName('id_product_group').Value; //открываем форму редактирования form_select_prod.Showmodal;end; end; end; end; end;
для события OnActivate формы прихода продуктов form_prihod_prod:procedure TForm_prihod_prod.FormActivate(Sender: TObject);begin//пересчет итоговой суммы при активации формыadoquery_summa.Active:=false;adoquery_summa.Active:=true;end;
для события OnCloseQuery формы прихода продуктов form_prihod_prod:procedure TForm_prihod_prod.FormCloseQuery(Sender: TObject; var CanClose: Boolean);begin//проверка перед закрытием формы и закрытие формы//сохранение формы if ( MessageBox(Handle, 'Cохранить документ?', 'Внимание !!!', MB_OkCANCEL)= IDOk) then begin
if docum_number.Text='' then begin ShowMessage('Не заполнено поле "Номер документа"'); CanClose:=false;docum_number.SetFocus; end else begin if (table_copy_prihod.Lookup('number_docum',docum_number.Text,'number_docum')<>null) and (dm.table_prihod.FieldByName('number_docum').AsString<>docum_number.Text)then begin ShowMessage('Такой номер уже существует');CanClose:=false;docum_number.Text:=''; docum_number.SetFocus; end else begin if dblookup_postav_ik.Text='' then begin ShowMessage('Не заполнено поле "Поставщик"');CanClose:=false;dblookup_postav_ik.SetFocus;end else begin if DateTimePicker1.ToString='' then begin ShowMessage('Не заполнено поле "Дата прихода"');CanClose:=false;DateTimePicker1.SetFocus;end else begin dm.table_prihod.Edit; dm.table_prihod.FieldByName('date_prihoda').Value:=DateTimePicker1.Date; dm.table_prihod.FieldByName('number_docum').Value:=docum_number.text; dm.table_prihod.FieldByName('sum').Value:=dbedit_summa.Field.Value; dm.table_prihod.post; end; end; end; end; end //при отказе от сохранения, проверяем, если уже заполненные записи продуктов и если такие есть, то не даем закрыть форму, пока все не будет заполнено правильно else if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if docum_number.Text='' then begin ShowMessage('Не заполнено поле "Номер документа"'); CanClose:=false;docum_number.SetFocus; end else begin if (table_copy_prihod.Lookup('number_docum',docum_number.Text, 'number_docum')<>null) and (dm.table_prihod.FieldByName('number_docum').AsString <> docum_number.Text) then begin ShowMessage('Такой номер уже существует');CanClose:=false;docum_number.Text:=''; docum_number.SetFocus; end else begin if dblookup_postav_ik.Text='' then begin ShowMessage('Не заполнено поле "Поставщик"');CanClose:=false;dblookup_postav_ik.SetFocus;end else begin if DateTimePicker1.ToString='' then begin ShowMessage('Не заполнено поле "Дата прихода"');CanClose:=false;DateTimePicker1.SetFocus;end
else begin dm.table_prihod.Edit; dm.table_prihod.FieldByName('date_prihoda').Value:= DateTimePicker1.Date; dm.table_prihod.FieldByName('number_docum').Value:= docum_number.text; dm.table_prihod.FieldByName('sum').Value:= dbedit_summa.Field.Value; dm.table_prihod.post; end; end; end; end; end //если записей нет, отменяем изменения else dm.table_prihod.cancel;end;
для события OnCalcFields компонента table_storage:procedure TForm_prihod_prod.table_storageCalcFields(DataSet: TDataSet);begin//вычисляемое поле суммаtable_storage.FieldByName('summa').Value:= table_storage.FieldByName('price').Value* table_storage.FieldByName('quantity').Value;end;
Открываем форму выбора продуктов прихода модуль (select_prod) и пишем для события OnClick кнопки Button1 (OK):
procedure TForm_select_prod.Button1Click(Sender: TObject);begin//Нажатие на кнопку ОК. Проверяем и сохраняем.if dblookup_products.Text='' then begin ShowMessage('Не заполнено поле "Продукт"');dblookup_products.SetFocus;end else begin if dblookup_ed_izmer.Text='' then begin ShowMessage('Не заполнено поле "Ед.изм."');dblookup_ed_izmer.SetFocus;end else begin if quantity.Text='' then begin ShowMessage('Не заполнено поле "Количество"');quantity.SetFocus;end else begin if price.Text='' then begin ShowMessage('Не заполнено поле "Цена"'); price.SetFocus;end else begin if DateTimePicker1.ToString='' then begin ShowMessage('Не заполнено поле "Срок реализации"'); DateTimePicker1.SetFocus;end else begin if ( MessageBox(Handle, 'Cохранить документ?', 'Внимание !!!', MB_OkCANCEL)= IDOk) then begin form_prihod_prod.table_storage.Edit; form_prihod_prod.table_storage.FieldByName('id_product_group').Value:= form_general.table_products.FieldByName('id_product_group').Value; form_prihod_prod.table_storage.FieldByName('date_realization').Value:=
DateTimePicker1.Date; form_prihod_prod.table_storage.Post; end else form_prihod_prod.table_storage.Cancel;close; end; end; end; end; end; end;
для события OnClick кнопки Button2 (Отмена):procedure TForm_select_prod.Button2Click(Sender: TObject);begin//кнопка отменаform_prihod_prod.table_storage.Cancel;form_select_prod.Close;end;
для события OnClick компонента DBLookup_products:procedure TForm_select_prod.DBLookup_productsClick(Sender: TObject);begin//заполняем поля по умолчанию при выборе продукта DBLookup_ed_izmer.KeyValue:=products.DataSet.FieldByName('id_ed_izmer').Value; form_prihod_prod.table_storage.FieldByName('id_ed_izmer').Value:= dblookup_ed_izmer.KeyValue; DateTimePicker1.Date:=sysutils.Date+ products.DataSet.FieldByName('time_hraneniya').Value;end;
для события OnClick компонента DBLookup_product_group:procedure TForm_select_prod.DBLookup_product_groupClick(Sender: TObject);begin//включем фильтр при выборе группы продукта form_general.table_products.Filtered:=true; form_general.table_products.Filter:='id_product_group='+ inttostr(DBLookup_product_group.KeyValue);//отключаем фильтр, если в выбранной категории нет продуктов if products.DataSet.RecordCount=0 then begin ShowMessage('Список продуктов пустой, выберите другую категорию или заполните справочник "Продукты".'); form_general.table_products.Filtered:=false; end;end;
для события OnClose формы form_select_prod:procedure TForm_select_prod.FormClose(Sender: TObject; var Action: TCloseAction);begin//пересчитываем итоговую сумму и закрываем форму. form_prihod_prod.table_storage.Cancel; form_general.table_products.Filtered:=false; form_prihod_prod.adoquery_summa.Active:=false;
form_prihod_prod.adoquery_summa.Active:=true;end;
Открываем форму «Справочник продуктов модуль (products) и пишем для события OnClick кнопки Button2 (Удалить запись):
procedure TForm_products.Button2Click(Sender: TObject);//удаление записиbegin//если записи отсутствуют то выводим сообщение, иначе проверяем используется//ли данный продукт на складе, если нет то удаляем запись if dbgrid1.DataSource.DataSet.RecordCount<>0 then begin if (MessageBox(Handle, 'Удаление записей может привести к нарушению работы всей базы данных. Удалить запись?', 'Внимание !!!', MB_YESNO)= IDYES) then if (form_prihod_prod.table_storage.Locate('id_product', form_general.table_products.FieldByName('id').Value, [loCaseInsensitive,loPartialKey])) then ShowMessage('Нельзя удалить данный продукт, так как он используется в складе.') else form_general.table_products.Delete end else ShowMessage('Нет записей для удаления');end;
а в uses добавим prihod_prod;
На этом создание формы прихода закончено. Можно приступать к тестированию на наличие ошибок.
Лабораторная работа № 10Программирование баз данных в Delphi
(Создаем форму для просмотра остатков продуктов на складе)
Дополним базу еще двумя таблицами для учета информации о расходе. Создадим SQL запросы к базе для формирования остатков продуктов на складе и создадим форму для просмотра остатков продуктов по этим запросам.
Прежде чем приступить к созданию формы, необходимо добавить в нашу базу две таблицы первая для хранения информации о расходных накладных (назовем ее rashod_doc, она является аналогом таблицы prihod) и вторая для хранения информации о расходе продуктов по расходной накладной (назовем ее rashod, является аналогом таблицы storage). Откроем нашу базу storage.mdb в MS Access 2007 и создадим таблицу с именем rashod_doc.
Далее создаем следующие поля таблицы rashod_doc:id (счетчик) – нужно задать как ключевое,number_docum (текстовый, в свойствах поля – размер поля – 20) –
номер расходной накладной date_rashoda (тип данных – Дата/время) – дата расхода, sum (тип данных – денежный, в свойствах поля – формат поля – основной, число десятичных знаков – 4) – сумма расхода.
Затем создаем таблицу rashod со следующими полями: id (счетчик) – нужно задать как ключевое; id_product (тип данных – числовой, в свойствах поля – размер поля –
Длинное целое) – код продукта; id_product_group (тип данных – числовой, в свойствах поля размер поля –
Длинное целое) – код группы продуктов; quantity (тип данных -денежный, в свойствах поля – формат поля –
основной, число десятичных знаков – 3) – количество; price (тип данных – денежный, в свойствах поля – формат поля –
основной, число десятичных знаков – 4) – цена; id_rashod_doc (тип данных – числовой, в свойствах поля – размер поля–
Длинное целое) – код расхода; id_ed_izmer (тип данных – числовой, в свойствах поля – размер поля –
Длинное целое) – код единицы измерения.
Сейчас немножко о том, как это все будет работать. Для того, чтобы посмотреть остатки продуктов на складе мы создадим три запроса к нашей базе. Первый запрос будет группировать продукты из таблицы storage по полям id_product и id_ed_izmer с одновременным суммированием по количеству (поле quantity) и сумме (поле price* quantity). Второй запрос будет делать тоже, что и первый, но по таблице rashod. А третий запрос будет находить разницу между первым и вторым запросом, и выводить эти данные в нашу форму.
И так приступим к созданию формы. Запускает наш проект, и создаем новую форму File->New->Form – Delphi.
В инспекторе объектов устанавливаем следующие свойства для новой формы Caption -> Остатки на складе; FormStyle -> fsMDIChild; Name -> Form_ostatki.
Сохраните модуль с именем ostatki. Пропишем Uses general, unit_dm; после раздела implementation в программном модуле unit ostatki. А программном модуле unit general главной формы пропишем Uses ostatki; Переходим в дата модуль (unit_dm) и размещаем там три компонента TADOQuery из вкладки dbGo (ADO) и один компонент TDataSource из вкладки Data Access.
Для ADOQuery1 в инспекторе объектов устанавливаем следующие свойства:Connection-> Form_general.ADOConnection1; Name-> ADOQuery_prihod; SQL-> (TStrings) -> вставляем следующий запрос:
SELECT storage.id_product, Sum([storage].[price]*[storage].[quantity]) AS sum_price, Sum(storage.quantity) AS [Sum-quantity], storage.id_ed_izmerFROM storage GROUP BY storage.id_product, storage.id_ed_izmer;
Свойство Active устанавливаем в True. Для ADOQuery2 в инспекторе объектов устанавливаем следующие свойства:
Connection-> Form_general.ADOConnection1; Name-> ADOQuery_rashod; SQL-> (TStrings) -> вставляем следующий запрос:
SELECT rashod.id_product, Sum([rashod].[price]*[rashod].[quantity]) AS sum_price, Sum(rashod.quantity) AS [Sum-quantity], rashod.id_ed_izmerFROM rashod GROUP BY rashod.id_product, rashod.id_ed_izmer;
Свойство Active устанавливаем в True. Для ADOQuery3 в инспекторе объектов устанавливаем следующие свойства:
Connection-> Form_general.ADOConnection1; Name-> ADOQuery_ostatki; SQL-> (TStrings) -> вставляем следующий запрос:
SELECT products.product_name, ADOQuery_prihod.id_product, [ADOQuery_ prihod].[Sum-quantity]-IIf([ADOQuery_rashod].[Sum-quantity]>0,[ADOQuery_rashod]. [Sum-quantity],0) AS ostatok, [ADOQuery_prihod].[sum_price]-IIf([ADOQuery_ rashod].[sum_price]>0,[ADOQuery_rashod].[sum_price],0) AS summa, ADOQuery_ prihod.id_ed_izmer, products.id_product_group, ed_izmer.ed_name FROM ((ADO Query_prihod LEFT JOIN ADOQuery_rashod ON ADOQuery_prihod.id_product = ADOQuery_rashod.id_product) LEFT JOIN ed_izmer ON ADOQuery_prihod.id_ed_izmer = ed_izmer.id) LEFT JOIN products ON ADOQuery_prihod.id_product = products.id;
Свойство Active устанавливаем в True. Для составления запросов я использовала конструктор запросов в MS Access, затем переключалась в режим SQL и копировала запрос в наш проект в Delphi.
Запросы ADOQuery_prihod, ADOQuery_rashod должны быть созданы в самой базе. Для их создания откройте базу storage.mdb в MS Access выберите создание -> конструктор запросов, закройте добавление таблиц и, щелкнув правой кнопкой мыши, выберите режим SQL. Далее скопируйте туда текст соответствующего запроса и сохраните его под соответствующим именем. Добавленные в Unit_dm компоненты ADOQuery_prihod и ADOQuery_rashod нужно удалить.
Для компонента DataSource1 устанавливаем свойства: DataSet->ADO Query_ostatki; Name->ostatki.
Далее переходим к нашей форме ostatki и размещаем на ней из вкладки Data Controls компонент TDBGrid. Для него устанавливаем следующие свойства:
Align-alClient; DataSource->dm.ostatki; Options->dgRowSelect->True.
Сейчас мы выберем нужные нам поля из запроса ADOQuery_ostatki для отображения их в форме. Для этого перейдем в дата модуль (unit_dm) проекта и выберем
компонентADOQuery_ostatki. В структуре (Structure) -> ADOQuery_ostatki -> Fields -> щелкнем правой кнопкой мыши и выберем Add all fields.
Выбираем поле product_name и в инспекторе объектов устанавливаем свойство: DisplayLabel -> Продукт; DisplayWidth -> 30.
Выбираем поле ed_name и в инспекторе объектов устанавливаем свойство:DisplayLabel -> Ед.изм.; DisplayWidth -> 10.
Выбираем поле id_product и в инспекторе объектов устанавливаем свойство:Visible->False.
Выбираем поле ostatok и в инспекторе объектов устанавливаем свойство:DisplayFormat ->0.000; DisplayLabel -> Остаток; DisplayWidth -> 10.
Выбираем поле summa и в инспекторе объектов устанавливаем свойство: DisplayFormat ->0.00; DisplayLabel ->Сумма; DisplayWidth -> 10.
Выбираем поле id_ed_izmer и в инспекторе объектов устанавливаем свойство:Visible->False.
Выбираем поле id_product_group и в инспекторе объектов устанавливаем свойство: Visible->False.
Далее создаем вычисляемое поле sred_price для вычисления средней стоимости продуктов». Для этого в структуре (Structure) -> products -> Fields -> щелкнем правой кнопкой мыши и выберем New field….
и заполняем, как показано на рисунке:
Name->sred_price; Type->Float; Calculated и жмем ОК.
Выбираем созданное поле (sred_price) и в инспекторе объектов устанавливаем свойство: DisplayFormat ->0.00; DisplayLabel ->Средняя цена; DisplayWidth -> 10 и переходим на вкладку Events и дважды жмем мышь на событии OnCalcFields;
В открывшемся обработчике событий пишем следующий код:procedure Tdm.ADOQuery_ostatkiCalcFields(DataSet: TDataSet);
begin//если остатки продуктов не равны 0 то вычисляем среднюю стоимость продукта if ADOQuery_ostatki.FieldByName('ostatok').Value<>0 then ADOQuery_ostatki.FieldByName('sred_price').Value:= ADOQuery_ostatki.FieldByName('summa').Value/ ADOQuery_ostatki.FieldByName('ostatok').Value else ADOQuery_ostatki.FieldByName('sred_price').Value:=0; end;
Возвращаемся снова к нашей форме ostatki и в обработчике событий для события OnActivate пишем следующий код:
procedure TForm_ostatki.FormActivate(Sender: TObject);begin// переоткрываем запросы при активации формы//тем самым обновляем данные на формеdm.ADOQuery_ostatki.Active:=false;dm.ADOQuery_ostatki.Active:=true; end;
Для события OnClose:procedure TForm_ostatki.FormClose(Sender: TObject; var Action: TCloseAction);begin//закрываем запросы и закрываем формуdm.ADOQuery_ostatki.Active:=false;Action:=cafree; end;
Сейчас сделаем запуск формы «Остатки на складе» из главной формы. Для этого выбираем в меню Project -> Options… Выбираем Forms и перемещаем Form_ostatki из Auto-create forms в Avalable forms. Переходим на главную форму, щелкаем мышкой по компоненту MainMenu1, а затем по пункту Просмотр склада. И напишем следующий обработчик события:
procedure TForm_general.N9Click(Sender: TObject);beginf:=0;//проверяем, активна ли наша формаif ActiveMDIChild.Caption<>'Остатки на складе' then begin//если нет то ищем ее среди неактивных и если находим, то показываем ее
for i:=0 to form_general.MDIChildCount-1 doif form_general.MDIChildren[i].Caption='Остатки на складе' then begin MDIChildren[i].Show;f:=1;end;end else f:=1;//если форма еще не создана, то создаем ееif f<>1 then Tform_ostatki.Create(Application); end;
Сохраняем и запускаем проект.
Лабораторная работа № 11Программирование баз данных в Delphi
(Создаем формы для учета расхода продуктов на складе)
Учет расхода также как и учет прихода будет состоять из трех форм. В первой форме будем выводить номер накладной расхода, дату расхода и сумму расхода по накладной.
Во второй форме будем выводить список продуктов выбранных для расхода с количеством, ценой и на какую сумму.
В третьей форме будем производить выбор продуктов для учета расхода.
Первые две формы учета расхода практически не отличаются от первых двух форм учета прихода за одним исключением из второй формы учета расхода убрано поле поставщик. Поэтому и создание этих форм чисто технически не отличается от создания форм прихода.
Пять полей DBEdit подключенных к таблице rashod. При двойном клике на поле DBGridа данные из DBGrida (Продукт, единица измерения, средняя цена автоматически заносятся в соответствующие поля, курсор устанавливается в поле количество). При нажатии кнопки ОК, данные заносятся в таблицу rashod базы данных после прохождения проверки корректности заполненных полей. При попытке ввести количество продуктов больше чем есть на складе, вызывается предупреждение. В случае отмены данные не сохраняются. Кроме того я добавил выделение зеленым цветом нулевых и красным цветом отрицательных остатков.
Создайте все три формы для учета расхода самостоятельно.
Лабораторная работа № 12Программирование баз данных в Delphi
(Создаем модуль печати данных о приходе и расходе)
Реализуем печать данных прихода, расхода и состояния склада. Печать будем реализовывать через MS Excel, то есть это будет не совсем печать, а экспорт данных в MS Excel, а там пользователь может сам выбрать, печатать или сохранить отчет. С начало приготовим шаблоны MS Excel, в которые будем выводить отчеты. Шаблон ведомость по приходу продуктов питания.
В шаблоне использован стиль ссылок R1C1. Включается Параметры->Формулы-> Стиль ссылок R1C1. Файл сохраняем с типом файла Шаблон.
Результат работы программы:
Шаблон ведомость по расходу продуктов питания.
Шаблон остатки на складе.
Далее в формы прихода и расхода внесем несколько изменений, необходимых для фильтрации документов прихода и расхода по дате.Добавим на формы прихода и расхода по два компонента TDateTimePicker из вкладки Win32 и компонент TCheckBox из вкладки Standart. Кнопку Button для вызова печати. Размещаем, как показано на рисунке:
Аналогично для формы расхода.
В инспекторе объектов для обеих DateTimePicker ов обнуляем свойство Time.А для события OnChange прописываем следующий код:
procedure TForm_prihod.DateTimePicker1Change(Sender: TObject);begin//Проверка установленных датif datetimepicker1.Date>datetimepicker2.Date thenbeginShowMessage('Внимание. Начальная дата прихода больше конечной');checkbox1.Checked:=false;DateTimePicker1.Date:=DateUtils.StartOfTheMonth(now);DateTimePicker2.Date:=date;end;end;procedure TForm_prihod.DateTimePicker2Change(Sender: TObject); begin//Проверка установленных датif datetimepicker1.Date>datetimepicker2.Date thenbeginShowMessage('Внимание. Начальная дата прихода больше конечной');checkbox1.Checked:=false;DateTimePicker1.Date:=DateUtils.StartOfTheMonth(now);DateTimePicker2.Date:=date;end;end;
А для события OnClick компонента CheckBox1 пишем:procedure TForm_prihod. Click(Sender: TObject);//включение фильтраbegindm.table_prihod.Filtered:=checkbox1.Checked;if checkbox1.Checked=true then dm.table_prihod.Filter:='(date_prihoda>='+datetostr(datetimepicker1.Date)+') and ('+ 'date_prihoda<='+datetostr(datetimepicker2.Date)+')';end;
Кроме того для события OnCreate формы пишем:procedure TForm_prihod.FormCreate(Sender: TObject);begin//установка начальных значений дат DateTimePickerDateTimePicker1.Date:=DateUtils.StartOfTheMonth(now);DateTimePicker2.Date:=Date;{DateUtils.EndOfTheMonth(now); }end;
В модуле Uses добавляем модуль DateUtils.
Аналогичные операции проделываем с формой расхода. Далее переходим в DataModule (Unit_dm) и размещаем там компонент TADOQuery из вкладки dbGo (ADO). В свойстве Name задаем имя ADOQuery_print, в свойство Connection->Form_general.ADOConnection1. Затем из вкладки Data Access размещаем компонент TDataSource в свойстве Name задаем имя print, а в свойство DataSet->ADOQuery_print. Затем создайте отдельный модуль для печати. Выбираем File->New->Unit – Delphi. Назовем его print.
Подключение интерфейса Excel происходит через модуль comobj:unit print;
interfaceUses Windows, Dialogs, SysUtils, Variants, DB, Excel_TLB, comobj, unit_dm;{Внимание!!! Перед подключением модуля Excel_TLB, необходимо импортировать библиотеку Excel. Для этого выберите Component->Import Component->Import a Type Library-> находим MS Excel и следуем инструкциям}function CreateApplication(FileName:string):boolean;procedure print_prihod(date_start,date_end:TDateTime;check:boolean);procedure print_rashod(date_start,date_end:TDateTime;check:boolean);procedure print_ostatki;var exl: OleVariant; WorkBook, Sheet: Variant;implementation function CreateApplication(FileName:string):boolean; //создаем приложение excelbegintry //Создаем объект интерфейса для доступа к серверу COM exl := CreateOleObject('Excel.Application'); // Отключаем реакцию Excel на события, //чтобы ускорить вывод информации exl.Application.EnableEvents := false; //Создаем книгу и обращаемся к первому листу Workbook := exl.Application.WorkBooks.Add(GetCurrentDir()+FileName); Sheet := WorkBook.WorkSheets[1]; result:=true;Exceptshowmessage('Внимание! Произошла ошибка при создании MS Excel приложения');result:=false;exl.DisplayAlerts := False; // отключаем предупрежденияexl.Workbooks.Close; // закроем все книгиexl.Application.quit;//освобождаем интерфейсыSheet := Unassigned;WorkBook := Unassigned;exl := Unassigned;end;end;//печать прихода
procedure print_prihod(date_start,date_end:TDateTime;check:boolean);var ArrayData,ArrayData1,ArrayData2: Variant; x,y,kdx,ndx,ndy,kdy,n,m,i:integer; //ndx, ndy -начало диапазона по оси х (вправо) и по оси у (вниз) //kdx, kdy -конец диапазона по оси х и по оси у // ArrayData - двухмерный массив для продуктов // ArrayData1 - двухмерный массив для единиц измерения // ArrayData2 - массив для датbegin if CreateApplication('\Шаблоны\Ведомость прихода продуктов.xlt')=false then exit; try//делаем запрос на выбор продуктов и единиц измерения прихода//и заполняем вариантный массив для продуктов и для единиц измеренияdm.ADOQuery_print.Active:=false;dm.ADOQuery_print.SQL.Clear;dm.ADOQuery_print.SQL.Add('SELECT products.product_name, ed_izmer.ed_name FROM prihod LEFT JOIN ((storage LEFT JOIN products ON storage.id_product = products.id) LEFT JOIN ed_izmer'+' ON storage.id_ed_izmer = ed_izmer.id) ON prihod.id = storage.id_prihod GROUP BY products.product_name, ed_izmer.ed_name;');dm.ADOQuery_print.Active:=True;y:=dm.print.DataSet.RecordCount;//количество записей по продуктам в приходеArrayData := VarArrayCreate([1, y*2,1,1], varVariant); //двухмерный массив для продуктовArrayData1 := VarArrayCreate([1, y*2,1,1], varVariant); //двухмерный массив для единиц измерения dm.ADOQuery_print.First; for i:=1 to y*2 do //умножаем на два так как в шаблоне для наименования продукта //используется высота ячейки в две клетки, приходится первую заполнять, а вторую пропускать begin if (i mod 2)<>0 then begin //шаг - каждый второй ArrayData[i,1] :=dm.ADOQuery_print.FieldByName('product_name').AsString; //заполняем продукт ArrayData[i+1,1] :=''; // оставляем пустой ArrayData1[i,1] :=dm.ADOQuery_print.FieldByName('ed_name').AsString; //заполняем единицу измерения ArrayData1[i+1,1] :='';// оставляем пустой if dm.ADOQuery_print.eof<>true then dm.ADOQuery_print.next; end; end;//выполняем запрос на выбор даты прихода и заполняем вариантный массив2 dm.ADOQuery_print.Active:=false;dm.ADOQuery_print.SQL.Clear;//проверяем включен ли фильтр и формируем соответствующий запрос по дате или безif check=false then dm.ADOQuery_print.SQL.Add('SELECT prihod.date_prihoda FROM prihod GROUP BY prihod.date_prihoda ORDER BY prihod.date_prihoda;')
else begin dm.ADOQuery_print.Parameters.AddParameter.Name:='date1'; dm.ADOQuery_print.Parameters.ParamByName('date1').DataType:=ftDateTime; dm.ADOQuery_print.Parameters.AddParameter.Name:='date2'; dm.ADOQuery_print.Parameters.ParamByName('date2').DataType:=ftDateTime; dm.ADOQuery_print.SQL.Add('SELECT prihod.date_prihoda FROM prihod GROUP BY prihod.date_prihoda HAVING (((prihod.date_prihoda)>=:date1 and (prihod.date_prihoda)<=:date2)) ORDER BY prihod.date_prihoda; '); dm.ADOQuery_print.Parameters.ParamByName('date1').Value:=date_start; dm.ADOQuery_print.Parameters.ParamByName('date2').Value:=date_end; end;dm.ADOQuery_print.Active:=True;x:=dm.print.DataSet.RecordCount;//количество записей датArrayData2 := VarArrayCreate([1, x,1,1], varVariant);//массив для датdm.ADOQuery_print.First;for i:=1 to x do begin //заполняем массив датами ArrayData2[i,1] :=dm.ADOQuery_print.FieldByName('date_prihoda').AsString; if dm.ADOQuery_print.eof<>true then dm.ADOQuery_print.next; end; // рисуем поле данных ndy:=24; ndx:=18; kdx:=18+x*4-1; kdy:=25; //выделение диапазона ячеек sheet.Range[sheet.cells[24,18],sheet.cells[25,21]].Select; //объеденение ячеек sheet.Range[sheet.cells[24,18],sheet.cells[25,21]].Merge; //рисуем поле с цифрами ndy:=23; ndx:=18; kdx:=18+x*4-1; kdy:=23; sheet.Range[sheet.cells[23,18],sheet.cells[23,21]].Select; sheet.Range[sheet.cells[23,18],sheet.cells[23,21]].Merge; Exl.Selection.HorizontalAlignment:=xlCenter; sheet.cells[23,18].value:=3; //рисуем поле с датами ndy:=17; ndx:=18; kdx:=18+x*4-1; kdy:=22; sheet.Range[sheet.cells[17,18],sheet.cells[22,21]].Select; sheet.Range[sheet.cells[17,18],sheet.cells[22,21]].Merge; exl.Selection.Orientation := 90; Exl.Selection.HorizontalAlignment:=xlCenter; Exl.Selection.VerticalAlignment:=xlCenter; //общее выделение и размножение вправо if x>1 then begin ndy:=17; ndx:=18; kdx:=18+x*4-1; kdy:=25;
sheet.Range[sheet.cells[17,18],sheet.cells[25,21]].Select; //автозаполнение выделенного диапазона exl.selection.autofill(sheet.Range[sheet.cells[ndy,ndx], sheet.cells[kdy,kdx]], xlFillDefault); end; //рисуем шапку над датой ndy:=15; ndx:=18; kdx:=18+x*4-1; kdy:=16; sheet.Range[sheet.cells[15,18],sheet.cells[16,kdx]].Select; sheet.Range[sheet.cells[15,18],sheet.cells[16,kdx]].Merge; // рисуем поле итоги sheet.Range[sheet.cells[15,kdx+1],sheet.cells[22,kdx+5]].Select; sheet.Range[sheet.cells[15,kdx+1],sheet.cells[22,kdx+5]].Merge; sheet.cells[15,kdx+1].value:='Итого'; Exl.Selection.HorizontalAlignment:=xlCenter; sheet.Range[sheet.cells[23,kdx+1],sheet.cells[23,kdx+5]].Select; sheet.Range[sheet.cells[23,kdx+1],sheet.cells[23,kdx+5]].Merge; sheet.cells[23,kdx+1].value:=3+x; Exl.Selection.HorizontalAlignment:=xlCenter; sheet.Range[sheet.cells[24,kdx+1],sheet.cells[25,kdx+5]].Select; sheet.Range[sheet.cells[24,kdx+1],sheet.cells[25,kdx+5]].Merge; //вводим формулу суммы sheet.cells[24,kdx+1].value:='=SUM(RC[-'+inttostr(x*4)+']:R[1]C[-1])'; //выделяем и рисуем границы шапки таблицы sheet.Range[sheet.cells[15,18],sheet.cells[23,kdx+5]].Select; exl.Selection.Borders[xlEdgeLeft].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeLeft].Weight := xlMedium; exl.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeTop].Weight := xlMedium; exl.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeBottom].Weight := xlMedium; exl.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeRight].Weight := xlMedium; exl.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideVertical].Weight := xlMedium; exl.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideHorizontal].Weight := xlMedium; ndy:=24; ndx:=2; kdx:=18+x*4-1; kdy:=24+y*2-1; //общее выделение и размножение вниз if y>1 then begin sheet.Range[sheet.cells[ndy,ndx],sheet.cells[ndy+1,kdx+5]].Select; exl.selection.autofill(sheet.Range[sheet.cells[ndy,ndx], sheet.cells[kdy,kdx+5]],xlfillcopy); end; //выделяем и рисуем границы данныx sheet.Range[sheet.cells[24,18],sheet.cells[kdy,kdx+5]].Select; exl.Selection.NumberFormat:='0,000';
exl.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeTop].Weight := xlMedium; exl.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeBottom].Weight := xlMedium; exl.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeRight].Weight := xlMedium; exl.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideVertical].Weight := xlThin; exl.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideHorizontal].Weight := xlThin; //заполняем продуктами и еденицами измерения sheet.Range[sheet.cells[24,2],sheet.cells[kdy,14]].value:= ArrayData; sheet.Range[sheet.cells[24,15],sheet.cells[kdy,17]].value:= ArrayData1;//в зависимости от фильтра по дате заполняем шапку датами начала периода и конца периода if check=false then sheet.cells[8,27].value:=ArrayData2[1,1]+' - '+ArrayData2[x,1] else sheet.cells[8,27].value:=DateToStr(date_start)+' - '+DateToStr(date_end);// заполняем таблицу датамиdm.ADOQuery_print.First;for i:=1 to x do begin sheet.cells[17,14+i*4].value:= dm.ADOQuery_print.fieldbyname('date_prihoda').AsString; if dm.ADOQuery_print.eof<>true then dm.ADOQuery_print.next; end;//запрос на выбор продукта, единицы измерения, даты прихода и суммы//формируем запрос и заполняем таблицу даннымиdm.ADOQuery_print.Active:=false;dm.ADOQuery_print.SQL.Clear;dm.ADOQuery_print.SQL.Add('SELECT products.product_name, ed_izmer.ed_name, prihod.date_prihoda, Sum(storage.quantity) AS [Sum-quantity]'+' FROM prihod LEFT JOIN ((storage LEFT JOIN products ON storage.id_product = products.id) LEFT JOIN ed_izmer ON storage.id_ed_izmer = ed_izmer.id) ON prihod.id = storage.id_prihod'+' GROUP BY products.product_name, ed_izmer.ed_name, prihod.date_prihoda ORDER BY prihod.date_prihoda; ');dm.ADOQuery_print.Active:=True; dm.ADOQuery_print.First;for m:=1 to y*2 do for n:=1 to x do if (m mod 2)<>0 then begin //выбираем продукт и единицу измерения и ищем совпадение по дате прихода if (dm.ADOQuery_print.Locate('product_name;ed_name;date_prihoda', VarArrayOf([ArrayData[m,1], ArrayData1[m,1],ArrayData2[n,1]]),[loCaseInsensitive, loPartialKey])) then begin sheet.cells[23+m,14+n*4].value:= dm.ADOQuery_print.fieldbyname('Sum-quantity').Value; end; end;
//показываем excel exl.visible:=true;//освобождаем память и интерфейс excelArrayData := Unassigned;ArrayData1 := Unassigned;ArrayData2 := Unassigned;Sheet := Unassigned;WorkBook := Unassigned;exl := Unassigned;Except//в случае ошибки освобождаем ресурсыshowmessage('Внимание! Произошла ошибка при создании отчета');exl.DisplayAlerts := False; // отключаем предупрежденияexl.Workbooks.Close; // закроем все книгиexl.Application.quit;ArrayData := Unassigned;ArrayData1 := Unassigned;ArrayData2 := Unassigned;Sheet := Unassigned;WorkBook := Unassigned;exl := Unassigned;end;end;//печать расхода procedure print_rashod(date_start,date_end:TDateTime;check:boolean);var ArrayData,ArrayData1,ArrayData2: Variant; x,y,kdx,ndx,ndy,kdy,n,m,i:integer; //ndx, ndy -начало диапазона по оси х (вправо) и по оси у (вниз) //kdx, kdy -конец диапазона по оси х и по оси у // ArrayData - двухмерный массив для продуктов // ArrayData1 - двухмерный массив для единиц измерения // ArrayData2 - массив для датbegin if CreateApplication('\Шаблоны\Ведомость расхода продуктов.xlt')=false then exit; try//делаем запрос на выбор продуктов и единиц измерения прихода//и заполняем вариантный массив для продуктов и для единиц измеренияdm.ADOQuery_print.Active:=false;dm.ADOQuery_print.SQL.Clear;dm.ADOQuery_print.SQL.Add('SELECT products.product_name, ed_izmer.ed_name FROM rashod_doc LEFT JOIN ((rashod LEFT JOIN products ON rashod.id_product = products.id) LEFT JOIN ed_izmer'+' ON rashod.id_ed_izmer = ed_izmer.id) ON rashod_doc.id = rashod.id_rashod_doc GROUP BY products.product_name, ed_izmer.ed_name;');dm.ADOQuery_print.Active:=True;y:=dm.print.DataSet.RecordCount;//количество записей по продуктам в приходеArrayData := VarArrayCreate([1, y*2,1,1], varVariant); //двухмерный массив для
продуктовArrayData1 := VarArrayCreate([1, y*2,1,1], varVariant); //двухмерный массив для единиц измерения dm.ADOQuery_print.First; for i:=1 to y*2 do //умножаем на два так как в шаблоне для наименования продукта //используется высота ячейки в две клетки, приходится первую заполнять, а вторую пропускать begin if (i mod 2)<>0 then begin //шаг - каждый второй ArrayData[i,1] := dm.ADOQuery_print.FieldByName('product_name').AsString; //заполняем продукт ArrayData[i+1,1] :=''; // оставляем пустой ArrayData1[i,1] := dm.ADOQuery_print.FieldByName('ed_name').AsString; //заполняем единицу измерения ArrayData1[i+1,1] :='';// оставляем пустой if dm.ADOQuery_print.eof<>true then dm.ADOQuery_print.next; end; end;//выполняем запрос на выбор даты прихода и заполняем вариантный массив2 dm.ADOQuery_print.Active:=false;dm.ADOQuery_print.SQL.Clear;//проверяем включен ли фильтр и формируем соответствующий запрос по дате или безif check=false then dm.ADOQuery_print.SQL.Add('SELECT rashod_doc.date_rashoda FROM rashod_doc GROUP BY rashod_doc.date_rashoda ORDER BY rashod_doc.date_rashoda;') else begin dm.ADOQuery_print.Parameters.AddParameter.Name:='date1'; dm.ADOQuery_print.Parameters.ParamByName('date1').DataType:=ftDateTime; dm.ADOQuery_print.Parameters.AddParameter.Name:='date2'; dm.ADOQuery_print.Parameters.ParamByName('date2').DataType:=ftDateTime; dm.ADOQuery_print.SQL.Add('SELECT rashod_doc.date_rashoda FROM rashod_doc GROUP BY rashod_doc.date_rashoda HAVING (((rashod_doc.date_rashoda)>=:date1 and (rashod_doc.date_rashoda)<=:date2)) ORDER BY rashod_doc.date_rashoda; '); dm.ADOQuery_print.Parameters.ParamByName('date1').Value:=date_start; dm.ADOQuery_print.Parameters.ParamByName('date2').Value:=date_end; end;dm.ADOQuery_print.Active:=True;x:=dm.print.DataSet.RecordCount;//количество записей датArrayData2 := VarArrayCreate([1, x,1,1], varVariant);//массив для датdm.ADOQuery_print.First;for i:=1 to x do begin //заполняем массив датами ArrayData2[i,1] :=dm.ADOQuery_print.FieldByName('date_rashoda').AsString; if dm.ADOQuery_print.eof<>true then dm.ADOQuery_print.next; end;
// рисуем поле данных ndy:=24; ndx:=18; kdx:=18+x*4-1; kdy:=25; //выделение диапазона ячеек sheet.Range[sheet.cells[24,18],sheet.cells[25,21]].Select; //объеденение ячеек sheet.Range[sheet.cells[24,18],sheet.cells[25,21]].Merge; //рисуем поле с цифрами ndy:=23; ndx:=18; kdx:=18+x*4-1; kdy:=23; sheet.Range[sheet.cells[23,18],sheet.cells[23,21]].Select; sheet.Range[sheet.cells[23,18],sheet.cells[23,21]].Merge; Exl.Selection.HorizontalAlignment:=xlCenter; sheet.cells[23,18].value:=3; //рисуем поле с датами ndy:=17; ndx:=18; kdx:=18+x*4-1; kdy:=22; sheet.Range[sheet.cells[17,18],sheet.cells[22,21]].Select; sheet.Range[sheet.cells[17,18],sheet.cells[22,21]].Merge; exl.Selection.Orientation := 90; Exl.Selection.HorizontalAlignment:=xlCenter; Exl.Selection.VerticalAlignment:=xlCenter; //общее выделение и размножение вправо if x>1 then begin ndy:=17; ndx:=18; kdx:=18+x*4-1; kdy:=25; sheet.Range[sheet.cells[17,18],sheet.cells[25,21]].Select; //автозаполнение выделенного диапазона exl.selection.autofill(sheet.Range[sheet.cells[ndy,ndx], sheet.cells[kdy,kdx]], xlFillDefault); end; //рисуем шапку над датой ndy:=15; ndx:=18; kdx:=18+x*4-1; kdy:=16; sheet.Range[sheet.cells[15,18],sheet.cells[16,kdx]].Select; sheet.Range[sheet.cells[15,18],sheet.cells[16,kdx]].Merge; // рисуем поле итоги sheet.Range[sheet.cells[15,kdx+1],sheet.cells[22,kdx+5]].Select; sheet.Range[sheet.cells[15,kdx+1],sheet.cells[22,kdx+5]].Merge; sheet.cells[15,kdx+1].value:='Итого'; Exl.Selection.HorizontalAlignment:=xlCenter; sheet.Range[sheet.cells[23,kdx+1],sheet.cells[23,kdx+5]].Select; sheet.Range[sheet.cells[23,kdx+1],sheet.cells[23,kdx+5]].Merge; sheet.cells[23,kdx+1].value:=3+x; Exl.Selection.HorizontalAlignment:=xlCenter; sheet.Range[sheet.cells[24,kdx+1],sheet.cells[25,kdx+5]].Select; sheet.Range[sheet.cells[24,kdx+1],sheet.cells[25,kdx+5]].Merge; //вводим формулу суммы
sheet.cells[24,kdx+1].value:='=SUM(RC[-'+inttostr(x*4)+']:R[1]C[-1])'; //выделяем и рисуем границы шапки таблицы sheet.Range[sheet.cells[15,18],sheet.cells[23,kdx+5]].Select; exl.Selection.Borders[xlEdgeLeft].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeLeft].Weight := xlMedium; exl.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeTop].Weight := xlMedium; exl.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeBottom].Weight := xlMedium; exl.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeRight].Weight := xlMedium; exl.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideVertical].Weight := xlMedium; exl.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideHorizontal].Weight := xlMedium; ndy:=24; ndx:=2; kdx:=18+x*4-1; kdy:=24+y*2-1; //общее выделение и размножение вниз if y>1 then begin sheet.Range[sheet.cells[ndy,ndx], sheet.cells[ndy+1,kdx+5]].Select; exl.selection.autofill(sheet.Range[sheet.cells[ndy,ndx], sheet.cells[kdy,kdx+5]], xlfillcopy); end; //выделяем и рисуем границы данныx sheet.Range[sheet.cells[24,18],sheet.cells[kdy,kdx+5]].Select; exl.Selection.NumberFormat:='0,000'; exl.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeTop].Weight := xlMedium; exl.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeBottom].Weight := xlMedium; exl.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeRight].Weight := xlMedium; exl.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideVertical].Weight := xlThin; exl.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideHorizontal].Weight := xlThin; //заполняем продуктами и еденицами измерения sheet.Range[sheet.cells[24,2],sheet.cells[kdy,14]].value:= ArrayData; sheet.Range[sheet.cells[24,15],sheet.cells[kdy,17]].value:= ArrayData1;//в зависимости от фильтра по дате заполняем шапку датами начала периода и конца периода if check=false then sheet.cells[8,27].value:= ArrayData2[1,1]+' - '+ ArrayData2[x,1] else sheet.cells[8,27].value:= DateToStr(date_start) + ' - ' + DateToStr(date_end);// заполняем таблицу датами dm.ADOQuery_print.First;for i:=1 to x do begin sheet.cells[17,14+i*4].value:=
dm.ADOQuery_print.fieldbyname('date_rashoda').AsString; if dm.ADOQuery_print.eof<>true then dm.ADOQuery_print.next; end;//запрос на выбор продукта, единицы измерения, даты расхода и суммы//формируем запрос и заполняем таблицу даннымиdm.ADOQuery_print.Active:=false;dm.ADOQuery_print.SQL.Clear;dm.ADOQuery_print.SQL.Add('SELECT products.product_name, ed_izmer.ed_name, rashod_doc.date_rashoda, Sum(rashod.quantity) AS [Sum-quantity]'+' FROM rashod_doc LEFT JOIN ((rashod LEFT JOIN products ON rashod.id_product = products.id) LEFT JOIN ed_izmer ON rashod.id_ed_izmer = ed_izmer.id) ON rashod_doc.id = rashod.id_rashod_doc'+' GROUP BY products.product_name, ed_izmer.ed_name, rashod_doc.date_rashoda ORDER BY rashod_doc.date_rashoda; ');dm.ADOQuery_print.Active:=True; dm.ADOQuery_print.First;for m:=1 to y*2 do for n:=1 to x do if (m mod 2)<>0 then begin //выбираем продукт и единицу измерения и ищем совпадение по дате расхода if (dm.ADOQuery_print.Locate('product_name;ed_name;date_rashoda', VarArrayOf([ArrayData[m,1], ArrayData1[m,1], ArrayData2[n,1]]), [loCaseInsensitive, loPartialKey])) then begin sheet.cells[23+m,14+n*4].value:=dm.ADOQuery_print.fieldbyname('Sum-quantity').Value; end; end;//показываем excel exl.visible:=true;//освобождаем память и интерфейс excelArrayData := Unassigned;ArrayData1 := Unassigned;ArrayData2 := Unassigned;Sheet := Unassigned;WorkBook := Unassigned;exl := Unassigned;Except//в случае ошибки освобождаем ресурсыshowmessage('Внимание! Произошла ошибка при создании отчета');exl.DisplayAlerts := False; // отключаем предупрежденияexl.Workbooks.Close; // закроем все книгиexl.Application.quit;ArrayData := Unassigned;ArrayData1 := Unassigned;ArrayData2 := Unassigned;Sheet := Unassigned;WorkBook := Unassigned;exl := Unassigned;
end;end;//Печать остатков на складе procedure print_ostatki;var ArrayData: Variant; i:integer;begin//если остатков нет выходимif dm.ostatki.DataSet.RecordCount=0 then begin showmessage('На складе нет остатков'); exit;end;//создаем интерфейс Excelif CreateApplication('\Шаблоны\Остатки на складе.xlt')=false then exit;trybegin//объявляем вариантный массив ArrayData := VarArrayCreate([1, dm.ostatki.DataSet.RecordCount,1,6], varVariant); dm.ADOQuery_ostatki.First; for i:= 1 to dm.ostatki.DataSet.RecordCount do begin //Заполняем вариантный массив данными из запроса остатки ArrayData[i,1] :=i; ArrayData[i,2] :=dm.ADOQuery_ostatki.FieldByName('product_name').Value; ArrayData[i,3] :=dm.ADOQuery_ostatki.FieldByName('ed_name').Value; ArrayData[i,4] :=dm.ADOQuery_ostatki.FieldByName('ostatok').Value; ArrayData[i,5] :=dm.ADOQuery_ostatki.FieldByName('summa').Value; ArrayData[i,6] :=dm.ADOQuery_ostatki.FieldByName('sred_price').Value; dm.ADOQuery_ostatki.Next; end;end;//выделяем и рисуем границы данныx sheet.Range['a4','f'+IntToStr(dm.ostatki.DataSet.RecordCount+3)].Select; exl.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeTop].Weight := xlMedium; exl.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeBottom].Weight := xlMedium; exl.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeRight].Weight := xlMedium; exl.Selection.Borders[xlEdgeLeft].LineStyle := xlContinuous; exl.Selection.Borders[xlEdgeLeft].Weight := xlMedium; exl.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideVertical].Weight := xlThin; exl.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous; exl.Selection.Borders[xlInsideHorizontal].Weight := xlThin;//заполняем ячейки таблицы Excel из массива sheet.Range['a4','f'+IntToStr(dm.ostatki.DataSet.RecordCount+3)].value:= ArrayData;
//показываем excelexl.visible:=true;//освобождаем память и интерфейс excelArrayData := Unassigned;Sheet := Unassigned;WorkBook := Unassigned;exl := Unassigned;Except//в случае ошибки освобождаем ресурсыshowmessage('Внимание! Произошла ошибка при создании отчета');exl.DisplayAlerts := False; // отключаем предупрежденияexl.Workbooks.Close; // закроем все книгиexl.Application.quit;ArrayData := Unassigned;Sheet := Unassigned;WorkBook := Unassigned;exl := Unassigned;end; end;end.
На форме приход дважды нажимаем на кнопку печат ь и пишем следующий код для события OnClick:
procedure TForm_prihod.Button4Click(Sender: TObject);var date_start:TDate; date_end:TDate; check:boolean;begin//вызов процедуры печатиif CheckBox1.Checked=True then check:=true else check:=false ;date_start:=(datetimepicker1.Date);date_end:=(datetimepicker2.Date);print_prihod(date_start,date_end,check);end;
Не забываем прописать модуль print в uses для формы прихода uses general, unit_dm, prihod_prod, print.
Аналогично делаем и для формы расхода. Для печати остатков на складе, размещаем на форме кнопку называем ее Печать и по событию OnClick вызываем процедуру печати print_ostatki. Печать справочников вы можете организовать самостоятельно по аналогии с печатью остатков на складе.
Примеры запросов к базе, созданные в конструкторе MS Access, для выбора информации для отчета по приходу я оставил в базе для образца их можно удалить. Запросы называются: ADOQuery_print1 – выбор продуктов и единиц измерения;ADOQuery_print2 – запрос на выбор дат прихода; ADOQuery_print3 – запрос на выбор продукта, единицы измерения, даты прихода и суммы.
Лабораторная работа № 13 Программирование баз данных в Delphi
(Создаем модуль для сжатия и восстановления базы данных).
Как программно сжать базу данных Microsoft Access. Ну во первых операцию по сжатью базы можно выполнить в ручную в самой программе Microsoft Access 2007. Для этого необходимо выполнить действия, показанные на рисунке:
Но нас интересует программный путь. Для этого запускаем наш проект и переходим на главную форму (form_general). Дважды кликаем мышью на компоненте MainMenu1 и создаем пункт меню «Сервис» и подпункт «Сжатие и восстановление базы»:
Затем дважды кликаем на пункте «Сжатие и восстановление базы» и пишем следующий код:
procedure TForm_general.N11Click(Sender: TObject);Var path,db,db1:string;begin
//закрываем формыif (form_general.MDIChildCount)<>0 thenbeginShowMessage('Закройте все формы и повторите операцию.');exit;end;if MessageBox(Handle, 'Вы приступили к сжатию и восстановлению базы данных. Продолжить? ', 'Внимание !!!', MB_YESNO)<> IDYES then exit; //извлекаем путь к базе, в нашем случае это папка с нашим приложением path:=ExtractFilePath(Application.ExeName); db:=path+'storage.mdb'; //закрываем соединение с базой for i:= 0 to ADOConnection1.DataSetCount - 1 do ADOConnection1.DataSets[i].Close; ADOConnection1.Connected:=False; //вызываем процедуру сжатия и восстановления базы CompactDatabase_JRO(db,'','');end;
Возьмите готовый код приведенный ниже. Для его работы добавим в Uses модуль ComObj; uses ……ComObj;
В разделе type процедуру Procedure CompactDatabase_JRO(DatabaseName: String; DestDatabaseName: String=''; Password:String=''), собственно которая и будет сжимать базу.
type…………………..………………….. Procedure CompactDatabase_JRO(DatabaseName: String; DestDatabaseName: String=''; Password:String='');
В разделе implementation добавим код самой процедуры: implementation{$R *.dfm}Uses ed_izmer,product_group,postav_ik,products,prihod,ostatki,rashod;procedure TForm_general.CompactDatabase_JRO(DatabaseName: string; DestDatabaseName: string = ''; Password: string = '');const Provider = 'Provider=Microsoft.Jet.OLEDB.4.0;';var TempName: array[0..MAX_PATH] of Char; // имя временного файла TempPath: string; // путь до него Name: string; Src, Dest: WideString; V: Variant;begin try Src := Provider + 'Data Source=' + DatabaseName; if DestDatabaseName <> '' then Name := DestDatabaseName
else begin // выходная база не указана - используем временный файл // получаем путь для временного файла TempPath := ExtractFilePath(DatabaseName); if TempPath = '' then TempPath := GetCurrentDir; //получаем имя временного файла GetTempFileName(PChar(TempPath), 'mdb', 0, TempName); Name := StrPas(TempName); end; DeleteFile(PChar(Name)); // этого файла не должно существовать, удаляем его :)) Dest := Provider + 'Data Source=' + Name; if Password <> '' then begin Src := Src + ';Jet OLEDB:Database Password=' + Password; Dest := Dest + ';Jet OLEDB:Database Password=' + Password; end; V := CreateOleObject('jro.JetEngine'); try V.CompactDatabase(Src, Dest); // сжимаем finally V := 0; end; if DestDatabaseName = '' then begin // т.к. выходная база не указана DeleteFile(PChar(DatabaseName)); //то удаляем не упакованную базу // и переименовываем упакованную базу if RenameFile(Name, DatabaseName) then begin ShowMessage('Процедура сжатию и восстановлению базы данных успешно завершена. Сейчас программа будет закрыта.'); Application.Terminate; end; end; except // выдаем сообщение об исключительной ситуации on E: Exception do ShowMessage(e.message); end;end;
Сохраняем проект. Внимание, при запуске из Delphi данной процедуры будет выскакивать ошибка:
Поэтому прежде, чем запустить проект его необходимо скомпилировать, и закрыть Delphi, а только потом запускать приложение.