As part of the FastReport report generator, which is integrated into the My Visual Database development environment, there is a component for displaying QR codes, which allows you to create stickers, payment documents, advertisements that may contain QR codes in the developed programs. But sometimes such code needs to be displayed directly on the form.

It is high time to add a universal procedure for calling reports programmatically into the ClearApp demo project, which in practice gives more possibilities than the standard button with Action = [Report]. To do this, I created a separate Report.pas module, in which I placed my Report_Open() procedure, formerly known as OpenReport(). The new name corresponds to the concept of naming procedures and functions, which implies that the name must begin with the name of the module.

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);
// programmatically open the report
//
// options:
// ADataSets - datasets
// ADSNames - dataset names
// AStrParam - parameter values
// AReportMode - open mode
// AStrParamName - parameter names
// AReportFileName - report name
// AReportDir - folder with reports
// AFileName - file name for export
// AResolution - image resolution
// AJPEGQuality - JPEG compression level
var
   i: integer;
   frxDBDatasets: array of TfrxDBDataset;

   procedure SetParam;
   var
     i: integer;
   begin
     // passing parameters as variables - after loading the report!
     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
   // folder with reports by default
   if AReportDir = '' then
     AReportDir := ExtractFileDir(Application.ExeName) + '\Report\';
   // create datasets
   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;
   // preparing of report
   Report.Clear;
   Report.DataSets.Clear;
   for i := 0 to Length(ADataSets) - 1 do
   begin
     Report.DataSets.Add(frxDBDatasets[i]);
   end;
   // depending on the setting of the global variable, select the mode
   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;
         // prepare report for export
         Report.PrepareReport;
         // don't show the export dialog
         PDFExport.ShowDialog := False;
         // if the file name is not specified, then
         if AFileName = '' then
           AFileName := GetTmpFilename('.pdf');
         // the report file will be created in a temporary folder with a random name
         PDFExport.FileName := AFileName;
         // options to embed fonts in the document
         PDFExport.EmbeddedFonts := True;
         PDFExport.PrintOptimized := True;
         PDFExport.Background := True; // save background
         PDFExport.OpenAfterExport := False; // do not open after export
         PDFExport.ShowProgress := False; // don't show progress
         // PDFExport.Transparency := True; // export transparent
         // export to PDF
         Report.Export(PDFExport);
       end;
     RM_EXCEL:
       begin
         CloseDS;
         Report.LoadFromFile(AReportDir + AReportFileName);
         SetParam;
         // prepare report for export
         Report.PrepareReport;
         // don't show the export dialog
         XLSExport.ShowDialog := False;
         // if the file name is not specified, then
         if AFileName = '' then
           AFileName := GetTmpFilename('.xlsx');
         // the report file will be created in a temporary folder with a random name
         XLSExport.FileName := AFileName;
         // export to PDF
         Report.Export(XLSExport);
       end;
     RM_JPEG:
       begin
         CloseDS;
         Report.LoadFromFile(AReportDir + AReportFileName);
         SetParam;
         // prepare report for export
         Report.PrepareReport;
         //
         JPEGExport.JPEGQuality := AJPEGQuality;
         JPEGExport.Resolution := AResolution;
         JPEGExport.SeparateFiles := False;
         JPEGExport.ShowDialog := False;
         // if the file name is not specified, then
         if AFileName = '' then
           AFileName := GetTmpFilename('.jpg');
         JPEGExport.FileName := AFileName;
         // export
         Report.Export(JPEGExport);
       end;
   end;
   // cleanup
   FreeDS;
   except
     RaiseException('procedure Report_Open(): '+ExceptionMessage );
   end;
end;Code language: Delphi (delphi)

The procedure allows you to run the generator in various modes: layout editing, viewing, and also export to various formats: PDF, Excel, JPEG. We will use the last mode to solve the task – displaying a QR code on the application form. To do this, we need the auxiliary procedure Report_QR_Make() , which is necessary to create a file with a QR code image, as well as a small report containing a component for generating it.

function Report_QR_Make ( AText:string; AReportFileName:string = ''; AReportMode:integer = -1 ):string;
// creates a jpeg file with a QR code
// for the procedure to work, a special report QR.fr3 or its equivalent is needed
var
   tmpDataSets : array of TDataSet;
   tmpDSNames: array of string;
   tmpStrParam: array of string;
   tmpStrParamName: array of string;
   tmpFileName:string;
   i: integer;
