----In the previous work of the author using Delphi to develop a database, the user put forward such a requirement: to dynamically generate reports based on their own query results and then print them. After much exploration, the author used the method of dynamically generating QuickReport controls to meet the needs of users. This method is explained below, hoping to provide some useful tips for friends who have similar work to do.
1. Basic ideas
----First write some query parameters (such as SQL commands, field names, field widths, etc.) into a temporary file in a certain format. When generating a report, just dynamically generate various QuickReport controls based on the parameters recorded in the temporary file.
2. Program implementation
2.1 Temporary file format
----The format of the temporary file can be customized according to needs. The author uses the INI file format. Delphi provides a TInifile class, which makes it very convenient to operate INI format files in Delphi. There are many articles about the format and specific operations of INI files, so I won’t go into details here. The temporary file format is as follows:
Report.ini
:Report details
[rep_detail]
Title=XXXXX table
: Printing paper settings, 1 is A4 paper, 2 is B5 paper, 3 is 16K
Page=1
: Printing mode, 1 means horizontal printing, 0 means vertical printing.
Orientation=1
:Number of fields included in the report
columns=8
:TQurey component information
[QureyData]
: Contents of the SQL command of the Tqurey component in the QuickReport component
Sql_command=select V_XM,V_JGZW,V_BMMC,V_DWMC,V_DWZW,V_ZY,V_ZC,V_BGDH from Hvzzjg where V_XM LIKE '李%'
[col_0]
Caption=Name
DataFiled=V_XM
Width=60
…
…
2.2 Dynamically generate QuickReport reports
--- The main controls of the report and their main property settings are as follows
Control name | Class name | property | attribute value |
Form_rep | TForm | caption | dynamic report |
QuickRep | TQuickRep | DataSet | REP_QUERY |
DetailBand1 | TQRBand | BandType | rbDetail |
ColumnHeaderBand1 | TQRBand | BandType | rbColumnHeader |
REP_DataSource | TDataSource | DataSet | Rep_Query |
Rep_Query | TQuery | DatabaseName | REPDATABASE |
Rep_Database | TDatabase | Connected | True |
Params.Strings | 'SERVER NAME=XXX 'USER MAME=XXX' 'PASSWord=XXX' | ||
DatabaseName | REPDATABASE |
The controls shown in the table above were created manually in the program. Other controls must be created dynamically in the program.
2.2.2 Main procedures
unit f_rep;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, QuickRpt, QRCtrls, DB, DBTables,PRINTERS,QRPrntr,inifiles,
TeeProcs, TeEngine, DbChart, QRTEE;
type
TForm_rep = class(TForm)
QuickRep: TQuickRep;
DetailBand1: TQRBand;
ColumnHeaderBand1: TQRBand;
REP_DataSource: TDataSource;
REP_QUERY: TQuery;
rep_Database: TDatabase;
procedure TForm_rep.QuickRepAfterPreview(Sender: TObject);//After browsing, release all created components
private
{Private declarations}
public
{Public declarations}
end;
var Form_rep:TForm_Rep;
type //Summary information of the report
C_rep_Summary=record
Title:string;//The title of the report
Page:TQRPaperSize;//The page settings of the report, what type of paper is used
Orientation:TPrinterOrientation;//The page setting of the report, whether it is horizontal or vertical
Columns:integer;//Number of columns included in the report
end;
type
C_Rep_Col_Summary=record//Summary information of report columns
Caption:string;//column name of the report
DataFiled:string;//The field name in the database corresponding to the column of the report
Width:integer;//column width of the report
end;
type
C_Rep_Col_Sum_store=record //Storage summary information of report columns
Caption_array:array of string;
DataFiled_array:array of string;
Width_array:array of integer;
end;
var
rep_Summary:C_rep_Summary;
Rep_Col_Summary:C_Rep_Col_Summary;
Rep_Col_Sum_store:C_Rep_Col_Sum_store;
Colum_Name: array of tQRRichText;
Colum_Data:array of TQRDBRichText;
C_Query:TQuery;
procedure Form_rep_init();
procedure DynCreat_TQRDBText(Colum_Num:integer;Colum_Height:integer;DataSet_Name:TQuery);//Dynamicly create TQRDBText control
procedure DynCreat_TQRRichtext(Colum_Num:integer);//Dynamicly create TQRRichtext control
procedure DynCreat_TQuery(Inifile_Name:Tinifile);//SQL statement to dynamically create TQuery control
procedure Get_PageCount();//Get the total number of printed pages
function Open_IniFile():Tinifile;//Open temporary file
procedure Read_Col_Summary(Inifile_Name:Tinifile);//Read summary information of report columns
procedure Read_Rep_Summary(Inifile_Name:Tinifile);//Read summary information of the report
function rep_chanslateOrientation(var Rep_Orientation:integer):TPrinterOrientation;//Convert the printing mode settings
function rep_chanslatepage(var Rep_Page:integer):TQRPaperSize;//Convert the print page size setting
implementation
{$R *.dfm}
function rep_chanslatepage(var Rep_Page:integer):TQRPaperSize;//Convert the print page type setting
begin
case Rep_Page of
1:begin
result:=A4;
Form_rep.QuickRep.PrinterSettings.PaperSize:=A4;
end;
2:begin
result:=B5;
Form_rep.QuickRep.PrinterSettings.PaperSize:=B5
end;
3:begin
result:=Executive;
Form_rep.QuickRep.PrinterSettings.PaperSize:=Executive;
end;
end;
end;
function rep_chanslateOrientation(var Rep_Orientation:integer):TPrinterOrientation;//Convert the printing mode settings
begin
case Rep_Orientation of
0:begin
result:=poPortrait;//0 is vertical
Form_rep.QuickRep.PrinterSettings.Orientation:=poPortrait;
end;
1:begin
result:=poLandscape;//1 is horizontal
Form_rep.QuickRep.PrinterSettings.Orientation:=poLandscape;
end;
end;
end;
function Open_IniFile():Tinifile;//Open temporary file
var Filename: string;
Ini_Filename:string;
begin
Filename:='Report.ini';
Ini_Filename:=File_Path+Filename;
Result:=Tinifile.Create(Ini_Filename);
end;
procedure Read_Rep_Summary(Inifile_Name:Tinifile);//Read summary information of the report
var Rep_Page,Rep_Orientation:integer;
begin
rep_Page:=Inifile_Name.Readinteger('rep_detail','Page',1);
Rep_Orientation:=Inifile_Name.Readinteger('rep_detail','Orientation',0);
with rep_Summary do
begin
Columns:=Inifile_Name.Readinteger('rep_detail','columns',0);
Title:=Inifile_Name.Readstring('rep_detail','Title','Unnamed report');
page:=rep_chanslatepage(Rep_Page);//Convert the printing page size
Orientation:=rep_chanslateOrientation(Rep_Orientation);//Convert the printing mode settings
end;
end;
procedure Read_Col_Summary(Inifile_Name:Tinifile);//Read summary information of report columns
var i_count:integer;
begin
//Save column information in array
with Rep_Col_Sum_store do
begin
SetLength(Caption_array,rep_Summary.Columns);
SetLength(DataFiled_array,rep_Summary.Columns);
SetLength(Width_array,rep_Summary.Columns);
end;
for i_count:=0 to rep_Summary.Columns-1 do
begin
with Rep_Col_Summary do
begin
Caption:=Inifile_Name.Readstring('col_'+inttostr(i_count),'Caption','Unnamed');
DataFiled:=Inifile_Name.Readstring('col_'+inttostr(i_count),'DataFiled','');
Width:=Inifile_Name.Readinteger('col_'+inttostr(i_count),'Width',0);
end;
with Rep_Col_Sum_store do
begin
Caption_array[i_count]:=Rep_Col_Summary.Caption;
DataFiled_array[i_count]:=Rep_Col_Summary.DataFiled;
Width_array[i_count]:=Rep_Col_Summary.Width;
end;
end;
end;
procedure DynCreat_TQRRichtext(Colum_Num:integer);//Dynamically create a TQRRichtext control, which is used to display the Chinese name of each column in the report
var Colum_Name_list:TStrings;
begin
Colum_Name[Colum_Num]:=tQRRichtext.Create(application); //Create TQRRichtext control
Colum_Name[Colum_Num].Parent:=Form_rep.ColumnHeaderBand1;
Colum_Name[Colum_Num].Frame.DrawTop:=true;
Colum_Name[Colum_Num].Frame.DrawBottom:=true;
Form_rep.ColumnHeaderBand1.Height:=40;
Colum_Name[Colum_Num].Height:=40;
Colum_Name[Colum_Num].Font.Height:=-14;
Colum_Name[Colum_Num].Font.Name:='Hell body';
Colum_Name[Colum_Num].Top:=0;
Colum_Name[Colum_Num].Alignment:=taCenter;
Colum_Name[Colum_Num].AutoStretch:=false;
//Draw table lines
Colum_Name[Colum_Num].Frame.Style:=psSolid;
Colum_Name[Colum_Num].Frame.Width:=1;
Colum_Name[Colum_Num].Frame.DrawRight:=true;
Colum_Name[Colum_Num].Frame.DrawBottom:=true;
if Colum_Num=0 then
begin
Colum_Name[Colum_Num].Frame.DrawLeft:=true;
end;
//Assign the information in the record RRep_Col_Sum_store to Colum_Name
Colum_Name_list:=TStringList.Create;
Colum_Name_list.Add(Rep_Col_Sum_store.Caption_array[Colum_Num]);
Colum_Name[Colum_Num].Lines:=Colum_Name_list;
Colum_Name[Colum_Num].Width:=Rep_Col_Sum_store.Width_array[Colum_Num];
Colum_Name[Colum_Num].Visible:=true;
//Calculate left boundary
if Colum_Num>0 then
Colum_Name[Colum_Num].Left:=Colum_Name[Colum_Num-1].Left+Colum_Name[Colum_Num-1].Width
else
Colum_Name[Colum_Num].Left:=0;
end;
Note: The TQRRichtext control is used here because the TQRRichtext control can automatically wrap lines when the name is too long.
procedure DynCreat_TQRDBText(Colum_Num:integer;Colum_Height:integer;DataSet_Name:TQuery);//Dynamically create a TQRDBText control, which is used to display the value of each column
begin
Colum_Data[Colum_Num]:=tQRDBText.Create(application);
Colum_Data[Colum_Num].Parent:=Form_rep.DetailBand1;
//Set the data set
Colum_Data[Colum_Num].DataSet:=DataSet_Name;
//Set the array Colum_Data.DateField property to the field name in C_Rep_Col_Sum_store
Colum_Data[Colum_Num].DataField:=Rep_Col_Sum_store.DataFiled_array[Colum_Num];
Colum_Data[Colum_Num].Width:=Rep_Col_Sum_store.Width_array[Colum_Num];
Colum_Data[Colum_Num].Height:=Colum_Height;
Form_rep.DetailBand1.Height:=Colum_Height;
Colum_Data[Colum_Num].Top:=0;
Colum_Data[Colum_Num].AutoSize:=false;
Colum_Data[Colum_Num].AutoStretch:=false;
Colum_Data[Colum_Num].WordWrap:=false;
Colum_Data[Colum_Num].Visible:=true;
//Draw table lines
Colum_Data[Colum_Num].Frame.Style:=psSolid;
Colum_Data[Colum_Num].Frame.DrawRight:=true;
Colum_Data[Colum_Num].Frame.DrawBottom:=true;
if Colum_Num=0 then
Colum_Data[Colum_Num].Frame.DrawLeft:=true;
//Calculate left boundary
if Colum_Num>0 then
Colum_Data[Colum_Num].Left:=Colum_Data[Colum_Num-1].Left+Colum_Data[Colum_Num-1].Width
else
Colum_Data[Colum_Num].Left:=0;
end;
procedure DynCreat_TQuery(Inifile_Name:Tinifile);//Dynamicly set the SQL statement of the TQuery control
var
Sql_command:string;
begin
Flag_CreatQuery:=false;
Sql_command:=Inifile_Name.Readstring('QureyData','Sql_Command','');
Form_rep.REP_QUERY.Close;
Form_rep.REP_QUERY.SQL.Clear;
Form_rep.REP_QUERY.SQL.Append(Sql_command);
if not Form_rep.REP_QUERY.Prepared then
Form_rep.REP_QUERY.Prepare;
try
Form_rep.REP_QUERY.ExecSQL;
Form_rep.REP_QUERY.Active:=true;
Form_rep.REP_QUERY.AutoCalcFields:=true;
Flag_CreatQuery:=true;
except
Application.MessageBox('SQL statement error!','System prompt',MB_ICONWARNING);
Flag_CreatQuery:=false;
end;
end;
procedure Form_rep_init();
var i_count:integer;
Rep_IniFile:Tinifile;//