FastReport分析 很久以前的笔记有空再整理一下

FastReport的基本思想来源于Windows版的“1S-Bookkeeping”6.0,因此报表的基本元素是包含多行文本的矩形。
与大多数报表生成器不同,它们的报表页面内容保存在图元文件(EMF格式的图像),在FastReport中准备好的报表是一组对象的集合,描述报表处理后各页面所包含的内容。

 

FR,与其它报表生成器一样,使用bands逻辑组织报表数据。
Bands分成两类:data-bands(主数据,从数据,等等)和其它(报表标题,页头,等等)。
Data-bands出现在报表的多行部分,例如Ttable的记录行。

考虑最简单的情况。
TfrPage是一个逻辑页,拥有多个Bands,以及其它对象。
TfrPage = class(TObject)
Bands: Array[TfrBandType] of TfrBand;
说明一个Page的同一种类型的Band链接起来

procedure TfrPage.InitReport;
  for b := btReportTitle to btNone do
    Bands[b] := TfrBand.Create(b, Self);
  TossObjects;

两种方式组织对象。
设计时将所有对象依次置于Objects列表中
build时将band类型对象填入Bands列表,同类型的band依次链接。
其它对象按其位置加入到相应band。

procedure TfrPage.TossObjects;
TossObjects设计时的Band对象转换为build时的Band对象。
设置对象的parent为相应的band,将对象加入相应的band的对象列表。
//将对象置于相应的Band,
//注意ColumnXXX objects同时属于两个个带,水平方向 ,垂直方向
//一个page中所有同一类型的band链起来
//band按坐标排序
//connect header & footer to each data-band

参看Group的例子
Group Header
Data
Group Footer

//解析器,数据结构中的表达式求值。p45 3.2
//考虑两个栈,一个操作码,一个操作数
//解析完一条语句。执行。
//全局变量,局部变量

一个栈
stack操作码
res操作数
最后形成一个逆boland表达式如:3 2 4 + *


设计时的TfrPages的object根据情况被添加到相应的Band中。

跟踪Runtime例子
ShowReport
   PrepareReport
      DoPrepareReport
         BuildBeforeModal
      DoBuildReport
  FormPage
     DoLoop// if not b.DataSet.Eof and b.NewPageAfter then NewPage
        AddToStack
        ShowStack
   TfrPage.ShowBand
      TfrBand.Draw
    DoCalcHeight
    DoDraw
       DrawObjects
          DrawObject
                                         TfrView.Print//Object均由TfrView派生Print到Stream
      ExpandVariables //由数据库得到数据值
      TfrView.SaveToStream
       DrawCross
        frParser.Calc(b1.GroupCondition) <> b1.LastGroupValue
        b.DataSet.Next;

btCrossData  TfrBand.DoAggregate
Parent.DoAggregate([btPageFooter, btMasterFooter, btDetailFooter,
             btSubDetailFooter, btGroupFooter, btCrossFooter, btReportSummary]);

 

   
为何使用Stack
如果存在多重分组,最小的分组最先处理

DoLoop!!!处理数据
  要处理的band进栈,最后ShowBand出栈
      if not b.DataSet.Eof then
      begin
        if (Level = 1) and HasGroups then
          InitGroups(Bands[btGroupHeader]);
        if b.HeaderBand <> nil then
          AddToStack(b.HeaderBand);
        if b.FooterBand <> nil then
          b.FooterBand.InitValues;

        while not b.DataSet.Eof do
        begin
          Application.ProcessMessages;
          if MasterReport.Terminated then break;
          AddToStack(b);
          WasPrinted := True;
          if Level < MaxLevel then
          begin
            DoLoop(Level + 1);
            if BndStackTop > 0 then
              if b.PrintIfSubsetEmpty then
                ShowStack
              else
              begin
                Dec(BndStackTop);
                WasPrinted := False;
              end;
          end
          else ShowStack;

          b.DataSet.Next;

每处理一条会调用
TfrDataSet.Eof
   FOnCheckEOF
      DetailDatasetCheckEOF计算是否完成了一个DetailDataset


frParser.Calc(b1.GroupCondition)计算分组!!

