rosmetod.rurosmetod.ru/upload/2015/01/20/09-48-35-ramazanova... · Web view2015/01/20  ·...

Preview:

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, а только потом запускать приложение.

Recommended