---- The author uses the Delphi development database in the previous paragraph, the user puts forward such a requirement: to dynamically generate reports based on their own query results and then print. After several exploits, the author uses the dynamically generated QuickReport control to meet the needs of users. This method will now be described below, I hope to provide a good choice for friends who have similar work to be made.
First, basic ideas
---- Some parameters (such as SQL commands, field names, field widths, etc.) are first written in a temporary file in a certain format. When generating a report, dynamically generate a variety of QuickReport controls according to the parameters recorded in the temporary file.
Second, the program is realized
2.1 Temporary File Format
---- The format of the temporary file can be customized as needed, and the author uses INI's file format. Delphi provides a TiniFile class that makes an Ini format file in Delphi, which is very convenient. There are many articles about the format of the INI file and specific operations. I will not go here. The temporary file format is as follows:
Report.ini
: Report Details
[rep_detail]
Title = xxxxx table
: Playing paper setting, 1 is A4 paper, 2 is B5 paper, 3 is 16K
Page = 1
: Printing method, 1 is horing, 0 is vertical
Orientation = 1
: The number of fields containing the fields
Column = 8
: TQurey component information
[QureyData]
: The content 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 'Lee%'
[col_0]
CAPTION = last name
DataFiled = v_xm
Width = 60
......
......
2.2 Dynamic Generation QuickReport Report
--- The main control of the report and its main attribute settings are as follows
Name of the control class name attribute property value Form_rep TForm caption dynamic reports 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 control shown above is manually created in the program. Other controls are dynamically created 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, Tengine, Dbchart, QRTEE
Type
TFORM_REP = Class (TFORM)
QuickRep: tquickrep;
Detailband1: tQRBAND;
ColumnHeaderband1: tqrband; rep_datasource: tdataserce;
REP_QUERY: TQUERY;
Rep_DATABASE: TDATABASE;
Procedure TFORM_REP.QUICKREPAFTERPREVIEW (Sender: TOBJECT); // Browse, release all created components
Private
{Private Declarations}
public
{Public declarations}
END;
Var form_rep: tform_rep;
Summary information of Type // Report
C_rep_summary = record
Title: String; // Report title
Page: TQRPAPERSIZE; / / Report page settings, use the model of paper
Orientation: tprinterorientation; // The page settings of the report are hosted or vertical
Columns: integer; // The number of columns included
END;
Type
C_REP_COL_SUMMARY = Record // Summary information of the report column
CAPTION: STRING; // Report column name
DataFiled: String; // The list of fields in the list of reports corresponding to the list of fields
Width: integer; // Reporting column width
END;
Type
C_rep_col_sum_store = record // Store summary information of the report
CAPTION_ARRY: 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; color; dataset_name: tquery); // Dynamically create TQRDBText control
Procedure Dyncreat_tqrrichtext (colum_num: integer); // Dynamically create TQRRICHText control
Procedure Dyncreat_tquery (Inifile_name: tinifile); // Dynamically create the SQL statement for the TQUERY control
Procedure get_pagecount (); // Get the total number of prints
Function open_inifile (): tinifile; // Open temporary file
Procedure read_col_summary (inIfile_name: tinifile); // Read the summary information of the report column
Procedure read_rep_summary (inIfile_name: tinifile); // Read the summary information of the report
Function rep_chanslateorientation (var rep_orientation: integer): tprinterorientation; // Convert the print mode setting
Function rep_chanslatepage (var rep_page: integer): tqrpapersize; // Transfer page size settings
IMPLEMENTATION
{$ R * .dfm}
Function rep_chanslate (var rep_page: integer): tqrpapersize; // Convert the Print Page Type Settings
BEGINCASE 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 print mode setting
Begin
Case rep_orientation of
0: Begin
Result: = poporTrait; // 0 is vertical
Form_rep.quickrep.printersettings.orient: = poporTrait;
END;
1: Begin
Result: = polandscape; // 1 is level
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 the 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', 'colorns', 0);
Title: = INIFILE_NAME.Readstring ('rep_detail', 'title', 'unnamed report');
Page: = rep_chanslatepage (rep_page); // Convert the print page size
Orientation: = rep_chanslateorientation (rep_orientation); // Convert the print mode setting
END;
END;
Procedure read_col_summary (inIfile_name: tinifile); // Read the summary information of the report column
Var i_count: integer;
Begin
// Save the column information in the 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 _' INTOSTR (i_count), 'caption', 'unnamed');
DataFile: = INIFILE_NAME.Readstring ('COL _' INTOSTR (i_count), 'DataFiled', '');
Width: = INIFILE_NAME.Readinteger ('COL _' INTOSTR (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 (color_num: integer); // Dynamically create TQRRICHTEXT controls, this control is used to display the Chinese name of each column of reports
Var colum_name_list: tstrings;
Begin
Colum_name [colum_num]: = tqrichtext.create (Application); // Create a 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: = 'black body';
Colum_name [color_num] .top: = 0;
Colum_name [colum_num] .alignment: = Tacenter;
COLUM_NAME [colum_num] .autostradch: = FALSE
// Painted Table Line
Colum_name [colum_num] .frame.style: = pssolid;
Colum_name [color_num] .frame.width: = 1;
Colum_name [colum_num] .frame.drawright: = true;
Colum_name [colum_num] .frame.drawbottom: = true;
IF color_num = 0 THEN
Begin
Colum_name [colum_num] .frame.drawleft: = true;
END;
// Put the information in the RREP_COL_SUM_STORE to colum_name
COLUM_NAME_LIST: = TStringList.create;
Colum_name_list.add (rep_col_sum_store.caption_Array [color_num]); colum_name [color_num] .line: = colum_name_list;
Colum_name [colum_num] .width: = rep_col_sum_store.width_Array [color_num];
Colum_name [color_num] .visible: = true;
// calculate the left boundary
IF colum_num> 0 THEN
Colum_name [colum_num] .left: = colum_name [color_num-1] .left color_name [colum_num-1] .width
Else
COLUM_NAME [Colum_Num] .left: = 0;
END;
Description: This TQRRICHTEXT control is used here because the TQRRICHText control can be automatically wrap when the name is too long.
Procedure Dyncreat_tqrdbtext (colum_num: integer; color; dataset_name: tQuery); // Dynamically create TQRDBText control, this control is used to display the value of each column
Begin
Colum_data [color_num]: = tqrdbtext.create (application);
Colum_data [color_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 [color_num] .height: = colum_height;
Form_rep.detailband1.height: = colum_height;
Colum_data [color_num] .top: = 0;
Colum_data [colum_num] .autosize: = false;
Colum_data [colum_num] .autostradch: = false;
Colum_data [colum_num] .WordWrap: = false;
Colum_data [colum_num] .visible: = true;
// Painted Table Line
Colum_data [colum_num] .frame.style: = pssolid;
Colum_data [color_num] .frame.drawright: = true;
Colum_data [colum_num] .frame.drawbottom: = true;
IF color_num = 0 THEN
Colum_data [colum_num] .frame.drawleft: = true;
// calculate the left boundary
IF colum_num> 0 THEN
Colum_data [colum_num] .left: = colum_data [color_num-1] .left color_data [colum_num-1] .width
Else
Colum_data [color_num] .left: = 0;
END;
Procedure Dyncreat_tquery (InIfile_name: tinifile); // Dynamically set the SQL statement VAR of the TQUERY control
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; / / Open INI file name
COL_HEIGHT: INTEGER;
Flag_sum: boolean;
Begin
Rep_INIFILE: = Open_INIFILE); // Open a temporary file file
Read_rep_summary (rep_inifile); // Read Summary Information for Reports
Read_col_summary (rep_inifile); // Read summary information of the report column
/ / Dynamically create a report control based on the parameters of the report read
WITH FORM_REP DO
Begin
Flag_creattqrexpr: = false; // Indicates that there is no TQREXPR control yet
Dyncreat_tquery (rep_inifile);
IF flag_creatquery then
Begin
QRLABEL_TITLE.CAPTION: = rep_summary.title;
QRLABEL_HEADER.CAPTION: = rep_summary.title;
// Set page information
Quickrep.page.orientation: = rep_summary.orientation;
Quickrep.page.papersize: = rep_summary.page;
SetLength (Colum_Data, Rep_SUMMARY.COLUMNS);
SetLength (colum_name, rep_summary.columns);
For i_count: = 0 to rep_summary.columns-1 do
Begin
DyncReat_tqrrichtext (i_count); // Dynamically create TQRRICHText control
DyncReat_tqrdbrichtext (i_count, col_height, form_rep.rep_query) // Dynamically create TQRDBText control
END;
// Turn the rep_x.ini file
Rep_inifile.destroy ();
end
Else
Form_rep.close;
END;
END;
Procedure tform_rep.quickRepAfterPreview (sender: TOBJECT); // Browse, release all created components VAR i_count: integer;
Begin
For i_count: = 0 to rep_summary.columns-1 do
BEGIN
COLUM_NAME [i_count] .free;
Colum_data [i_count] .free;
END;
END;
End.
Third, the problem that needs attention
---- Drawing the table line in QuickReport, except for the method mentioned in the article, you can use the QRSHAPE control. However, regardless of that the method is used, it must be carefully calculated. If you need to adjust it according to the effect of the print, you can ensure that the table line does not produce a deviation.
---- After all dynamically created controls, must be released.
---- Temporary files are also emptied after use.
---- The program shown above is merely the routine that the author is simplified in order to illustrate the idea. In the actual application of the author, all used controls (including forms form) are dynamically generated. And when you generate a report, you can also dynamically generate statistics, insert charts, etc., interested friends can send a letter to chief_marshal@sina.com and I discuss details.