В составе генератора отчетов FastReport, который интегрирован в среду разработки My Visual Database, имеется компонент для отображения QR-кодов, что позволяет создавать в разрабатываемых программах стикеры, платежные документы, рекламные объявления, которые могут содержать QR-коды. Но иногда такой код необходимо отобразить непосредственно на форме.

В демонстрационный проект ClearApp давно пора добавить универсальную процедуру программного вызова отчетов, которая на практике дает больше возможностей, чем стандартная кнопка с Action = [Отчет]. Для этого я создал отдельный модуль Report.pas, в который поместил мою процедуру Report_Open(), ранее известную под именем OpenReport(). Новое название соответствует концепции именования процедур и функций, которая подразумевает, что название должно начинаться с имени модуля.

procedure Report_Open(ADataSets: array of TDataSet; ADSNames: array of string; AStrParam: array of string; AStrParamName: array of string; AReportMode: integer; AReportFileName: string; AReportDir: string = ''; AFileName: string = ''; AResolution: integer = 300; AJPEGQuality: integer = 100); // программно открыть отчет // // параметры: // ADataSets - датасеты // ADSNames - названия датасетов // AStrParam - значения параметров // AReportMode - режим открытия // AStrParamName - названия параметров // AReportFileName - название отчета // AReportDir - папка с отчетами // AFileName - имя файла для экспорта // AResolution - разрешение изображения // AJPEGQuality - степень сжатия JPEG var i: integer; frxDBDatasets: array of TfrxDBDataset; procedure SetParam; var i: integer; begin // передача параметров как переменных - после загрузки отчета! Report.Variables.Clear; for i := 0 to Length(AStrParam) - 1 do Report.Variables[AStrParamName[i]] := '''' + AStrParam[i] + ''''; end; procedure CloseDS; var i: integer; begin for i := 0 to Length(ADataSets) - 1 do begin frxDBDatasets[i].DataSet.Close; end; end; procedure FreeDS; var i: integer; begin for i := 0 to Length(ADataSets) - 1 do begin frxDBDatasets[i].Free; end; end; begin try // папка с отчетами по умолчанию if AReportDir = '' then AReportDir := ExtractFileDir(Application.ExeName) + '\Report\'; // создаём датасеты SetLength(frxDBDatasets, Length(ADataSets)); for i := 0 to Length(ADataSets) - 1 do begin frxDBDatasets[i] := TfrxDBDataset.Create(Report.Owner); frxDBDatasets[i].UserName := ADSNames[i]; frxDBDatasets[i].CloseDataSource := True; frxDBDatasets[i].OpenDataSource := True; frxDBDatasets[i].DataSet := ADataSets[i]; end; // подготовка отчета Report.Clear; Report.DataSets.Clear; for i := 0 to Length(ADataSets) - 1 do begin Report.DataSets.Add(frxDBDatasets[i]); end; // в зависимости от настройки глобальной переменной, выбираем режим case AReportMode of RM_DESIGN: begin Report.LoadFromFile(AReportDir + AReportFileName); SetParam; Report.DesignReport; end; RM_PREVIEW: begin CloseDS; Report.LoadFromFile(AReportDir + AReportFileName); SetParam; Report.ShowReport; end; RM_PDF: begin CloseDS; Report.LoadFromFile(AReportDir + AReportFileName); SetParam; // подготовить отчёт к экспорту Report.PrepareReport; // не отображать диалог экспорта PDFExport.ShowDialog := False; // если имя файла не указано, то if AFileName = '' then AFileName := GetTmpFilename('.pdf'); // файл с отчетом будет создан во временной папке со случайным именем PDFExport.FileName := AFileName; // опции, встраивающие шрифты в документ PDFExport.EmbeddedFonts := True; PDFExport.PrintOptimized := True; PDFExport.Background := True; // сохранять фон PDFExport.OpenAfterExport := False; // не открывать после экспорта PDFExport.ShowProgress := False; // не показывать прогресс // PDFExport.Transparency := True; // экспорт прозрачного // экспортировать в PDF Report.Export(PDFExport); end; RM_EXCEL: begin CloseDS; Report.LoadFromFile(AReportDir + AReportFileName); SetParam; // подготовить отчёт к экспорту Report.PrepareReport; // не отображать диалог экспорта XLSExport.ShowDialog := False; // если имя файла не указано, то if AFileName = '' then AFileName := GetTmpFilename('.xlsx'); // файл с отчетом будет создан во временной папке со случайным именем XLSExport.FileName := AFileName; // экспортировать в PDF Report.Export(XLSExport); end; RM_JPEG: begin CloseDS; Report.LoadFromFile(AReportDir + AReportFileName); SetParam; // подготовить отчёт к экспорту Report.PrepareReport; // JPEGExport.JPEGQuality := AJPEGQuality; JPEGExport.Resolution := AResolution; JPEGExport.SeparateFiles := False; JPEGExport.ShowDialog := False; // если имя файла не указано, то if AFileName = '' then AFileName := GetTmpFilename('.jpg'); JPEGExport.FileName := AFileName; // экспортировать Report.Export(JPEGExport); end; end; // зачистка FreeDS; except RaiseException('procedure Report_Open(): '+ExceptionMessage ); end; end;
Code language: Delphi (delphi)

Процедура позволяет запускать генератор в различных режимах: редактирование макета, просмотр, в также экспорт в различные форматы: PDF, Excel, JPEG. Последний режим мы и будем использовать для решения поставленной задачи – отображения QR-кода на форме приложения. Для этого нам потребуется вспомогательная процедура Report_QR_Make() , которая необходима для создания файла с изображением QR-кода, а также небольшой отчет, содержащий компонент для его генерации.

