用户登录
用户注册

分享至

FastReport 程序员手册

  • 作者: 花花公子149
  • 来源: 51数据库
  • 2021-06-24

一、使用tfrxreport 组件工作
1、加载并存储报表
默认情况下,报表窗体同项目窗体构存储在同一个dfm文件中。多数情况下,无须再操作,因而你就不必采用特殊方法加载报表。如果你决定在文件中存储报表窗体或者是数据库的

blob字段(他提供了非常大的弹性,你能够在非编译程序中修改),你必须使用“tfrxreport”提供的加载和存储方法。
function loadfromfile(const filename: string; exceptionifnotfound: boolean = false): boolean;
从一个给定名字文件中加载报表。如果第二个参数等于“true”并且文件没找到,那么他会触发一个异常。如果文件加载成功,他返回“true”。

procedure loadfromstream(stream: tstream);
从流中加载报表。

procedure savetofile(const filename: string);
用特殊名称文件存储报表。

procedure savetostream(stream: tstream);
把报表存在流中。

例如:
pascal:
frxreport1.loadfromfile('c:\1.fr3');
frxreport1.savetofile('c:\2.fr3');

c++:
frxreport1->loadfromfile("c:\\1.fr3");

frxreport1->savetofile("c:\\2.fr3");

2.设计报表
通过“tfrxreport.designreport”方法调用报表设计器。你必须在你的项目中包含报表设计器(必要条件是:要么使用“tfrxdesigner”组件,要么增加“frxdesgn”单元到uses

列表)
“desigreport”方法接受两个默认参数:
procedure designreport(modal: boolean = true; mdichild: boolean = false);
modal参数决定设计器是否被模态,mdichild参数允许把设计器窗体作为一个mdi子窗体。

例如:
frxreport1.designreport;

3.运行报表
应用下面两个“tfrxreport”方法中的一个启动报表:
procedure showreport(clearlastreport: boolean = true);
启动报表并在预览窗体中显示。如果“clearlastreport”参数等于“false”,报表将会增加先前的一个报表结果,否则清除前一个报表结构。

function preparereport(clearlastreport: boolean = true): boolean;
启动报表,没有打开预览窗体,参数赋值与“showreport”方法同名。如果报表构造成功,他返回“true”。

多数情况下,使用第一种方法更为方便一些。在报表被构造的同时,他会立刻显示一个预览窗体。

当需要增加另一个报表到前一个报表中的时候,“clearlastreport”参数显得方便些。(此类技术用于批量报表打印)。

例如:
frxreport1.showreport;

 

4.预览报表
使用两种途径显示一个报表是可能的:两者都是调用“tfrxreport.showreport”方法(先前描述过了),或者使用“tfrxreport.showpreparedreport”方法来帮助实现。在第二

种情况下,报表构造没有被执行,但显示了一个完成的报表。也就是说,你要么在“preparedreport”方法帮助下构造他,要么在构造前从文件中加载报表(查看“加载/存储完

成的报表”)

例如:

pascal:

if frxreport1.preparereport then
  frxreport1.showpreparedreport;

c++:

if(frxreport1->preparereport(true))
  frxreport1->showpreparedreport();

在这种情况下,报表构造器先被完成了,并显示在预览窗体中。构造一个庞大的报表可能要花费很多时间,那就是为什么使用“showreport”非等时同步方法会好于

“preparereport/showpreparedreport”方法。你可以通过“tfrxreport.previewoptions”属的缺省值设定预览参数值。(这句翻译的不够好,请参考原文)

原文参考:in this case, report construction is finished first, and after that it is displayed in the preview window. construction of a large report can take

a lot of time, and that is why it is better to use the “showreport anisochronous” method, than the “preparereport/showpreparedreport” one. one can assign

preview settings by default via the “tfrxreport.previewoptions” property.[span]5、打印报表
大多数情况下,你可以从预览窗体打印报表。要人工打印报表,你应该使用“tfrxreport.print”方法,例如:

frxreport1.loadfromfile(...);

frxreport1.preparereport;

frxreport1.print;

同时,你可以在显示的打印对话框中设置打印参数,你也可以使用默认设定值。取消打印对话框,请参考“tfrxreport.printoptions”属性帮助

