信息系统不可避免要制作各式各样的报表,如果每次开发报表都需要重新编译,这是一个非常大的工程,也不利于整个系统的管理和维护。
通过研究大部分报表都是通过若干个查询条件产生的表格式或图表式的报表,基于这个想法我使用delphi设计一个通用的DLL报表模块,在使用中只需要在后台设置一些基本参数和SQL,在主程序调用这个DLL即可实现动态报表。

经过一天的研究,发现实现起来其实比想象中的要容易得多,也基本达到了我的想法。在此要感谢强大的dbgrideh

主要思路是:
1、动态生成查询控件,目前支持TDBDateTimeEditEh和Tedit控件的动态Creat,以后可以扩展到combobox,单选复选框这些控件。
2、通过报表设计器将存在数据库里的SQL的查询条件与生成的控件进行绑定,再动态生成SQL查询语句。
3、通过adoquery查询生成的SQL语句,使用dbgrideh展示、打印和导出报表内容
4、将报表DLL挂载到系统菜单中,动态生成。

报表设计器界面:

相关的代码与大家分享:

1、控件生成,同时生成一个label在datetime或edit控件前面,作为控件的说明
复制内容到剪贴板程序代码 程序代码

function CreatDateTime(kjmc:string;kjid:integer;kjvalue:string;kjleft:integer;labcaption:string):string;
begin

dtp[kjid]:=TDBDateTimeEditEh.Create(plugform);
dtp[kjid].Left:=kjleft+50;
dtp[kjid].Top:=20;
dtp[kjid].Value:=kjvalue;
dtp[kjid].EditFormat:=’YYYY-MM-DD HH:NN:SS’;
dtp[kjid].Width:=140;
dtp[kjid].Name:=kjmc;
dtp[kjid].Parent:=plugform.RzPanel1; //添加date控件

LAB[kjid]:=TLabel.Create(plugform); //添加LAB
lab[kjid].Left:=kjleft;
lab[kjid].Width:=20;
lab[kjid].Top:=22;
lab[kjid].Caption:=kjmc;
lab[kjid].Parent:=plugform.RzPanel1;

end;

function Createdit(kjmc:string;kjid:integer;kjvalue:string;kjleft:integer;labcaption:string):string;
begin

edi[kjid]:=TRzEdit.Create(plugform);
edi[kjid].Left:=kjleft+50;
edi[kjid].Top:=20;
edi[kjid].Width:=140;
edi[kjid].Name:=kjmc;
edi[kjid].Parent:=plugform.RzPanel1; //添加date控件
edi[kjid].TextHint:=’请输入’;

LAB[kjid]:=TLabel.Create(plugform); //添加LAB
lab[kjid].Left:=kjleft;
lab[kjid].Width:=20;
lab[kjid].Top:=22;
lab[kjid].Caption:=kjmc;
lab[kjid].Parent:=plugform.RzPanel1;

end;

2、创建时先查找控件存不存在,防止报错
复制内容到剪贴板程序代码 程序代码

if plugform.FindComponent(”+plugform.RemoteAdoQuery1.FieldByName(‘vcl_label’).AsString+”)=nil then

3、文件导出
复制内容到剪贴板程序代码 程序代码

procedure Tplugform.RzBitBtn2Click(Sender: TObject);
var
pExpClass:TDBGridEhExportClass; //导出文件类型
pExt:string ; //导出文件扩展名
pExpFile:string; //导出文件路径及文件名称
pExpFileExt:string; //SaveDialog1返回的文件名的扩展名
begin
SaveDialog1.Filter:=’电子表格文件 (*.xls)|*.XLS|文本文件 (*.txt)|*.TXT|CSV文件 (*.csv)|*.CSV|网页文件 (*.htm)|*.HTM|RTF文件 (*.rtf)|*.RTF’;
SaveDialog1.FilterIndex:=0;
//清空SaveDialog1默认文件名
SaveDialog1.FileName := ”;

if SaveDialog1.Execute then begin //如果SaveDialog1正确执行
case SaveDialog1.FilterIndex of //根据FilterIndex设置导出文件类型和扩展名
1: begin pExpClass := TDBGridEhExportAsText; pExt := ‘txt’; end;
2: begin pExpClass := TDBGridEhExportAsCSV; pExt := ‘csv’; end;
3: begin pExpClass := TDBGridEhExportAsHTML; pExt := ‘htm’; end;
4: begin pExpClass := TDBGridEhExportAsRTF; pExt := ‘rtf’; end;
5: begin pExpClass := TDBGridEhExportAsXLS; pExt := ‘xls’; end;
else
pExpClass := nil; pExt := ”;
end;
if pExpClass <> nil then begin //如果导出文件类型已经被正确设置
pExpFile:= trim(SaveDialog1.FileName);
pExpFileExt:= Copy(pExpFile,Length(pExpFile)-2,3);
//判断返回的文件名称是否已经包含正确的扩展名,如果没有则添加正确的扩展名
if UpperCase(pExpFileExt) <> UpperCase(pExt) then
pExpFile := pExpFile + ‘.’ + pExt;

SaveDBGridEhToExportFile(pExpClass,DBGridEh1,pExpFile,True); //按现有设置导出全部数据。
//X_pMsg:=’The data have saved as ‘+pExpFile;
//stbForm.Panels[0].Text:=X_pMsg;
MessageDlg(‘保存成功,文件地址: ‘+pExpFile,mtInformation,[mbOk],0);
end;
end;

end;

4、自动求和,判断字段类型是integer或money就自动求和

复制内容到剪贴板程序代码 程序代码

//自动求和
with DBGridEh1 do
begin

FooterRowCount:=1;
Columns[0].Footers.Add;
Columns[0].Footers[0].ValueType:= fvtStaticText;
Columns[0].Footers[0].Value:=’合计’;

for I := 0 to plugform.DBGridEh1.FieldCount – 1 do
begin
if (plugform.RemoteAdoQuery2.Fields[i].DataType=ftInteger) or (plugform.RemoteAdoQuery2.Fields[i].DataType=ftBCD) then
begin

Columns[i].Footers.Add;
Columns[i].Footers[0].ValueType:= fvtSum;
end;
end;

//ValueType是操作的类型;(fvtSum 求和; fvtAvg 平均值; fvtCount 记录数; fvtStaticText 文本

SumList.Active:=true;
end;