begin
   try
     // control of valid values for the report mode
     case AReportMode of
     -1: AReportMode := RM_JPEG; // default
     RM_DESIGN,RM_JPEG: AReportMode := AReportMode; // allowed values
     else
       RaiseException('function Report_QR_Make(): Invalid value AReportMode = '+IntToStr(AReportMode) );
     end;
     // need a special report with a QR code generation component
     if AReportFileName = '' then
       AReportFileName := 'QR.fr3';
     // do not connect to the database
     SetLength( tmpDataSets,0 );
     SetLength( tmpDSNames, 0 );
     // text to create the code is passed as a parameter
     SetLength(tmpStrParam, 1); // festival dates and city
     SetLength( tmpStrParamName, 1 );
     // options
     i := 0;
     // Text for code
     tmpStrParamName[i] := 'TextData';
     tmpStrParam[i] := AText;
     inc(i);
     // we need a temporary file
     tmpFileName := GetTmpFilename('.jpg');
     // call the universal report opening function
     Report_Open( tmpDataSets, tmpDSNames, tmpStrParam, tmpStrParamName, AReportMode, AReportFileName, '', tmpFileName );
     // if the designer was called first, then run the converter again
     if AReportMode = RM_DESIGN then
       Report_Open( tmpDataSets, tmpDSNames, tmpStrParam, tmpStrParamName, RM_JPEG, AReportFileName, '', tmpFileName );
     // clean...
     Report_FreeDataSets( tmpDataSets );
     Result := tmpFileName; // in file - picture
   except
     RaiseException('function Report_QR_Make(): '+ExceptionMessage );
   end;
end;
Code language: Delphi (delphi)

The report is a page with the same size as the QR code. Unfortunately, the integration of the QR code component by the MVDB developer was not carried out completely, which is why it is not possible to control the generator parameters (dot sizes, indents from the edge and encoding type) using a script, that is, when changing the size of the data displayed in the QR code. code, you will need to manually adjust the page size.

At the same time, to transfer data to the component, you will have to write a short script directly in the report itself – an OnAfterData event handler for the QRCode component, in which the value from the TextData parameter is passed to the Text property, which is responsible for the content of the code.

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

To load a QR code into an image, let’s add the Report_QR_Load() procedure, whose task is to create an image file, and after loading it into a component on the form, delete the temporary file.

procedure Report_QR_Load ( AText:string; AImage: TdbImage; AReportFileName: string = ''; AReportMode:integer = -1 );
// uploading a QR code to an image
var
  tmpFilename: string;
begin
  tmpFilename := Report_QR_Make (AText,AReportFileName,AReportMode );
  AImage.Picture.LoadFromFile(tmpFilename);
  DeleteFile(tmpFilename);
end;
Code language: JavaScript (javascript)

In the Report.pas module, you need to place constants that determine the mode of operation of the report generator. Variables responsible for the operation of FastReport can also be transferred there from the AppConstVar.pas module.

uses 'System\Utils.pas', 'VClass\AppConstVar.pas';

const
   // report mode
   RM_DESIGN = 0; // editor
   RM_PREVIEW = 1; // preview
   RM_PDF = 2; // export to PDF
   RM_EXCEL = 3; // export to excel
   RM_JPEG=4; // export to JPG

var
   Report: TfrxReport; // report engine and its elements:
   PDFExport: TfrxPDFExport; // export to PDF
   XLSExport: TfrxXLSExport; // export to XLS
   JPEGExport: TfrxJPEGExport; // export to JPG
Code language: Delphi (delphi)

As an illustration of the use of the above technology, the Report_QR_Demo() procedure is used, which adds a QR code with the website address to the “About” form. The call to this procedure must be added in the UserApp_MainForm_OnShow() procedure or in any other place, after the initialization of system variables, which occurs in the App_InitSystemVar() procedure.

procedure Report_QR_Demo;
// demonstration of loading a QR code into an image
var
   tmpImage: TdbImage;
begin
   // create a picture on the "About" form
   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;
   // load the site address into it
   Report_QR_Load( APP_SITE, tmpImage );
   // you can pass the report name and enable debug mode:
   // Report_QR_Load( APP_SITE, tmpImage, 'QR.fr3',0 );
end;
Code language: Delphi (delphi)
Form “About” with a QR code

Links

CleanApp – archive with source texts (available to library subscribers)

Leave a Reply

Your email address will not be published. Required fields are marked *