作者:刘建华
Delphi程序执行时实时生成报表
当前,在软件开发工具中,Delphi以其控件多、面向对象编程功能强、代码执行速度快和简单易用等特点,结合可视化开发环境和当前最快的编译器技术,已成为全球公认的快速应用开发工具,正被愈来愈多的编程人员所采用。使用Delphi可以编写各种Windows应用程序,尤其是开发数据库信息管理系统有其独特的优势。在数据库信息管理系统的开发的过程中,我们经常需要打印输出很多报表,用Delphi设计复杂报表是一件比较烦锁的事件,它没有Visual FoxPro中那样简便。但由于Delphi中设计报表采用的也是控件,因此,我们可以在程序执行时直接建立所需的报表控件来实时生成报表,而且,生成的报表样工可以由程序控制来决定。例如,我们在数据库信息查询时,查询出来的结果信息结构一般是不固定的,假如我们要将查询结果打印出来,只设计一种报表格式是不行的,为所有可能的结果信息都设计一种报表格式也不是一种很好的解决办法。为了解决这样一个问题,我们可以采用实时生成报表技术。本文的目的就是通过一个实例向大家详细介绍怎样实时生成报表。
本例所将设计一个打印对话框,该对话框包括TQickRep控件和一些报表样式控制控件,其它窗体外观如下图所示:
1、 控件功能说明
QuickRep:TQuickRep 它包括列标头(HB:TQRBand)、细节(DB:TQRBand)、页脚(FB:TQRBand)、总结(SB:TQRBand)带区,并且细节、页脚、总结中没有包括一个TQRLabel、TQRExpr或TDBText控件,主要是在程序执行时建立,列标头带区中包括Title(TQRLabel)用于报表标题;QRSQL: TQRLabel用于查询条件,这两个控件的Caption属性在程序执行时可任意更改。为了能够让QuickRep不显示出来,将其置于Panel1(Tpanel)的后面,并将Panel1扩展到整个窗体;
Query:TQuery SQL语句控件,程序将根据Query返回的结果来生成报表。因此,在建立这个窗体时,一定要将Query.SQL属性指定一条SQL语句;
在以上窗体中“纸张”和“页面设置”两栏所包括的控件是对QuickRep.Page属性的控制,程序执行时更改它们会直接改变QuickRep控件相应的属性值,这可以通过OnChange或OnExit事件代码完成;
“打印内容设置”栏中的标题是指定报表的标题(TT:TEdit),其值与QuickRep.ReportTitle和Title.Caption一致,可以任意更改;“打印查询条件”复选框指定是否打印查询条件,该复选框的选取否直接控制QRSQL.Caption是否为空;“表列对齐方式”由一组选项按钮组成,它主要用于报表生成时细节内容的对齐方式,它的更改控制变量RD1(Byte)的值(0自动对齐,1中间对齐,2左边对齐);“表列打印宽度”由一组选项按钮组成,主要用于在生成报表格式时列值的宽度,它的更改控制变量RD2(Byte)的值(0自动宽度,1相同宽度,2限制最大宽度),当选中1相同宽度,2限制最大宽度时要求输入宽度,单位为像素;“统计方式”指出报表是否包含页脚(FB:TQRBAND)和总和(SB:TQRBAND)带区。
2、 程序说明
程序定义了如下类型:
TQRLabelName=array of TQRLabel;
TQRDBTextName=array of TQRDBText;
TQRShapeName=array of TQRShape;
TQRExpName=array of TQRExpr;
上述类型为动态数组类型,数据的每个元素为一个类。在实时建立报表控件时,要建立的控件个数是不确定的且控制名称也不能确定,用动态数组是一个比较好的解决办法,即可以任意指定数据的维数,又不用自己管理内存分配问题,还有利于报表包含控件的释放与处理。程序还声明了上述类型的变量如下:
CHBName:TQRLabelName;
DBName:TQRDBTextName;
CHBShape,DBShape,FBShape,SumShape:TQRShapeName;
FBName,SumName:TQRExpName;
这些数组变量将在窗体建立时根据Query返回的字段结果分配内存,每一个字段对就数组的一个元素。
程序执行过程:窗体在建立并显示时,就对本窗体建立初始化操作。在OnCreate事件中将QuickRep.Page属性的相应值显示出来,在OnShow事件中执行Query.Open操作,并根据返回结果分配控件数组变量空间。窗体建立后,单击“生成”按钮生成报表(忽略备注字段和相片字段),然后可单击“打印”和“预览”进行打印或者预览报表。当产生报表后又更改了设置,必须重新生成报表。如果Query返回的结果集字段太多,生成报表时有可能纸张矿小不能将生成全部报表,可调整报表纸张大小,再生成报表。当关闭窗体时,将释放建立的控件。
3、 源程序清单及注释
unit PrintDlg;
interface
uses
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;//列标头带区中列标题控制件类动态数组
TQRDBTextName=array of TQRDBText; //细节带区中列标题控制件类动态数组
TQRShapeName=array of TQRShape; //线条控制件类动态数组
TQRExpName=array of TQRExpr; //统计控制件类动态数组
TPrintForm = class(TForm)
GroupBox1: TGroupBox;
Label5: TLabel;
BtnSet: TbitBtn;//“设置”按钮控件
BtnCancel: TBitBtn;// “关闭”按钮控件
Panel1: TPanel;
BtnPrint: TBitBtn;// “打印”按钮控件
BtnPrview: TBitBtn;// “预览”按控件钮
QuickRep: TQuickRep;// 快速报表控件
HB: TQRBand;// “列标头”带区控件
Title: TQRLabel;// 报表标题控件
QRE1: TQRExpr;// 列标头带区中“页码”控件
QRE2: TQRExpr;//列标头带区中“日期”控件
Panel2: TPanel;
Label1: TLabel;
R1: TRadioButton;//“ 纵向打印”控件
R2: TRadioButton;// “横向打印”控件
GroupBox4: TGroupBox;
TT: TEdit;// 标题输入框控件
Label2: TLabel;
SR: TCheckBox;// “打印查询条件”控件
Label3: TLabel;
Image1: TImage;//显示纵向打印图像
Image2: TImage;//显示横向打印图像
QRSQL: TQRLabel;// 列标头带区中用于显示“查询条件”控件
GroupBox2: TGroupBox;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
Label13: TLabel;
PageSpace: TEdit;// 栏间距输入框控件
PageTop: TEdit;// 页边距上输入框控件
PageBottom: TEdit; // 页边距下输入框控件
PageLeft: TEdit; // 页边距左输入框控件
PageRight: TEdit; // 页边距右输入框控件
PageDlux: TCheckBox; // “双面打印”控件
PageCol: TEdit; // 分栏输入框控件
Pages: TEdit; // 打印份数输入框控件
PaperH: TEdit; // 纸张长度输入框控件
PaperW: TEdit;//纸张宽度输入框控件
Label4: TLabel;
Label6: TLabel;
Ps: TComboBox;//纸张型号列表框控件
Query: TQuery;//SQL查询控件
DB: TQRBand;// “细节”带区控件
CrtRep: TBitBtn; // “生成”按钮控件
Label14: TLabel;
Label15: TLabel;
Panel3: TPanel;
Wdauto: TRadioButton; // “自动宽度”控件
Wdall: TRadioButton; // “相同宽度”控件
Wdmax: TRadioButton; // “限制最在宽度”控件
Label16: TLabel;
ColWd: TEdit; // 列宽输入框控件
Panel4: TPanel;
DJAUTO: TRadioButton; // “自动对齐”控件
DJCENTER: TRadioButton; // “中间中齐”控件
DJLEFT: TRadioButton; // “左边对齐”控件
FB: TQRBand; // 页脚带区控件
Label17: TLabel;
Panel5: TPanel;
TJ1: TCheckBox; // “每页统计”控件
TJ2: TCheckBox; // “统计总和”控件
SB: TQRBand; // 总和带区控件
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);
procedure 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;//定义列标头带区控件名动态数组名
DBName:TQRDBTextName; //定义细节带区控件名动态数组名
CHBShape,DBShape,FBShape,SumShape:TQRShapeName; //定义线条控件动态数组名
FBName,SumName:TQRExpName; //定义页脚(FBNAME)和总和带区(SUMNAME)控件名动态数组名
DJ:TAlignment;//列对齐方式(taLeftJustify, taRightJustify, taCenter)
Rd1,Rd2:Byte;//用于保存表列对齐方式(RD1)和打印宽度(RD2)状态变量名
public
{ Public declarations }
CXTJ,BT:String;//CXTJ存放查询条件,BT存放报表标题
//由上一级窗体指定
end;
const
PaperSize:array[0..26] of TQRPaperSize=(A3, A4, A4Small, A5, B4, B5, Letter,
LetterSmall, Tabloid, Ledger, Legal,Statement, Executive, Folio,
Quarto, qr10X14, qr11X17, Note, Env9, Env10, Env11, Env12,
Env14, CSheet, DSheet, ESheet, Custom);
//QuickRep所列出的纸张类型
var
PrintForm: TPrintForm;
implementation
{$R *.DFM}
procedure TPrintForm.FormCreate(Sender: TObject);
//将QuickRep.Page属性以及其它属性值显示出来
var
I:Byte;
begin
PageCol.Text:=IntToStr(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列表框显示纸张类型
if QuickRep.Page.PaperSize=PaperSize[I] then begin
PS.ItemIndex:=I;
Break;
end;
//判断纸张宽度是否可以更改,只有纸张类型为自定义(Ps.ItemIndex=26)才能更改
PaperH.Enabled:=Ps.ItemIndex=26;
PaperW.Enabled:=Ps.ItemIndex=26;
end;
procedure TPrintForm.RadioButtonClick(Sender: TObject);
//纸张方向改变事件处理
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;
//交换纸张宽度和长度的值
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;
end;
procedure TPrintForm.PageColChange(Sender: TObject);
begin
if StrToInt(PageCol.Text)<1 then PageCol.Text:='1';
QuickRep.Page.Columns:=StrToInt(PageCol.Text);
end;
procedure TPrintForm.PageSpaceExit(Sender: TObject);
begin
QuickRep.Page.ColumnSpace:=StrToFloat(PageSpace.Text);
end;
procedure TPrintForm.PagesChange(Sender: TObject);
begin
if StrToInt(Pages.Text)<1 then Pages.Text:='1';
QuickRep.PrinterSettings.Copies:=StrToInt(Pages.Text);
end;
procedure TPrintForm.PageTopExit(Sender: TObject);
begin
QuickRep.Page.TopMargin:=StrToFloat(PageTop.Text);
end;
procedure TPrintForm.PageBottomExit(Sender: TObject);
begin
QuickRep.Page.BottomMargin:=StrToFloat(PageBottom.Text);
end;
procedure TPrintForm.PageLeftExit(Sender: TObject);
begin
QuickRep.Page.LeftMargin:=StrToFloat(PageLeft.Text);
end;
procedure TPrintForm.PageRightExit(Sender: TObject);
begin
QuickRep.Page.RightMargin:=StrToFloat(PageRight.Text);
end;
procedure TPrintForm.TTExit(Sender: TObject);//标题更改事件处理
begin
QuickRep.ReportTitle:=TT.Text;
Title.Caption:=TT.Text;
Bt:=TT.Text;
end;
procedure TPrintForm.DTClick(Sender: TObject);//打印查询条件复选框事件
begin
QRSQL.Enabled:=SR.Checked;
end;
procedure TPrintForm.BtnPrviewClick(Sender: TObject);//预览按钮单击事件
begin
QuickRep.Preview;
end;
procedure TPrintForm.BtnSetClick(Sender: TObject); //设置按钮单击事件
begin
QuickRep.PrinterSetup;
end;
procedure TPrintForm.PsChange(Sender: TObject);//纸张类型改变事件
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.Enabled;
BtnPrview.Enabled:=BtnPrint.Enabled;
end;
procedure TPrintForm.PaperChange(Sender: TObject);//纸张宽度和长度改变事件
begin
QuickRep.Page.Width:=StrToFloat(PaperW.Text);
QuickRep.Page.Length:=StrToFloat(PaperH.Text);
end;
procedure TPrintForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;
procedure TPrintForm.FormDestroy(Sender: TObject);
begin
ClearRep;
PrintForm:=nil;
end;
procedure TPrintForm.CreateReport(Sender: TObject);//生成按钮单击事件
Var
I,L:Byte;
CHBtp,CHBlf,Cd,ObWidth:Word;
begin
Screen.Cursor:=crHourGlass;
Title.Caption:=Bt;//设置标题
ClearRep(); //清除已经建立的对象;
if Sr.Checked then QrSQL.Caption:=CXTJ else QRSQL.Caption:='';//是否打印查询条件?
CHBtp:=HB.Height-17;//建立的控件在带区中的顶部位置
CHBlf:=0; //建立的控件在带区中的左边位置
ObWidth:=0; //建立的控件的宽度
for I := 0 to Query.FieldCount-1 do //根据Query返回字段数建立控件
begin
if (Query.Fields[I].DataType<>ftBlob) And (Query.Fields[I].DataType<>ftMemo) then
begin //忽略备注字段和相片字段
L:=Query.Fields[I].DataSize-1;//L=字段宽度(字节)-1
case Rd1 of //根据选择的对齐方式设置控件的对齐方式
0: if L<=10 then Dj:=taCenter else DJ:=taLeftJustify;
//自动对齐:字段小于等于10居中对齐,否则左边对齐
1: Dj:=taCenter;//居中对齐
2: DJ:=taLeftJustify;//左边对齐
end;
case Rd2 of //根据选择的列表宽度设置报表列宽度
0: begin
//自动宽度:如果L>14则宽度ObWidth=14+(L-14)/2;如果ObWidth
//的宽度不能显示列标题,则ObWidth=列标题宽度;如果字段类型
//为日期型、货币型和浮点数型,则ObWidth=65
if L>14 then L:=14+(L-14) div 2;
ObWidth:=L*6;
L:=Length(Query.Fields[I].DisplayName);
if ObWidth<L*6 then ObWidth:=L*6;
ObWidth:=ObWidth+2;
if (Query.Fields[I].DataType=ftDateTime) or
(Query.Fields[I].DataType=ftFloat) or
(Query.Fields[I].DataType=ftCurrency) then ObWidth:=65;
end;
1: if ColWd.Text<>'' then ObWidth:=StrToInt(ColWd.Text)
else ObWidth:=100;//相同宽度:ObWidth=输入宽度值
2: begin //限制最大宽度:首先按自动宽度计算再判断宽度是否超最大值,
//如果超过则ObWidth=最大宽度输入值
if ColWd.Text<>'' then Cd:=StrToInt(ColWd.Text)
else Cd:=200;
ObWidth:=L*6;
if ObWidth>Cd then ObWidth:=Cd;
ObWidth:=ObWidth+2;
if (Query.Fields[I].DataType=ftDateTime) or
(Query.Fields[I].DataType=ftFloat) or
(Query.Fields[I].DataType=ftCurrency) then ObWidth:=65;
end;
end;
if CHBlf+ObWidth>=HB.Width then begin //建立控件>纸宽?
DlgMes:='纸张宽度不够,请更改纸张尺寸。';
MessageBox(Handle,DlgMes,Cap_Inf,Ico_Inf);
break;
end
else begin
CHBShape[I]:=TQRShape.Create(HB);//建立列标头带区线条控件
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); //建立列标题控件
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;//取字段作为列名
CHBNAME[I].BringToFront;
DBShape[I]:=TQRShape.Create(DB); //建立细节带区线条控件
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); //建立细节带区控件
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 then begin //是否建立页脚带区?
FBShape[I]:=TQRShape.Create(FB); //建立页脚带区线条控件
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].DataType=ftCurrency) or (I<2) then
begin //如果字段类型为数值类型则建立
FBNAME[I]:=TQRExpr.Create(FB); //建立页脚带区控件
FBNAME[I].Parent:=FB;
FBNAME[I].ParentReport:=QuickRep;
FBNAME[I].Top:=3;
FBNAME[I].Left:=CHBlf+2;
FBNAME[I].AutoSize:=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 then begin //是否建立总和带区?
SumShape[I]:=TQRShape.Create(SB); //建立总和带区线条控件
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].DataType=ftCurrency) or (I<2) then
begin //如果字段类型为数值类型则建立
SumNAME[I]:=TQRExpr.Create(SB); //建立总和带区控件
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;//当前字段处理完成,往右一个字段宽度
end;
end;
end;
CrtRep.Enabled:=False;//禁上生成按钮
BtnPrint.Enabled:=not CrtRep.Enabled;允许打印铵钮
BtnPrview.Enabled:=BtnPrint.Enabled;允许预览按钮
if Tj1.Checked then begin //如果建立了页脚带区,则将页脚带区中前两列更改
FBNAME[0].Expression:='''页合计''';
FBNAME[1].Expression:='COUNT+''行''';
end;
if Tj1.Checked then begin //如果建立了总和带区,则将总和带区中前两列更改
SumNAME[0].Expression:='''总计''';
SumNAME[1].Expression:='COUNT+''行''';
end;
//调整列标头带区中的日期及页码打印位置
QRE2.Left:=HB.Width-Qre2.Width;
QRSQL.Left:=QRE1.Width+10;
QRSQL.Width:= QRE2.Left-10-QRSQL.Left;
QuickRep.DataSet:=Query; //为QuickRep指定数据集,该句一定不能少
Screen.Cursor:=crDefault;
end;
procedure TPrintForm.ClearRep();//清除生成报表格式时建立的控件
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]) then 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 then QrSQL.Caption:=CXTJ else QRSQL.Caption:='';
end;
procedure TPrintForm.FormShow(Sender: TObject); //窗体显示事件
begin
Query.Active:=True;//打印SQL
TT.Text:=Bt;
QuickRep.ReportTitle:=Bt;//设置标题
//控件名数组分配空间
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);
end;
procedure TPrintForm.PaperSizeChg(Sender: TObject);
begin
CrtRep.Enabled:=True;
BtnPrint.Enabled:=not CrtRep.Enabled;
BtnPrview.Enabled:=BtnPrint.Enabled;
end;
procedure TPrintForm.DJChage(Sender: TObject);//对齐方式改变事件处理
var
Chg:Byte;
begin
if Djauto.Checked then Chg:=0
else if DjCenter.Checked then Chg:=1
else Chg:=2;
if Chg<>Rd1 then begin PaperSizeChg(nil);Rd1:=Chg;end;
end;
procedure TPrintForm.WdChage(Sender: TObject);//宽度改变事件处理
var
Chg:Byte;
begin
if Wdauto.Checked then Chg:=0
else if Wdall.Checked then begin
Chg:=1;
if ColWd.Text='' then ColWd.Text:='100';
end
else begin
Chg:=2;
if ColWd.Text='' then ColWd.Text:='200';
end;
if Chg<>Rd2 then begin PaperSizeChg(nil);Rd2:=Chg;end;
ColWd.Enabled:=Chg<>0;
end;
procedure TPrintForm.QuickRepStartPage(Sender: TCustomQuickRep);
//报表打印开始新页事件处理,页脚带区中的统计值清空
Var
I:Byte;
begin
if Tj1.Checked then
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、 调用对话框举例:
首先在将要调用的窗体中的USES语句中包含PrintDlg单元,然后可以用如下代码调用:
if not assigned(PrintForm) then PrintForm:=TPrintForm.Create(Application);
PrintForm.Query.SQL.Assign(Query.SQL);
//如果调用窗体不包含Query控件,可直接设置SQL语句的值
PrintForm.Bt:=报表标题;
PrintForm.Caption:=窗体标题;
PrintForm.CXTJ:=查询条件;
PrintForm.ShowModal;
5、 结束语
此程序关键是CreateReport事件过程和动态控件名称的处理。由于编幅所限,有些内容没有说明,希望读者自行体会。对于一般的报表生成,此程序能够满足要求。
本人有最新版本,功能更强,有需要的朋友可发邮件给我,一定邮的。