0 引言 随着计算机技术的不断普及, 办公的数字化程度越来越高, 出现了大量的计算机系统, 如固定资产管理系统、人事工资管理系统等等。这其中存在大量的MIS系统。MIS系统的一个重要特点是需要处理大量数据并形成报表。由于行业或者其他一些原因, 这些报表的格式种类繁多, 而且还有一些复杂报表。这些报表的格式在开发期间可能都无法设定。为了解决这些问题, 本文采用了表格功能强大的Excel作为报表模板, 用户可以按照自己的要求设置报表格式, 程序运行时再根据用户的设置动态填入数据, 从而实现动态报表功能。
1 实现原理 先由用户按照自己的格式生成Excel报表模板,系统读取模板文件, 并把模板文件存入数据库, 保存用户输入的报表信息, 如某一字段填入第几行第几列。报表打印时, 提取相应的Excel文件, 利用Delphi的Excel控件填入数据库的数据, 实现动态报表功能。
2实现过程 2. 1 定义数据表 系统使用MsSql Server2000数据库,定义两个表,一个是MB,用来存储报表基本信息和Excel文件,一个是MB_Detail存放报表的详细信息,如对应字段的行号和列号。表结构如下:
图1 MB 表结构 图2 MB _Detail表结构
MB表中,“模板内容”字段为image类型, 用来存储Excel模板文件,“记录类型”字段用来表示是单张表格(只打印一条记录)还是列表(打印多条记录); MB Detail表中的列号数据类型为char, 对应Excel中的列号如A、B、C等。
2. 2 保存和读取Excel模板 2. 2. 1 保存Excel模板 本系统将用户设置好的Excel报表模板存入数据库“模板内容”字段。由于本字段存储的是Excel文件内容, 需要采用特殊的存储方式。本系统使用Delph i的TO leContainer控件, 与Excel文件建立连接, 最后存入数据库。因此, 先在模板设置界面上放置TO leContainer控件, 取名为OExcel,主要代码如下: V ar Stream: TS tream; / /定义保存文件的流 Beg inOExce.l C reateOb jectFromF ile( edtfile. Tex ,t Fa lse); OExce.l DoV erb( OExce.l Prim aryV erb); MB. FieldByName(模板名称). As String: = ExtractFileName(edtFile.Text); Stream: = MB. CreateB lobStream (MB. Fie ldByName( '模板内容)', bmW rite) ; try OExcel SaveToS tream(Stream); finally Stream. Free; OExcel DestroyObject; end; End;
2. 2. 2 读取Excel模板 当需要打印报表时,需要将相应的Exce l模板从数据库中读出保存, 并用满足要求的数据填充, 其中读出Excel并保存的代码如下: With TSaveDialog. Create(self) do Begin FileName : = trim(MB.FieldByN ame(模板名称). AsString) ; / /保存的模板的名称 Stream: = MB. CreateBlobStream (MB. Fie ldByName(模板内容 , bmRead);/ /建立数据库流 try OExce.l LoadFromS tream( Stream) ; / /将数据库中的数据读入O leConta iner OExce.l O ldStreamForm at: = true;/ /设置保存的格式不变 OExce.l SaveA sDocument( FileName);/ /将Excel模板文件保存到当前文件夹 fina lly S tream. Free; end; End
2. 3 利用TExcelApplication控件实现报表输出 2. 3. 1 存储报表信息 上节中实现了Excel模板的存储与读取, 实际上,在保存Excel模板的同时, 还要往数据库中存入相应的模板信息, 如某一字段的值存入填入Excel表格中的行号和列号, 是打印单行记录还是多条记录等。具体生成报表信息的界面如图3和图4所示: 图3所示是打印多条记录的情况。这种情况下, 只要确定某一字段需要填入模板中的哪一列, 因此,行号不能输入。这种格式主要用于列表式报表。 图4所示是打印单条记录的情况, 需要指出每个字段在Excel中的行号和列号。这种格式主要用于打印卡片式的报表。
图 3 寛/font] 打印多条记录 图 4 寛/font] 打印单条记录
2. 3. 2 报表输出 报表输出需要用到Delphi的TExcelApplication控件。TExcelApplication控件是Delphi提供的操作MS Office文档的控件之一, 通过它, 可以实现在Delphi程序中对Excel文档的相关操作。TExcelApplication控件的主要方法有: ExcelA: = TExcelApplication. Create(self); / /建立控件 ExcelA. Connect;/ /打开一个Excel应用程序 ExcelA. Visible[0] : = true; / /打开的Excel中的Sheet1可见 ExcelA. Workbooks. Open( F ileN ame, EmptyParam, , 0); / /打开文件名为FileN ame的Excel文件 具体的输出代码如下: Stream: = MB. CreateBlobStream (MB. FieldByName(模板内容), bmRead) ; O. LoadFromStream( Stream ); / /从数据库中读出Excel模板 O. SaveA sDocument( FileName); / /保存 ExcelA : = TExcelApplication. Create( self); ExcelA.Connect; ExcelA.Visible[0] : = true; ExcelA.Workbooks. Open ( FileName, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,EmptyParam, EmptyParam, EmptyParam, EmptyParam,EmptyParam, EmptyParam, EmptyParam, EmptyParam, 0); / /打开 Excel While not DataSet Eof do / /DataSet为输出数据的表 begin MB DETA IL. First; while not MB DETA IL. Eof do begin if trim(MB DETA IL. FieldByName(列号). AsString) < > ''then begin tmpStr : = Trim ( DataSet FieldByName(trim (MB DETA IL. FieldByNam e(字段名). As叜琀爀椀渀最)) . AsString) ; row : = MB DETA IL. FieldByName(列号). asString+inttostr( RBegin) ; ExcelA. Range[ row, row ] . Select; ExcelA. ActiveCell FormulaR1C1: = tmpstr; end; MB DETA IL. Next; end; Inc( RBegin) ; DataSet Next; if not DataSet Eof then ExcelA. Range[ 懜+inttostr( RBegin) , 竜+ inttostr( RBegin) ] . Insert(xlDown, 0) ; / /按模板格式新建一行 end;
3、结论 在Delphi中可以使用多种报表工具完成报表的设计和打印, 但大多数报表工具都太专业, 普通用户使用有一定困难。Excel是使用非常广泛的办公软件, 简单易学, 通过Excel与De lphi结合, 可以设计出非常复杂的报表格式, 完全实现报表的动态生成与输出。本文使用的方法已经在最近开发的设备管理系统中使用, 用户反映良好。
|