function Report_QR_Make ( AText:string; AReportFileName:string = ''; AReportMode:integer = -1 ):string; // создает jPEG файл с QR-кодом // для работы процедуры нужен специальный отчет QR.fr3 или его аналог var tmpDataSets : array of TDataSet; tmpDSNames: array of string; tmpStrParam: array of string; tmpStrParamName: array of string; tmpFileName: string; i: integer; begin try // контроль допустимых значений для режима отчета case AReportMode of -1: AReportMode := RM_JPEG; // по умолчанию RM_DESIGN,RM_JPEG: AReportMode := AReportMode; // допустимые значения else RaiseException('function Report_QR_Make(): Недопустимое значение AReportMode = '+IntToStr(AReportMode) ); end; // нужен специальный отчет с компонентом генерации QR-кода if AReportFileName = '' then AReportFileName := 'QR.fr3'; // к базе не подключаемся SetLength( tmpDataSets,0 ); SetLength( tmpDSNames, 0 ); // текст для создания кода передаем параметром SetLength( tmpStrParam, 1 ); // даты фестиваля и город SetLength( tmpStrParamName, 1 ); // параметры i := 0; // Текст для кода tmpStrParamName[i] := 'TextData'; tmpStrParam[i] := AText; inc(i); // нам понадобится временный файл tmpFileName := GetTmpFilename('.jpg'); // вызвать универсальную функцию открытия отчета Report_Open( tmpDataSets, tmpDSNames, tmpStrParam, tmpStrParamName, AReportMode, AReportFileName, '', tmpFileName ); // если сначала вызывали дизайнер, то потом ещё раз запустить конвертер if AReportMode = RM_DESIGN then Report_Open( tmpDataSets, tmpDSNames, tmpStrParam, tmpStrParamName, RM_JPEG, AReportFileName, '', tmpFileName ); // чистим... Report_FreeDataSets( tmpDataSets ); Result := tmpFileName; // в файле - картинка except RaiseException('function Report_QR_Make(): '+ExceptionMessage ); end; end;
Code language: Delphi (delphi)

Отчет представляет собой страницу размером, совпадающим с размером QR-кода. К сожалению, интеграция компонента QR-кода разработчиком MVDB была произведена не полностью, из-за чего нет возможности управлять параметрами генератора (размеры точек, отступы от края и тип кодирования) c помощью скрипта, то есть при изменении размера данных, отображаемых в QR-коде, потребуется ручная корректировка размера страницы.

В то же время для передачи данных в компонент придется написать коротки скрипт непосредственно в самом отчете – обработчик события OnAfterData для компонента QRCode, в котором свойству Text, отвечающему за содержимое кода, передаётся значение из параметра TextData.

procedure QRcodeOnAfterData(Sender: TfrxComponent); begin QRcode.Text := <TextData>; end;
Code language: Delphi (delphi)

Для загрузки QR-кода в картинку добавим процедуру Report_QR_Load(), задача которой создать файл изображения, а после его загрузки в компонент на форме, удалить временный файл.

procedure Report_QR_Load ( AText:string; AImage: TdbImage; AReportFileName: string = ''; AReportMode:integer = -1 ); // загрузка QR-кода в картинку var tmpFilename: string; begin tmpFilename := Report_QR_Make (AText,AReportFileName,AReportMode ); AImage.Picture.LoadFromFile(tmpFilename); DeleteFile(tmpFilename); end;
Code language: JavaScript (javascript)

В модуле Report.pas необходимо разместить константы, определяющие режим работы генератора отчетов. Туда же можно перенести из модуля AppConstVar.pas переменные, отвечающие за работу FastReport.

uses 'System\Utils.pas', 'VClass\AppConstVar.pas'; const // режим отчёта RM_DESIGN = 0; // редактор RM_PREVIEW = 1; // предварительный просмотр RM_PDF = 2; // экспорт в PDF RM_EXCEL = 3; // экспорт в Excell RM_JPEG = 4; // экспорт в JPG var Report: TfrxReport; // движок отчетов и его элементы: PDFExport: TfrxPDFExport; // экспорт в PDF XLSExport: TfrxXLSExport; // экспорт в XLS JPEGExport: TfrxJPEGExport; // экспорт в JPG
Code language: Delphi (delphi)

В качестве иллюстрации использования вышеописанной технологии используется процедура Report_QR_Demo(), которая добавляет QR-код с адресом сайта на форму “О программе”. Вызов данной процедуры нужно добавить в процедуре UserApp_MainForm_OnShow() или в любом другом месте, после инициализации системных переменных, которое происходит в процедуре App_InitSystemVar().

procedure Report_QR_Demo; // демонстрация загрузки QR-кода в картинку var tmpImage: TdbImage; begin // создаем картинку на форме "О программе" tmpImage := TdbImage.Create(frmdbCoreAbout); tmpImage.Name := 'imgQRCode'; tmpImage.Parent := frmdbCoreAbout; tmpImage.Width := frmdbCoreAbout.Button1.Width; tmpImage.Height := tmpImage.Width; tmpImage.Proportional := True; tmpImage.Stretch := True; tmpImage.Top := 10; tmpImage.Left := frmdbCoreAbout.Button1.Left; // загружаем в неё адрес сайта Report_QR_Load( APP_SITE, tmpImage ); // можно передавать имя отчета и включать режим отладки: // Report_QR_Load( APP_SITE, tmpImage, 'QR.fr3',0 ); end;
Code language: Delphi (delphi)
Форма “О программе” с QR-кодом

Ссылки

CleanApp – архив с исходными текстами (доступен подписчикам библиотеки)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *