Author: Liu Jianhua
Delphi program implements real-time generation reports
At present, in the software development tool, Delphi has more controlled, the code execution speed and easy to use, and the code execution speed is high, and the current fastest compiler technology has become a globally recognized fast. Application development tools are being used in more and more programmers. Using Delphi, you can write a variety of Windows applications, especially the developing database information management system has its unique advantage. During the development of the database information management system, we often need to print a lot of reports, using the Delphi design complex report is a more annoying event, which is simple in Visual FoxPro. However, because the design reports in Delphi are also controls, we can generate reports in real time during program execution, and generated report samples can be determined by program control. For example, when we queried in the database information, the results of the results are generally unfair. If we want to print the query results, only a report format is not possible, designing all possible results information Report format is not a good solution. In order to solve such a problem, we can generate report technologies in real time. The purpose of this article is to introduce you to how to generate reports in real time through an example. This example will design a print dialog that includes TqickRep controls and some report style control controls. Other form appearances are shown below: 1. Control Function Description QuickRep: TquickRep It includes a column header (HB: TQRBAND) , Details (DB: TQRBAND), Foot (FB: TQRBAND), Summary (SB: TQRBAND) belt, and details, footer, not included in the summary, which is mainly established when executed Title (TQRLABEL) is included in the column headband area for report titles; QRSQL: TQRLABEL is used for query conditions, which can be arbitrarily changed when the program is executed. In order to allow QuickRep not displayed, it is placed behind Panel1 (TPANEL) and extending Panel1 to the entire form; Query: TQuery SQL statement control, the program will generate a report according to the result returned by Query. Therefore, when this form is established, you must specify a SQL statement in the "Paper" and "Page Settings" in the above form, the controls included on the QuickRep.page property, the program When you change, you will change the corresponding value value of the QuickRep control, which can be done with the onchange or onexit event code; the title in the Print Content Settings is the title of the specified report (TT: TEDIT), its value and QuickRep.ReportTitle And Title.caption, can be changed any; "Print Query Condition" check box Specifies whether to print query conditions, the selection of the check box does not directly control whether Qrsql.caption is empty; "Table Column Alignment" by a set of options The button consists, it is mainly used to align the details of the details of the report generation. It changes the value of the control variable RD1 (0 automatic alignment, 1 intermediate alignment, 2 left alignment); "Table Liem Print Width" by a set The option button consists of mainly used to generate the width of the report format, its change control variable RD2 (0 automatic width, 1 same width, 2 limit maximum width), and is selected in the same width, 2 The input width is required to limit the maximum width, and the unit is pixel; "Statistical manner" means whether the report contains the footer (FB: TQRBAND) and the sum (SB: tqrband) band area.
2, description of the procedures defines the following types of procedures: TQRLabelName = array of TQRLabel; TQRDBTextName = array of TQRDBText; TQRShapeName = array of TQRShape; TQRExpName = array of TQRExpr; a class of the above type dynamic array type, each element of data. When establishing a report control in real time, the number of controls to be established is uncertain and the control name cannot be determined. It is a better solution to use the dynamic array, that is, the dimension of the data can be arbitrarily specified, but also manage memory allocation itself. The problem is also conducive to the report contains the release and processing of the control. Program also declares the type described above variables are: CHBName: TQRLabelName; DBName: TQRDBTextName; CHBShape, DBShape, FBShape, SumShape: TQRShapeName; FBName, SumName: TQRExpName; assign these variables based on the field arrays Query results returned when the form is established Memory, each field pair an element in an array. Program execution process: The form establishes an initialization operation when the form is established and displayed. The corresponding value of the QuickRep.page property is displayed in the OnShow event in the onshow event, and the control array variable space is assigned according to the return result. After the form is created, click the "Generate" button to generate a report (ignore the description field and photo field), then click Print and Preview to print or preview the report. When the report is generated, the setting must be regenerated. If Query returns too much result set field, it is possible to generate a report to generate all reports, adjust the report paper size, regenerate into a report. When the form is turned off, the established control will be released.
3, the source list and annotation unit PrintDlg; interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, Spin, QuickRpt, QRPrntr, printers, Qrctrls, Db, DBTables, ComCtrls, SysIni TYPE TQRLABELNAME = array of tqrlabel; // Columns Tie Zone Dynamic array TQRDBTextName = array of tqrdbtext; // Detail zone Middle Title Control Parts Dynamic array TQRShapeName = array of tqrshape; // Line control class dynamic array tQREXPNAME = array of tqrexpr; // Statistics Control Category Dynamic array TPrintform = Class (TFORM) Groupbox1: TgroupBox; label5: TLabel; btnset: tbitbtn; // "Settings" button control BTNCANCANCANCEL: Tbitbtn; / / "Close" button control Panel1: tpner; btnprint: tbitbtn; // "Print" button control btnprview: tbitbtn; // "Preview" button QuickRep: tquickrep; // Quick Report control HB: tqrband; // " Header "band area control Title: tqrlabel; // Report title control QRE1: TQREXPR; // Column headband" Page Code "Control QRE2: TQREXPR; // The" Date "control panel2: TPANEL Label1: TLABEL; R1: Tradiobutton; // "Longitudinal Print" control R2: tradiobutton; // "Transverse Print" control Groupbox4: TgroupBox; tt: tedit; // Title Input box control label2: TLabel; Sr: tCheckbox; / / "Print Query Condition" control lab EL3: TLABEL; Image1: Timage; // Display portrait print image Image2: TIMAGE; / / Display horizontal print image Qrsql: TQRLABEL; // Used to display "Query Condition" Control Groupbox2: TgroupBox; Label7: TGROUPBOX; Label8: TLabel; Label9: TLabel; Label10: TLabel; Label11: TLabel; Label12: TLabel; Label13: TLABEL; PageSpace: Tedit; // Bar Spacing Input Box Control PageTop: Tedit; // Page Enter the box control PageBottom: TEDIT; // Enter the box control PageLeft: TEDIT; // Page Level Left Enter the box control PAGERIGHT: TEDIT; / / Page Night Enter the box control PagedLux: tCheckbox; // "Double-sided Print" Controls PageCol: TEDIT; // Branch Input Box Control Pages: TEDIT; // Print Capacity PAPERH: TEDIT; // Paper Length Input Box Control Paperw: TEDIT; // Paper Width Input Box Control Label4: TLABEL; Label6: TLABEL; PS: Tcombobox; // Paper model list box control Query: tQuery; // SQL query control DB: tqrband;
// "Detail" belt control CRTREP: Tbitbtn; // "Generate" button control label14: TLabel; label15: TLabel; Panel3: TPANEL; WDAUTO: TRADIOBUTTON; / / "Auto Width" control WDALL: TRADIOBUTTON; // " Width "control wdmax: tradiobutton; //" Limits the most in the width "control label16: TLABEL; COLWD: TEDIT; // Column width input box control Panel4: TPANEL; Djauto: tradiobutton; //" Auto Align "control DjCenter: TRADIOBUTTON // "Intermediate neutral" control DJLEFT: TRADIOBUTTON; / / "Align" control FB: tqrband; // Page foot belt control label17: TLabel; Panel5: TPANEL; TJ1: tCHECKBOX; // "Statistics per page" control TJ2: TCheckBox; // "statistical sum" controls SB: TQRBand; // sum of band control procedure FormCreate (Sender: TObject); procedure RadioButtonClick (Sender: TObject); procedure PageDluxClick (Sender: TObject); procedure PageColChange (Sender: TObject); procedure PageSpaceExit (Sender: TObject); procedure PagesChange (Sender: TObject); procedure PageTopExit (Sender: TObject); procedure PageBottomExit (Sender: TObject); procedure PageLeftExit (Sender: TObject); procedure PageRightExit (Sender: TObject) ; PROC edure TTExit (Sender: TObject); procedure DTClick (Sender: TObject); procedure BtnPrviewClick (Sender: TObject); procedure BtnSetClick (Sender: TObject); procedure PsChange (Sender: TObject); procedure PaperChange (Sender: TObject); procedure FormClose (Sender: TObject; var Action: TCloseAction); procedure FormDestroy (Sender: TObject); procedure CreateReport (Sender: TObject); procedure SRClick (Sender: TObject); procedure ClearRep (); procedure FormShow (Sender: TObject); procedure PaperSizeChg (Sender: TObject); procedure DJChage (Sender: TObject); procedure WdChage (Sender: TObject); procedure QuickRepStartPage (Sender: TCustomQuickRep); procedure BtnPrintClick (Sender: TObject);
Private {private declarations} chbname: tqrlabelname; // Defines the leader strip control name Dynamic array name DBNAME: tqrdbtextName; // Define Detail Zone Control Name Dynamic Name CHBSHAPE, DBSHAPE, FBSHAPE, SUMSHAPE: TQRShapeName; // Definition Line control dynamic number group name fbname, sumname: tqrexpname; // Defines footer (FBNAME) and Sumname Control Name Dynamic Name DJ: Talignment; // Collapse Mode (TACENTER) RD1, RD2 : Byte; // Used to save a list of alignment (RD1) and print width (RD2) status variable name public {public declarations} cxtj, bt: string; // cxtj storage query condition, BT storage report title // Level 1 form specifying end; const papersize: array [0..26] of tqrpapersize = (A3, A4, A4SMALL, A5, B4, B5, LETTER, LETSMALL, TABLOID, LEDGER, LEGAL, Statement, Executive, Folio, Quarto , QR10X14, QR11X17, Note, ENV9, ENV10, ENV11, ENV12, ENV14, CSHEET, DSHEET, ESHEET, CUSTOM; // QuickRep, list, listed
Var Printform: TPrintform;
IMPLEMENTATION
{$ R * .dfm}
Procedure TPrintform.formCreate (Sender: TOBJECT); // Displayed QuickRep.page properties and other attribute values VAR i: Byte; begin pagecol.text: = INTOSTR (QuickRep.page.columns); PageSpace.Text: = Formatfloat '0.00', QuickRep.Page.ColumnSpace); PageTop.Text: = FormatFloat ( '0.00', QuickRep.Page.TopMargin); PageBottom.Text: = FormatFloat ( '0.00', QuickRep.Page.BottomMargin); PageLeft.Text : = FormatFloat ( '0.00', QuickRep.Page.LeftMargin); PageRight.Text: = FormatFloat ( '0.00', QuickRep.Page.RightMargin); PageSpace.Text: = FormatFloat ( '0.00', QuickRep.page.ColumnSpace) ; R1.Checked: = QuickRep.Page.Orientation = poPortrait; Image1.Visible: = R1.Checked; R2.Checked: = QuickRep.Page.Orientation = poLandscape; Image2.Visible: = R2.Checked; PageDlux.Checked: = QuickRep.PrinterSettings.Duplex; Pages.Text: = IntToStr (QuickRep.PrinterSettings.Copies); PaperH.Text: = FormatFloat ( '0.00', QuickRep.Page.Length); PaperW.Text: = FormatFloat ( '0.00', QuickRep .Page.width; for i: = 0 to 26 do // ps list box Display paper type if quickrep.page.papersize = papersize [i] the beginning Ps.ItemIndex: = i; Break; End; // Judging whether the paper width can be changed, only the paper type is custom (ps.itemindex = 26) can change PaperH.Enabled: = ps.itemindex = 26; paperw.enabled: = Ps.itemindex = 26;
procedure TPrintForm.RadioButtonClick (Sender: TObject); // change the sheet orientation event handler var S: String; begin Image1.Visible: = R1.Checked; Image2.Visible: = R2.Checked; if R1.Checked then QuickRep.Page. Orientation: = POPORTRAIT Else QuickRep.page.orientation: = polandscape; // Exchange paper width and length value s: = paperh.text; paperh.text: = paperw.text; paperw.text: = s; if (ps. ItemIndex = 26) or (Ps.ItemIndex = 0) then begin QuickRep.Page.Width: = StrToFloat (PaperW.Text); QuickRep.Page.Length: = StrToFloat (PaperH.Text); end; end; procedure TPrintForm.PageDluxClick (Sender: TOBJECT); Begin Quickrep.printersettings.Duplex: = pagedlux.checked;
Procedure tprintform.pagecolchange (sender: TOBJECT); Begin if strat) <1 the pagecol.text: = '1'; quickrep.page.columns: = strt (pagecol.text);
Procedure tprintform.pageSpaceExit; begin quickrep.page.columnspace: = strtofloat (pagespace.text);
Procedure tprintform.pageSchange (sender: TOBJECT); Begin if strat: = '1'; QuickRep.printersettings.copies: = strt (pages.text);
Procedure tprintform.pagetopexit; begin quickrep.page.topmargin: = strtofloat (pagetop.text);
Procedure tprintform.pagebottomexit; begin quickrep.page.bottommargin: = strtofloat (pagebottom.Text);
Procedure tprintform.pageleftexit; begin quickrep.page.phaftmargin: = start.text); end;
Procedure tprintform.pagerightexit; begin quickrep.page.rightmargin: = start.text); end;
Procedure tPrintform.ttexit (sender: Tobject); // Title Change Event Processing Begin Quickrep.ReportTitle: = tt.text; title.caption: = tt.text; bt: = tt.text; end; procedure tPrintform.dtclick (sender : TOBJECT); // Print Query Conditions check box event begin Qrsql.enable: = sr.checked;
Procedure tprintform.btnprviewclick (sender: TOBJECT); // Preview button Click Event Begin QuickRep.Preview; End;
Procedure tprintform.btnsetclick (sender: TOBJECT); // Setting button Click Event Begin Quickrep.printerSetup; End;
procedure TPrintForm.PsChange (Sender: TObject); // paper type change event begin QuickREp.Page.PaperSize: = PaperSize [Ps.ItemIndex]; PaperH.Text: = FormatFloat ( '0.00', QuickRep.Page.Length); PaperW .Text: = formatfloat ('0.00', Quickrep.page.width); Paperh.Enabled: = ps.itemindex = 26; paperw.enabled: = ps.itemindex = 26; crtrep.enabled: = true; btnprint.enabled: = NOT CRTREP.ENABED; btnprview.enabled: = btnprint.enabled;
procedure TPrintForm.PaperChange (Sender: TObject); // paper width and length change events begin QuickRep.Page.Width: = StrToFloat (PaperW.Text); QuickRep.Page.Length: = StrToFloat (PaperH.Text); end;
Procedure tprintform.formclose (Sender: Tobject; var Action: tclosection); begin action: = cafree;
Procedure tprintform.formDestroy (Sender: TOBJECT); Begin Clearrep; Printform: = NIL; END;
Procedure tprintform.createReport (Sender: TOBJECT); // Generate Button Click Event Var i, L: Byte; Chbtp, Chblf, CD, Obwidth: Word; Begin Screen.cursor: = CRHOURGLASS; TITLE.CAPTION: = BT; / / Set the title clearrep (); // Clear the established object; if sr.checked the qrsql.caption: = cxtj else qrsql.caption: = ''; // Is it printing query critical? Chbtp: = hb.height-17 ; // Established control in the top position of the belt zone CHBLF: = 0; // Established control in the left position of the belt area ObWidth: = 0; // The width of the control of the control is for i: = 0 to query. FieldCount-1 Do // Return to the number of fields according to Query Back (query.fields [i] .dattype <> ftblob) and (query.fields [i] .DataType <> ftmemo) THEN BEGIN / / 忽 注字> Field L: = query.fields [i] .datasize-1; // l = field width (byte) -1 case rd1 of // sets the alignment of the control according to the selected alignment 0: if L <= 10 Then DJ: = TACENTER ELSE DJ: = TALEFTJUSTIFY; // Auto Alignment: The field is less than or equal to 10 among the alignment, otherwise the left is aligned 1: DJ: = Tacenter; // Come align 2: DJ: = TALEFTJUSTIFY; // Align end; casse Rd2 of // Set the report column width 0: begin // automatic width: If L> 14 width Obwidth = 14 (L-14) / 2; if the width of OBWIDTH // cannot display column headings, Then Obwidth = column width; if the field type // is the date type, monetary and floating point digital, Obwidth = 65 if L> 14 TH EN L: = 14 (L-14) DIV 2; Obwidth: = L * 6; L: = Length (Query.fields [i] .displayName); if Obwidth Input Width Value 2: Begin // Limit Maximum Width: First Press Auto Width to calculate whether the width is over the maximum value, // If exceeds Obwidth = maximum width input value if coolwd.text <> 'Then CD: = StrtOINT COLWD.TEXT) ELSE CD: = 200; ObWidth: = L * 6; if Obwidth> CD damWidth: = Cd; Obwidth: = Obwidth 2; IF (query.fields [i] .dattype = ftdatetime) or (Query .Fields [i] .dattype = ftfloat) or (query.fields [i] .datatype = ftcurrency) THEN OBWIDTH: = 65; end; end; if Chblf Obwidth> = Hb.Width Then Begin // Setup Controls> Paper Wide? DLGMES: = 'The paper width is not enough, please change the paper size. '; MessageBox (Handle, DLGMES, CAP_INF, ICO_INF); Break; Else Begin Chbshape [I]: = TQRShape.create (HB); // Create a lead strip line control chbshape [i] .parent: = HB Chbshape [i] .top: = chbtp; chbshape [i] .left: = chblf; chbshape [i] .width: = Obwidth 1; chbshape [i] .height: = 17; ChbName [i]: = tqrlabel.create (hb); // established column header control chbname [i] .parent: = Hb; chbname [i] .top: = chbtp 2; chbname [i] .left: = chblf 1; chbname [i] .autosize: = false; chbname [i] .width: = obWidth-1; chbname [i] .alignment: = Tacenter; chbname [i] .caption: = query.fields [i]. DisplayName; // Take a field as a column name chbname [i]. Bringtofront; Dbshape [i]: = tqrshape.create (db); // Establish detail line control dbshape [i] .parent: = db; dbshape [i] .top: = - 1; dbshape [i] .left: = CHBLF; dbshape [i] .width: = Obwidth 1; dbshape [i] .height: = 17; DBNAME [I]: = tqrdbtext.create (dB); // Establish detail band control DBNAME [i] .parent: = db; dbname [i] .parentreport: = quickrep; dbname [i] .top: = 2; DBNAME [I] .left: = CHBLF 2; DBNAME [i] .autosize: = false; dbname [i] .width: = Obwidth-3; dbname [i] .HEight: = 13; dbname [i] .alignment : = DJ; DBNAME [i] .dataset: = query; dbname [i] .datafield: = query.fields [i] .fieldname; dbname [i]. Bringtofront; if tj1.checked the begin // Whether to create a footer Belt? FBShape [I]: = tqrshape.create (fb); // Creating a footer strip control FBShape [i] .parent: = Fb; fbshape [i] .top: = 0; fbshape [i]. Left: = chblf; fbshape [i] .width: = Obwidth 1; fbshape [i] .height: = 17; IF (query.fields [i] .datatype = ftfloat) or (Query.fields [i] .dattype = ftcurrency) or (i <2) Then Begin // Create fBNAME [i]: = TQREXPR.CREATE (FB); // Create footband control FBNAME [i] .parent: = fb; fbname [i] .parentreport: = quickrep; fbname [i] .top: = 3; fbname [i]. Left: = chblf 2; fbname [i] .autosize: = false; false; false; fbname [i] .width: = Obwidth-3; fbname [i] .height: = 13; fbname [i] .alignment: = tacenter; fbname [I] .Expression: = 'SUM (query.' Query.fields [i] .fieldname ')'; fbname [i]. Bringtofront; end; end; If tj2.checked the begin // Does the sum belt area? Sumshape [i]: = tqrshape.create (SB); // Establish the sum of the strip line control SUMSHAPE [i] .parent: = Sb; Sumshape [i]. Top: = 0; Sumshape [i] .left: = chblf; Sumshape [i] .width: = Obwidth 1; Sumshape [i] .height: = 17; IF (query.fields [i] .datatype = ftfloat) or (query.fields [i] .dattype = ftcurrency) or (i <2) Then Begin // Create Sumname [i]: = TQREXPR.CREATE (SB); // Establishment sum and band control sumname [i] .parent: = Sb; sumname [i] .parentreport: = quickrep; sumname [i] .top: = 3; Sumname [i] .left : = CHBLF 2; Sumname [i] .autosize: = false; sumname [i] .width: = Obwidth-3; Sumname [i] .Height: = 13; Sumname [i] .alignment: = tacenter; Sumname I] .Expression: = 'SUM (query.' Query.fields [i] .fieldname ')'; sumname [i]. Bringtofront; end; end; chblf: = chblf obWidth; // Current field processing completion, To the right field width End; end; end; crtrep.enabled: = false; // Forbidden to generate button btnprint.enabled: = not crtrep.enabled; allowed to print an ammonium button btnprview.enabled: = btnprint.enabled; Allow preview button If TJ1.CHECKED THEN // If the footer band is established, the first two columns in the footer strip are changed to the FBNAME [0] .Expression: = '' 'page meter' '' '; fbname [1] .Expression : = 'Count ' 'row' ''; end; if tj1.checked the begin // The sum belongs to change the sum of sumname [0] .Expression: = '' 'total' ''; Sumname [1] .Expression: = 'count ' '' ''; end; // Adjust the date and page print position in the tibial headband area QRE2.LEFT: = hb.width-qre2.width; Qrsql.Left: = qre1.width 10; Qrsql.Width: = QRE2.LEFT-10- Qrsql.Left; QuickRep.DataSet: = query; // Specify a data set for QuickRep, this sentence must not be less screen.cursor: = crdefault; Procedure tprintform.clearrep (); // Clear the control VAR i: Byte; Begin for i: = 0 to query.fieldcount-1 Do Begin if Assigned (Chbshape [i]) THEN BEGIN CHBSHAPE [I] .Free; chbshape [i]: = nil; end; if assigned (chbname [i]) THEN BEGIN chbName [i] .free; chbname [i]: = nil; end; if Assigned (dbshape [i]) THEN BEGIN Dbshape [i] .free; dbshape [i]: = nil; end; if assigned (dbname [i]) THEN BEGIN DBNAME [I] .free; dbname [i]: = nil; end; if Assigned (FBShape [i ]) The begin fbshape [i] .free; fbshape [i]: = nil; end; if assigned (fbname [i]) THEN BEGIN FBNAME [i] .free; fbname [i]: = nil; end; if Assigned (SUMSHAPE [I]) THEN BEGIN SUMSHAPE [I] .free; Sumshape [I]: = nil; end; if Assigned (Sumname [i]) THEN BEGIN SUMNAME [i] .free; Sumname [i]: = nil; End; end; end; procedure tPrintform.SrClick (sender: TOBJECT); begin if sr.checked the qrsql.caption: = cxtj else qrsql.caption: = '; END; Procedure TPrintform.FormShow (Sender: Tobject); // Form Display Event Begin Query.active: = true; // Print SQL Tt.Text: = BT; QuickRep.ReportTitle: = BT; / / Set Title // Control Name space allocation array SetLength (CHBNAME, Query.FieldCount); SetLength (CHBShape, Query.FieldCount); SetLength (DBNAME, Query.FieldCount); SetLength (DBShape, Query.FieldCount); SetLength (FBNAME, Query.FieldCount); SetLength ( FBSHAPE, Query.fieldcount; setlength (sumname, query.fieldcount); setlength (SUMSHAPE, Query.fieldcount); Procedure tPrintForm.Papersizechg (Sender: TOBJECT); begin crtrep.enabled: = true; btnprint.enabled: = not crtrep.enabled; btnprview.enabled: = btnprint.enabled; end; Procedure tPrintform.djchage (sender: Tobject); // Alignment change event processing var chg: Byte; recomcate; need; = 0 else if Djcenter.checked the chg: = 1 else chg: = 2; if chg <> Rd1 dam papersizechg (nil); rd1: = chg; end; end; procedure tprintform.wdchage (sender: Tobject); // Width change event processing var chG: Byte; begin if wdauto.checked the chg: = 0 Else if wdall.checked the begin chg: = 1; if colwd.text = '' TEN COLWD.TEXT: = '100'; END ELSE BEGIN CHG: = 2; if COLWD.TEXT = '' TEN COLLWD.TEXT: = '200'; End; if Chg <> rd2 dam papendsizechg (nil); rd2: = chg; end; COLWD.Enabled: = CHG <> 0; Procedure tprintform.quickrepStartPage (Sender: tcustomquickrep); // Report print start new page event processing, statistics in the footer stripe Empty VAR i: Byte; beginif tj1.checked the for i: = 0 to query.fieldcount-1 DO if assigned (fbname [i]) THEN FBNAME [I] .RESET; END; Procedure tprintform.btnprintClick (Sender: TOBJECT); begin quickrep.print; end; end.4, call dialog box example: First contains the printdlg unit in the Uses statement in the form to be called, then you can use the following code call: IF NOT Assigned (Printform) Then Printform: = TPrINTForm.create (Application); Printform.Query.sql.assign (Query.SQL); // If the call form does not include the Query control, you can directly set the value of the SQL statement printform.bt : = Report title; Printform.caption: = Form title; Printform.cxtj: = Query Condition; Printform.ShowModal; 5, Conclusion This Program is the CreateReport event procedure and dynamic control name. Due to the limit, some content has not been explained, I hope the reader will experience it. This program can meet the requirements for a general report generation. I have the latest version, more functions, friends who need you can send me an email, and you will be post.