Skip to content

前言:本文专门为DELPHI开发程序员学习而写,普通的二次开发和项目实施人员无需阅读。

第26章 特殊事件

OnGetValue事件:在对象文本中的变量需要数据时触发。

OnBeforePrint事件:在画出所有对象之前触发,常用于调入备注字段的内容或从数据库调入图像。

OnUserFunction事件:当对象文件中的变量或表达式包含函数时触发。

第27章 TRMReport对象其它事件

事件描述
OnBeginBand数据部分被定义时触发
OnBeginColumn报表切换不同分栏时触发
OnBeginDoc报表生成之前触发
OnBeginPage页面生成之前触发
OnEndBand数据部分正确生成之后触发
OnEndDoc报表生成之后触发
OnEndPage页面生成之后触发
OnManualBuild生成报表定制时触发
OnPrintColumn生成交叉报表栏时触发
OnProgress标明当前生成进度时触发

第28章 变量

可以在ReportMachine的对象和表达式中使用变量。

变量的查找顺序:

  1. 数据字典中有这个变量
  2. 它是一个数据字段
  3. 它是一个专用变量(Page#、Date、Time等)
  4. 它是RmVariables列表中的变量
  5. 它是一个对象的属性
  6. 它是RmConsts中的常量

在数据字典,我们建议大家提前定义自己需要的中文保留,目的是 —— 降低代码阅读的困难程度。

变量赋值方法:

通过frVariables:

pascal
frVariables['Reporting Period'] := 'January';
frReport1.ShowReport;

通过OnGetValue事件:

pascal
procedure TForm1.frReport1GetValue(const ParName: String; var ParValue: Variant);
begin
  if AnsiCompareText(ParName, 'Reported Period') = 0 then
    ParValue := Table1OtchPeriod.Value;
end;

通过编程为变量列表赋值:

pascal
with frReport1.Dictionary do
begin
  Variables['Number'] := 1;
  Variables['Sum'] := '0.2 * Table1."Summa"';
  Variables['Date'] := '''' + 'January' + '''';
end;

第29章 扩展ReportMachine函数

ReportMachine生成器是开放的,可通过自己的函数库、新的可视控件、输出文件格式和向导来扩展。

29.1 设计自己的预览窗口

使用TRMPreview控件。

主要功能:

  • First, Prev, Next, Last —— 导航
  • SaveToFile —— 保存已生成的报表
  • LoadFromFile —— 调入已生成的报表
  • Print —— 打印已生成的报表
  • OnePage —— 设置预览比例为1页
  • PageWidth —— 设置预览的页面宽度

29.2 扩展函数

可写一个TRMFunction的继承类:

pascal
TRMFunction = class(TObject)
public
  procedure DoFunction(p1, p2, p3: Variant; var val: Variant; 
    Const FunctionName : String = ''); virtual; abstract;
end;

注册函数:调用RegisterRMFunction方法。


第七篇:报表示例

第30章 示例概览

ReportMachine配套有示例项目:

  1. 在报表中插入图表(Chart目录)
  2. 存储临时报表到Delphi窗体(DFMSTORE目录)
  3. 组织“最终用户”工作环境(USER目录)
  4. 使用数据感知控件(ENDUSER1目录)
  5. 运用OnManualBuild事件控制报表逻辑结构(MANUAL目录)
  6. 运行时使用代码手工合成报表(RUNTIME目录)
  7. 打印可变栏数或未知栏数的报表(PRNTBL1目录)
  8. 打印可变栏数和栏宽可变的报表(PRNTBL2目录)
  9. 使用标准和Delphi设计器创建不同的报表(REPORTS目录)

第31章 在报表中插入图表

在报表窗体上放置Chart对象,在图表编辑器的“数据”页中设置“图例”和“值”。

“前X个分组”仅显示前X个值,其它值放在“其它”栏中。

第32章 运用OnManualBuild事件控制报表逻辑结构

通过OnManualBuild事件处理控制报表内容的逻辑结构。

pascal
procedure TForm1.frReport1ManualBuild(Sender: TRMPage);
begin
  Sender.ShowBandByType(btReportTitle);
  for i := 0 to 3 do
  begin
    Sender.ShowBandByName('Band2');
    for j := 0 to 2 do
      Sender.ShowBandByName('Band3');
    if i <> 3 then
      Sender.NewPage;
  end;
end;

第33章 运行时使用代码手工合成报表

当报表结构在设计阶段不确定或需要在运行时改变时,动态创建报表模板。

pascal
procedure TForm1.Button1Click(Sender: TObject);
var
  v: TRMView;
  b: TRMBandView;
  Page: TRMPage;
begin
  frReport1.Pages.Clear;
  frReport1.Pages.Add;
  Page := frReport1.Pages[0];
  
  b := TRMBandView(RMCreateObject(gtBand, ''));
  b.SetBounds(0, 20, 0, 20);
  b.BandType := btMasterData;
  b.Dataset := 'frDBDataSet1';
  Page.Objects.Add(b);
  
  v := RMCreateObject(gtMemo, '');
  v.SetBounds(20, 20, 200, 16);
  v.Memo.Add('[Table1."Company"]');
  Page.Objects.Add(v);
  
  frReport1.ShowReport;
end;

第34章 打印可变栏数或未知栏数的报表

使用交叉表达到目的。

在OnGetValue事件中设定字段值:

pascal
procedure TForm1.frReport1GetValue(const ParName: String; var ParValue: Variant);
begin
  if ParName = 'Cell' then
    ParValue := Table1.Fields[frUserDataset1.RecNo].Value;
  if ParName = 'Header' then
    ParValue := Table1.Fields[frUserDataset2.RecNo].FieldName;
end;

第35章 打印可变栏数和栏宽可变的报表

使用OnPrintColumn事件动态定义栏宽:

pascal
procedure TForm1.frReport1PrintColumn(ColNo: Integer; var Width: Integer);
var
  Field: TField;
begin
  Field := Table1.Fields[ColNo - 1];
  if Field is TStringField then
    Width := Field.Size * Canvas.TextWidth('W')
  else if Field is TDateTimeField then
    Width := 15 * Canvas.TextWidth('W')
  else
    Width := 64;
  FWidth := Width;
end;

OnBeforePrint事件处理中将栏宽设为上面定义的宽度:

pascal
procedure TForm1.frReport1EnterRect(Memo: TStringList; View: TRMView);
begin
  View.dx := FWidth;
end;