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)
Links
CleanApp – archive with source texts (available to library subscribers)