6.载入并存储报表
这个功能可以在预览窗口中执行。也可以使用手工方法执行,帮助参考“tfrxreport.previewpages”方法:
   function loadfromfile(const filename: string; exceptionifnotfound: boolean = false): boolean;

   procedure savetofile(const filename: string);

   procedure loadfromstream(stream: tstream);

   procedure savetostream(stream: tstream);
赋值和参数化类似与tfrxreport相应的方法。文件包含了完成的报表,默认情况下以“fp3”为扩展名。

例如:
pascal:
frxreport1.previewpages.loadfromfile('c:\1.fp3');
frxreport1.showpreparedreport;

c++:
frxreport1->previewpages->loadfromfile("c:\\1.fp3");
frxreport1->showpreparedreport();

注意,完成的报表加载完毕后,预览方法是通过“showpreparedreport” 方法执行的。

7.导出报表
他可以从预览窗口中执行。也可以手动操作,通过“ffrxreport.export”方法,及这个方法中的参数,你可以导出你想要导出的文件类型:

frxreport1.export(frxhtmlexport1);

导出过滤组件必须是有效的(你必须把他们放到你项目中的窗体上)并调整正确。

the export filter component must be available (you must put it on the form of your project) and be adjusted correctly.

8.创建自定义预览窗体
fastreport在标准的预览窗口中显示报表。如果因为某些原因而不适合你,你可以创建一个自定义预览窗体。为了这个目的,需要设计fastreport组件面板中的“tfrxreport”组

件。要显示报表,tfrxreport.preview方法应该连接到这个组件。

在使用tfrxpreview组件的时候,有两个典型的问题。他不会处理按键(箭头,pgup,pgdown等等)和鼠标滚轮(如果有的话)。要让tfrxpreview同按键工作,设置焦点给他(他

是可以做到的,例如,在窗体的onshow事件句柄中)

frxpreview.setfocus;

要让tfrxpreview同鼠标滚轮工作,你必须创建onmousewheel事件句柄,并且调用tfrxpreview.mousewheelscroll方法。

procedure tform1.formmousewheel(sender: tobject; shift: tshiftstate; 
wheeldelta: integer; mousepos: tpoint; var handled: boolean);
begin
  frxpreview1.mousewheelscroll(wheeldelta);
end;


9.建立复合报表(批量打印)
    在某些情况下,需要立刻组织几个报表打印,或者在一个打印预览窗体中封装并呈现几个报表。要执行这些,在fastreport中有些工具能够允许建立一个新的报表附加在一个

已经存在的报表上。“tfrxreport.preparereport”方法中有一个选项“clearlasreport”布尔类型参数,默认情况下他等于true,这个参数定义了是否有必要在建立报表时清除

前一个报表。下面的方法展示了如何从两个报表中建立一个批量报表:
pascal:

frxreport1.loadfromfile('1.fr3');
frxreport1.preparereport;
frxreport1.loadfromfile('2.fr3');
frxreport1.preparereport(false);
frxreport1.showpreparedreport;

c++:

frxreport1->loadfromfile("1.fr3");
frxreport1->preparereport(true);
frxreport1->loadfromfile("2.fr3");
frxreport1->preparereport(false);
frxreport1->showpreparedreport();
    我们加载并建立第一个报表,但并没有显示他。然后我们加载第二个报表到同一个tfrxreport对象,并使用“clearlastreport”参数,让他等于false。这就允许第二个报表

附加在先前建立的报表之后。接下来,我们在预览窗口中显示一个完成的报表。

9.1 复合报表中的页数
    你可以使用“page”,“page#”,“totalpages”和“totalpages#”系统变量显示页数或总页数,在复合报表中,这些变量以下面的方式工作:
page - 当前报表页数
page# - 批量报表页数
totalpages - 当前报表总页数(报表必须两遍)
totalpages# - 批量报表总页数

9.2 合并符合报表页数
    正如上面所说的,报表设计页中的“printonprevouspage”方法让你在打印报表的时候使用前一页的剩余空间接合报表。在复合报表中,允许你在前一个报表的最后一页的剩

