Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
laboratornye_raboty.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
2.27 Mб
Скачать

Практическая часть

На этом уроке мы реализуем  печать данных прихода, расхода и состояния склада.  Печать будем реализовывать через MS Excel, то есть это будет не совсем печать, а экспорт данных в MS Excel, а там пользователь может сам выбрать, печатать или сохранить отчет. В начале приготовим шаблоны  MS Excel, в которые будем выводить отчеты. Шаблон ведомость по приходу продуктов питания.

    В шаблоне использован стиль ссылок R1C1. Включается Параметры->Формулы-> Стиль ссылок R1C1. Файл сохраняем с типом файла Шаблон Excel 97-2003. Результат работы программы:

Шаблон ведомость по расходу продуктов питания.

Шаблон остатки на складе.

  Далее в формы прихода и расхода внесем несколько изменений, необходимых для фильтрации документов прихода и расхода по дате. Добавим на формы прихода и расхода по два компонента TDateTimePicker из вкладки Win32 и компонент  TCheckBox из вкладки Standart.  Кнопку  Button для вызова печати. Размещаем, как показано на рисунке:

Аналогично для формы расхода. В инспекторе объектов для обеих DateTimePicker ов обнуляем свойство Time. А для  события OnChange прописываем следующий код:

procedure TForm_prihod.DateTimePicker1Change(Sender: TObject); begin //Проверка установленных дат if datetimepicker1.Date>datetimepicker2.Date then begin ShowMessage('Внимание. Начальная дата прихода больше конечной'); 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 then begin ShowMessage('Внимание. Начальная дата прихода больше конечной'); checkbox1.Checked:=false; DateTimePicker1.Date:=DateUtils.StartOfTheMonth(now); DateTimePicker2.Date:=date; end; end;

А для события OnClick компонента CheckBox1 пишем:

procedure TForm_prihod. Click(Sender: TObject); //включение фильтра begin dm.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 //установка начальных значений дат  DateTimePicker DateTimePicker1.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; interface Uses 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; //создаем приложение excel begin try   //Создаем объект интерфейса для доступа к серверу COM   exl := CreateOleObject('Excel.Application');   // Отключаем реакцию Excel на события,   //чтобы ускорить вывод информации   exl.Application.EnableEvents := false;   //Создаем книгу и обращаемся к первому листу   Workbook := exl.Application.WorkBooks.Add(GetCurrentDir()+FileName);   Sheet := WorkBook.WorkSheets[1];   result:=true; Except showmessage('Внимание! Произошла ошибка при создании MS Excel приложения'); result:=false; //освобождаем интерфейсы 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; //освобождаем память и интерфейс excel ArrayData := 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; //освобождаем память и интерфейс excel ArrayData := 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; //создаем интерфейс Excel if CreateApplication('\Шаблоны\Остатки на складе.xlt')=false then exit; try begin //объявляем вариантный массив  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; //показываем excel exl.visible:=true; //освобождаем память и интерфейс excel ArrayData := 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 – запрос на выбор продукта, единицы измерения, даты прихода и суммы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]