Band->EmFPages

FastReport有22个Bands
名  称 何  时  何  地
 
报表标题 打印在打印报表之初
 
报表合计 打印在报表结束时
 
页头 打印在每页项部
 
页脚 打印在每页底部
 
主项头 打印在第一个数据层开始
 
主项数据 第一层数据——重复每个主项数据记录
 
主项脚 打印在第一个数据层结束
 
细项头 打印在第二个数据开始
 
细项数据 第二层数据——重复每个细项数据记录
 
细项脚 打印在第二个数据层结束
 
子细项头 打印在第三层数据开始
 
子细项数据 第三层数据——重复每个子细项数据记录
 
子细项脚 打印在第三个数据层结束
 
覆盖 打印在每页的最底层(用于打印水印)
 
栏目头 打印在栏目开始
 
栏目脚 打印在栏目结束
 
分组头 组标题打印在分组开始
 
分组脚 打印在分组后
 
交叉表头

交叉表数据

交叉表脚 这组区域用于创建交叉表,报表上可变栏目。
 
子 这个区域能被追加到其它任何类型的区域(交叉表和页脚除外)。子区域显示在父区域之后。
 

在正统的方案中(在细节,在ReportBuilder中)只有一个细节数据区。

FastReport中的方案,你不需要sub-report。在这个表中你可以看到,
你可以在一个报表中使用三层数据(bands:主项数据,细项数据和子细项数据)。

TfrDesignerPage由Panel继承
报表中的对象由TfrView继承


Fr_View.pas的实现比较简单,
TfrPreview直接继承自Tpanel,内含了一个TfrPreviewForm,预览窗体。
在窗体中,有一个关键的控件,PBox: TfrPBox,他继承自Tpanel,
在他的Paint()中,实现了报表画在屏幕上的效果。

TfrPreviewForm
RedrawAll
TfrEMFPages(EMFPages).Draw

在FR_View的绘制函数中,不只一次的调用了TfrEMFPages.Draw(),
而在这个Draw()函数里,分别调用了各个TfrView子类的Draw()函数以达到绘制画布的目的。

同样,在TfrDesignerPage.Mup()中,调用了TfrDesignerPage.DrawPage(),
在DrawPage()中,调用了各个TfrView子类的Draw()。

TfrReport(Doc).EMFPages := TfrEMFPages.Create(Doc);
TfrReport(Doc) Doc是一个TfrReport

PfrPageInfo

TfrEMFPages与TfrPage有何区别与联系?
TfrEMFPages = class(TObject)//主要关注PfrPageInfo,物理页面?

TfrPage = class(TObject)//主要关注与Bands,逻辑页面?
Bands: Array[TfrBandType] of TfrBand;
Objects,RTObjects

TfrEMFPages.ObjectsToPage(Index: Integer);
将2者联系起来


procedure TfrPage.InitReport;
中TfrPage.TossObjects
由Objects创建RtObjects
由RtObject处理脚本

// placing objects over band

// connect header & footer to each data-band


DoBuildReport

TfrPage.FormPage形成页

L4734,L4752:NewPage

L4240:
NewPageAfter := (Flags and flBandNewPageAfter) <> 0;
PageBreak := (Flags and flBandPageBreak) <> 0;

PrepareReport and ShowReport methods starts report building
(ShowReport method runs preview after preparing).

TfrBand
This is build-time version of TfrBandView object. In design-time bands are represents by TfrBandView objects. Before building report, all TfrBandView objects are copyed to the TfrBand objects. TfrBand object contains list of child visual objects (Objects property) and dataset attached to it (DataSet property - only for data-bands).

!!!TfrReport.DoBuildReport;!!!
如何计算分页数目
TfrPage.ShowBand
TfrBand.Draw

 


fr4
frxClass,frxEngine核心
frxEngine.ShowBand
    DoShow

TfrxEngine.RunPage与3以前的FormPage相对应 未采用Stack而采用List

 


ReportMachine
RM_Class
procedure TRMReportPage.PlaceObjects;

RM_Grid
TRMGridEx//支持split 融合
设计非拖动,而是表格模式

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值