首页  编辑  

qucikReport 源代码剖析

Tags: /超级猛料/Report.报表、图表/Report报表/   Date Created:

      qucikReport 源代码剖析

按设计期与外部运行Exe单元分类:

外部运行Exe:

qrdatasu 报表数据源设置Dialog

qrdatawz 从报表数据源中选择字段Dialog

qreditor 报表设计器 Dialog,用于外部使用,和qrdatasu,qrdatawz 都有关联

qrexpred 表达式显示格式Dialog

QRLABLWZ - MAILING LABEL SETUP DIALOG  

qrmdsu 主从表设置Dialog

qrwizard 新报表的wizard Dialog

设计期与独立Exe公用单元:

qrcomped 设计期报表属性设置Dialog

qrabout about Dialog

qrenved 用户自定义函数Dialog

qrexpbld 表达式设置Wizard Dialog

qrprev 打印预览Dialog

qrprgres 打印进度条Dialog

qrprnsu 打印机设置Dialog

qrLablEd 增强型qrlabel的属性编辑器 Dialog

比较重要的类:

qrexpr 表达式计算

qr3const 定义了一些提示常量,打印纸张列表常量。

qrexport 把报表输出到各种文件,如ascii,csv,xls,html,rtf,text,wmf

qrctrls 设计期控件

重要的类:

qrprntr 打印预览基础类,是一个重要的单元 打印控制时重要.

quickrpt Quickrpt组件源码 设计期重要

未知:

qrextra 附加类,作用未明

TQrPrinterSettings 设置打印属性

TQrStandardPreViewInterface 建立预览窗口

TQrPreviewImage 打印和预览的图象

TQrPreView 控制预览

这是三个很重要的类:

TQrStream  存图象的流

TQrPagelist 图象内存页的列表

TQrPrinter 控制打印

QuickRept在预览时做了些什么?给你段源码你就明白了。

procedure TCustomQuickRep.Preview;

begin

Application.ProcessMessages;

if PrepareQRPrinter and not QRPrinter.ShowingPreview then

begin

  QRPrinter.Destination := qrdMetafile;

  QRPrinter.Master := Self;

  QRPrinter.OnPrintSetup := PrinterSetup;

  QRPrinter.OnExportToFilter := ExportToFilter;

  QRPrinter.Title := ReportTitle;

  if assigned(FOnPreviewEvent) then

    QRPrinter.OnPreview := FOnPreviewEvent;

  QRPrinter.Preview;

  CreateReport(false);

  if Cancelled then

  begin

    QRPrinter.Free;

    Exit;

  end;

  repeat

    Application.HandleMessage

  until (QRPrinter = nil) or (not QRPrinter.ShowingPreview) or Application.Terminated;

end;

end;

有人说程序压栈了,NO,是REPEAT了,你的退出方式符合QuickRep的条件吗?呵呵。。。

打印原理:

在内存中建立一个内存流,再每一个BAND做处理[其中细节还没有探明],把band信息存到内存流中[writebuffer]。在预览或打印时,建立一个TMetaFile文件,先写入EMFHEADER。把内存流的信息LoadFromStream到MetaFile文件中,在打印或预览时就进行文件的定位,读取[seek,read,write],然后就在打印机的纸上输出。输出时用Canvas.StreahDraw(Rect, MetaFile);走纸控制是按打印机设置走纸的。如果设置当前打印机不支持,则按默认首选项打印,可以动态用API改变默认打印首选项来控制走纸。

关于metaFile文件类型:

是一种可无级缩放的矢量图。在WINDOWS中有一种WMF文件就是此格式。矢量图可由WINDOWS控制缩放,打印。QUIEKREPORT就是利用了元文件的这个好处,不需自己管走纸,预览打印了。而国人王寒松写的EREPORT用的是DOS下常用的找位置用程序生画线textout的手法。metafile文件一旦建立,得到文件句柄,你就象面对一张白纸一样,往上用函数画你的东西吧。画完用打印机的CANVAS打印即可。ArcoBat Reader得PDF文件也是这个原理。

metafile文件可缩放的工作原理:

  在文件中存放的其实是图象的相对位置,在具体的设备上显示时,才通过坐标映射关系转换为具体的坐标。

关于Delphi对MetaFile的编程,Graphics.pas就有TMetaFile的源码,我就不多费口舌了。

主要处理点:

如何把各BAND信息存到流里去。想改变Qr的打印速度和打印方式,需要从此下手。

对MetaFile文件格式的处理。在王寒松做的eReport中是纯粹用线画,用Textout,没有用MetaFile,用MetaFile速度会慢,但处理缩放很好,用线画,对打印速度会有提高,但无级缩放,达不到矢量图的效果。

打印是用Qrprinter打印的。但quickrep.print与quickrep.qrPrinter.print打印在源代码上不一样,还没有深研究。

qrprinter只在预览和打印中才产生,没有预览和打印,没有qrprinter.

quickrep几个最主要的事件:

afterpreview 只在关闭预览窗口才触发

afterprint 只在打印完最后一页才触发

beforeprint 在打印第一页时触发

OnEndPage 在一页末下一页开始前的间隔触发

OnNeedData

OnPreview 在预览前触发

OnStartPage 在每一页开始触发

bandtype

rbtitle 在第一页的头部

rbpageheader 在每一页的头部

rbDetail 记录区

rbPageFooter 在每页纸的尾部

rbsummary 在detail区和group footer区的下

rbcolumnheader 在每页纸的头部。

如何多张互不关联报表连打[节约纸张]?

答:用复合报表制作。在OnAddReports中把报表Reports.add(报表)

缺点:每一个报表的CloumnHeader,PageHeader只能在每张纸的头出现。

如果两张报表在一张纸上,第二个报表的CloumnHeander,PageHeader不出现。

如改为Title,就可出现,但在后续的纸的头部就不出现了。

或许在 TQuickRep.OnNeedData中可以办到,但没仔细想。

用报表生成器做连续打印的思想:

1 建立一个不定长数组,存放quickRep,ClientDataSet

把一个报表取下,把值添好,把它用流的技术复制一份[单纯赋值只是引用指针,因为我们

是用一个QuickRep恢复,所以下一张报表会把我们当前的报表冲掉,而流技术可以复制一份],

从流里边恢复控件必须把流里控件所涉及到的类都用RegisterClass注册一遍,否则从流中恢复时

Owner有可能不认识这个类[Form类和Components类会系统自动识别],无法利用RTTI信息建立控件和保存控件的运行期信息。然后就把数组中的报表增加到复合报表中连打,因为就一个cdsReportDataSet, 而报表连的都是

cdsReportDataSet,现在新建了一个cdsReportDataSet的副本,所以只能把报表上的控件的DataSet都换掉}

不要在其他地方给复合报表.Reports赋值,因为在复合报表内部处理时,它只认在OnAddReport中增加的报表,具体的内部细节是它有一个内部方法:CreateComposite,第一句就是Reports.Clear;在第5句就有一句:

if Assigned(OnAddReports) then OnAddReports(Sender);

Createcomposite在 Print,Preview,prepare都有。