余空间创建一个新的报表。要执行这个,要使能每一个连续报表的第一个设计页“printonpreviousepage”属性[span]10.交互报表
    在交互报表中,你可以在预览窗口定义任意报表对象的鼠标单击反应。例如,一个用户能够单击数据线,结果运行一个带有选择线的明细数据。
    任何报表都能交互。要执行他,你仅仅需要创建tfrxreport.onclickobject事件句柄。下面代码是这个事件句柄的示例:
pascal:

procedure tform1.frxreport1clickobject(page: tfrxpage; view: tfrxview;
  button: tmousebutton; shift: tshiftstate; var modified: boolean);
begin
  if view.name = 'memo1' then
    showmessage('memo1 contents:' + #13#10 + tfrxmemoview(view).text);
  if view.name = 'memo2' then
  begin
    tfrxmemoview(view).text := inputbox('edit', 'edit memo2 text:', tfrxmemoview(view).text);
    modified := true;
  end;
end;

c++:
void __fastcall tform1::frxreport1clickobject(tfrxview *sender,
      tmousebutton button, tshiftstate shift, bool &modified)
{
  tfrxmemoview * memo;
  if(memo =  dynamic_cast <tfrxmemoview *> (sender))
  {
    if(memo->name == "memo1")
      showmessage("memo1 contents:\n\r" + memo->text);
    if(memo->name == "memo2")
    {
      memo->text = inputbox("edit", "edit memo2 text:", memo->text);
      modified = true;
    }
  }
}


在对象的单击事件句柄上,你可以做如下事情:
- 修改一个对象或页的内容,传递句柄(结果,被修改的将被特殊标记,因此修改的内容应该引起重视);
- 由于使用重构或重新建立报表,调用tfrxreport.preparereport方法

在此例中,点击名字为memo1对象的结果显示这个对象内容的消息。当点击memo2是显示一个对话框,这个对象的内容可能被修改。设置modified标志为true,允许保持和显示变更

。 
 
同样的方法,单击事件可以被定义成不同的响应。例如,运行一个新报表。如下注释是必要的。在fastreport3版本中,一个报表组件可以在一个预览窗口中显示唯一的报表(不像

fastreport2.x版本)。那就是为什么一个报表预览窗也会在分开的对象中运行一个报表,或者是同一个对象,但当前报表必须被抹除。
 

关于给终端用户一个可单击对象提示定位,在预览窗口中,鼠标经过一个可单击对象的时候,我们可以修改鼠标的光标。要做到这些,在报表设计器上选择一个要设计的对象并设置

他的cursor属性为不同于crdefault的某个值。

更多的细节涉及到定义的单击对象。在简单报表中,可以依照对象的名字或他的内容来定义。然而,这就不能更多的执行可修改的事例。例如,一个明细报表应当在一个数据选择

行被创建。一个用户单击了内容为12的memo1对象。数据行让这个对象参考什么?那就是为什么你应当知道主键了,主键用于明确的标识这一行。fastreport能够赋值一个字串,包

含任意数据(在我们的事例主键数据中),对于每个报表对象,这个字串存储在tagstr属性中。


让我们来通过一个报表的例子来举例说明,这个报表包含在fastreportdemo.exe-'simple list'示例中。这是一个公司的客户列表,包含诸如客户名称,地址,联系人等数据。数

据源是来自dbdemos演示数据库的customer.db表。这个表有一个主键,custno字段,他没有出现在报表中。我们的任务是终止他通过参考单击完成报表上的任意对象记录他,这就

意味着要获取主键的值,要执行此项操作,就要为所有对象的tagstr属性加入值,依赖于主数据栏:
[customers."custno"]


在报表建立期间,使用相同的方法计算tagstr属性内容,同时计算文本对象的内容;这就意味着变量值会替代所有变量的位置。变量细节使用方括号括起来。那就是为什么行值

是'1005', '2112'等类似值了。在报表建立后,包含tagstr属性对象的类型取决与主数据栏。一个简单的从字串到整形的转换就会提供给我们一个主键的值,这也是所需记录能够

找到的主键。
 

如果主键是复合的(包含多个字段),tagstr属性的内容可能是如下值:
[table1."field1"];[table1."field2"]

在构造一个报表完成后,tagstr属性包含“1000;1”类型值, 此值不同比相同要好。

11.从代码中存取报表对象
报表对象(例如:report page, band, memo-object)是不能在你的代码中直接存取的。这就意味着你不能通过名字寻址对象。例如,当你在你的窗体上寻址一个按钮。要寻址一

个对象,在tfrxreport.findobject方法中找到帮助:

pascal:
var
  memo1: tfrxmemoview;
memo1 := frxreport1.findobject('memo1') as tfrxmemoview;

c++:
tfrxmemoview * memo = 
dynamic_cast <tfrxmemoview *> (frxreport1->findobject("memo1"));

然后,你就能够寻址对象的属性和方法。你也使用“tfrxreport.pages”属性寻址报表页。

pascal:
var
  page1: tfrxreportpage;
page1 := frxreport1.pages[1] as tfrxreportpage;

c++:
tfrxreportpage * page1 = dynamic_cast <tfrxreportpage *> (frxreport1->pages[1]);

12.从代码中创建报表
作为一项规则,你将在设计器中创建多数报表。然而,在某些情况下(例如,当报表窗体未知的时候),使用代码手工创建一个报表是是十分必要的。
想要手工创建一个报表,你需要执行下面的顺序步骤:
- 清除报表组件
- 添加数据源
- 添加数据页
- 添加报表页
- 添加栏页
- 设置栏属性,接着把他们同数据相连
- 在每个栏上加入对象
- 设置对象属性,接着把他们同数据相连

让我们来检查一下创建一个简单报表的类型列表。假设我们拥有如下组件:frxreport1: tfrxreport and frxdbdataset1: tfrxdbdataset(最后一个连接到dbdemos数据,

customer.db表)。我们的报表将包含一个带有报表标题和主数据栏的页。在报表标题栏上有一个带有“hellow fastreport”文本的对象,主数据栏包含一个带有连接到“custno”

字段的对象。

pascal:

var
  datapage: tfrxdatapage;
  page: tfrxreportpage;
  band: tfrxband;
  databand: tfrxmasterdata;
  memo: tfrxmemoview;

{ 清除报表 }
frxreport1.clear;
{ 为报表添加数据集到可存取的列表中 }
frxreport1.datasets.add(frxdbdataset1);

{ 添加"data"页 }
datapage := tfrxdatapage.create(frxreport1);

{ 添加页 }
page := tfrxreportpage.create(frxreport1);
{ 创建唯一名称 }
page.createuniquename;
{ 设置默认字段大小, 纸张和打印方向 }
page.setdefaults;
{ 修改纸张方向 }
page.orientation := polandscape;

{ 添加一个报表标题栏 }
band := tfrxreporttitle.create(page);
band.createuniquename;
{ it is sufficient to set the ?top? coordinate and height for a band }
{ both coordinates are in pixels }
band.top := 0;
band.height := 20;
 
{ 为标题栏添加一个对象 }

memo := tfrxmemoview.create(band);
memo.createuniquename;
memo.text := 'hello fastreport!';
memo.height := 20;
{ 这个对象将伸展坐标到栏的宽度 }
memo.align := bawidth;
 
{ 添加主数据栏 }
databand := tfrxmasterdata.create(page);
databand.createuniquename;
databand.dataset := frxdbdataset1;
{ 顶端的调整应当比先前加入栏的顶部+高度大一些 }
databand.top := 100;
databand.height := 20;

{ 在主数据栏上添加一个对象 }
memo := tfrxmemoview.create(databand);
memo.createuniquename;
{ 连接数据 }
memo.dataset := frxdbdataset1;
memo.datafield := 'custno';
memo.setbounds(0, 0, 100, 20);
{ 调整文本到右侧的对象边缘 }
memo.halign := haright;

{ 显示报表 }
frxreport1.showreport;


c++:

tfrxdatapage * datapage;
tfrxreportpage * page;
tfrxband * band;
tfrxmasterdata * databand;
tfrxmemoview * memo;

// 清除报表 
frxreport1->clear();

// 在报表上添加一个数据集到数据集存取列表
frxreport1->datasets->add(frxdbdataset1);

// 添加“数据”页
datapage = new tfrxdatapage(frxreport1);

// 添加一页
page = new tfrxreportpage(frxreport1);

// 创建一个不重复的名称
page->createuniquename();

// 设置域大小, 纸张和默认的打印方向
page->setdefaults();

// 修改纸张的打印方向
page->orientation = polandscape;

// 增加一个报表标题栏
band = new tfrxreporttitle(page);
band->createuniquename();

// 为栏充分设置顶部坐标和高度
// 在像素上包含坐标
band->top = 0;
band->height = 20;

// 在报表标题栏加入一个对象
memo = new tfrxmemoview(band);
memo->createuniquename();
memo->text = "hello fastreport!";
memo->height = 20;

// 此对象将会被按照栏的宽度延展
memo->align = bawidth;

// 添加主数据栏
databand = new tfrxmasterdata(page);
databand->createuniquename();

databand->dataset = frxdbdataset1;
// 顶部坐标应该大于前边添加栏的顶部坐标+高度
databand->top = 100;
databand->height = 20;

// 主数据上加入一个对象
memo = new tfrxmemoview(databand);
memo->createuniquename();
// 连接到数据

memo->dataset = frxdbdataset1;
memo->datafield = "custno";
memo->setbounds(0, 0, 100, 20);

// 调整文本到右侧对象的空白
memo->halign = haright;
// 显示报表
frxreport1->showreport(true);

让我们来解释一些细节:
    所有在报表中使用的数据集都必须添加到数据源列表中,在我们示例中,是用frxreport1.datasets.add(frxdbdataset1)这一行执行的。否则,报表就不会工作。
    数据页对于插入内部数据集是必要的,例如tfrxadotable。这些数据集只能放在数据页。
    调用page.setdefaults不是必须的,因为在这个案例中页a4纸张设置和页边距都是0毫米。默认值设置10毫米页边距,并捕获打印机页大小和对齐方式。
    在增加栏到页面的同时,你要确认他们没有互相重叠在一起。要执行他,顶部和高度的坐标是相似的。总是要在设计器中定位相同的位置的。
 
对象的坐标和大小是以像素为单位的,因为所有对象的left, top, width和height属性都拥有扩展类型,你能够指出非整形值。下面常量用于转化像素到厘米和英寸:
fr01cm = 3.77953;
fr1cm  = 37.7953;
fr01in = 9.6;
fr1in  = 96;

例如,一个栏的高度等于5毫米如下设定:
band.height := fr01cm * 5; 
band.height := fr1cm * 0.5;

12.代码中创建对话框
    我们知道,报表可以包含对话框窗体。下面的例子展示了如何创建一个带有ok按钮的对话框窗体:

pascal:

 { for working with dialogue objects the following unit should be used }

uses frxdctrl;

var
  page: tfrxdialogpage;
  button: tfrxbuttoncontrol;

{ 添加页 }
page := tfrxdialogpage.create(frxreport1);
{ 创建唯一名称 }
page.createuniquename;
{ 设置大小 }
page.width := 200;
page.height := 200;
{ 设定位置 }
page.position := poscreencenter;
 
{ 添加一个按钮 }
button := tfrxbuttoncontrol.create(page);
button.createuniquename;
button.caption := 'ok';
button.modalresult := mrok;
button.setbounds(60, 140, 75, 25);

{ 显示报表 }
frxreport1.showreport;
 
c++:

//使用对话框对象工作,会用到下面的单元

#include "frxdctrl.hpp"

tfrxdialogpage * page;
tfrxbuttoncontrol * button;

//添加一页
page = new tfrxdialogpage(frxreport1);

//创建唯一名称
page->createuniquename();

//设置大小
page->width = 200;
page->height = 200;

//设定位置
page->position = poscreencenter;

// 添加一个按钮
button = new tfrxbuttoncontrol(page);
button->createuniquename();
button->caption = "ok";
button->modalresult = mrok;
button->setbounds(60, 140, 75, 25);

//显示报表 
frxreport1->showreport(true);

软件
前端设计
程序设计
Java相关