深入-FastReport TfrxReport组件使用
Posted westsoft
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入-FastReport TfrxReport组件使用相关的知识,希望对你有一定的参考价值。
一:加载和保存报表
报表默认保存在项目窗体文件中,大多数情况下,没有更多的操作要深圳市, 因此,你不需要采取特别措施来载入报告.如果你决定保存报表到文件或是数据库中 (这样更灵活, 比如修改报表不用重编译程序), 你可以使用 “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);
保存报表到流
报表文件的扩展名默认为“FR3”.
举例:
frxReport1.LoadFromFile(‘c:1.fr3‘);
frxReport1.SaveToFile(‘c:2.fr3‘);
二:设计报表
显示报表设计窗体,调用“TfrxReport.DesignReport” 方法. 需要引用相关单元。
方法"DesignReport" 有两个默认参数。
procedure DesignReport(Modal: Boolean = True; MDIChild: Boolean = False);
第一个参数控制是否以模态方式显示窗体。第二个参数控制是否为MDI子窗体。
举例:
frxReport1.DesignReport;
三:运行(显示)一个报表
使用“TfrxReport”组件以下的两个方法启动一个报表:
procedure ShowReport(ClearLastReport: Boolean = True);
启动一个报表,并显示预览窗口. 如果参数“ClearLastReport” 等于“False” 报表将添加到先前创建好的报表后面, 否则先前的报表将清除 (默认).
function PrepareReport(ClearLastReport: Boolean = True): Boolean;
启动一个报表,没有预览窗口. 参数跟方法“ShowReport” 一样. 报表创建完成,返回“True”。
大多数情况, 更多使用第一种方法. 会显示预览窗口, 继续构建新报表.
参数“ClearLastReport” 方便控制以下情况,当需要添加其他报表时 。(批量打印报表等情况)
举例:
frxReport1.ShowReport;
四:预览报表
预览窗口显示报表有2个方法: 一个是调用 “TfrxReport.ShowReport” 方法, 一个是调用“TfrxReport.ShowPreparedReport” 方法. 第二个方法中报表构建的动作不执行,但报表已经完成显示. 这意味着,你可以事先构建报表借助“preparereport”方法, 或加载先前从文件加载的报表。
举例:
if frxReport1.PrepareReport then
frxReport1.ShowPreparedReport;
在这种情况下, 报表首先构建完成, 之后显示在预览窗体. 构建一个大报表可能花很多时间, 这就是为什么使用“showreport”(准同步方法),比使用“PrepareReport/ShowPreparedReport”更好. 可以指定预览方式,通过“tfrxreport.previewoptions”属性进行设置。
五:打印报表
大多数情况, 你从预览窗口打印报表. 手动打印报表,可以调用“TfrxReport.Print”方法, 举例:
frxReport1.LoadFromFile(...);
frxReport1.PrepareReport;
frxReport1.Print;
在同一时间, 弹出对话框,可以设置打印参数,. 你可以设置不显示此对话框,设置“TfrxReport.PrintOptions” 属性。
六:加载和保存已完成的报表
报表可以在预览窗口中执行此操作. 也可以手动执行 “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"。
举例:
frxReport1.PreviewPages.LoadFromFile(‘c:1.fp3‘);
frxReport1.ShowPreparedReport;
注意,此种完成的报表在加载完毕后,其预览是通过“showpreparedreport”方法!
七:导出报表
可以在预览窗口执行此操作. 也可以手动调用“TfrxReport.Export” 方法. 方法的参数要指定要导出的文件类型,如:
frxReport1.Export(frxhtmlExport1);
导出组件必须可用 (组件放在窗体上) 并设置正确.
八:创建一个自定义的预览窗体
FastReport显示报表在一个标准的预览窗体中。 可以创建自定义的预览窗体,使用组件“TfrxPreview”。
使用组件时有两个典型问题. 组件没有处理相关按键(光标, PgUp, PgDown etc) 和鼠标滚动。 让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;
九:建立混合型的报表
某些情况下,在一次打印中需要几个报表,或多个报表放在一个预览窗口. FastReport中提供了工具,允许在已有报表上添加新的报表. «TfrxReport.PrepareReport» 方法有一个布尔型的参数选项 «ClearLastReport» , 默认等于 «True» .此参数定义是否清除之前构建的报表. 以下代码演示加载多个报表:
frxReport1.LoadFromFile(‘1.fr3‘);
frxReport1.PrepareReport;
frxReport1.LoadFromFile(‘2.fr3‘);
frxReport1.PrepareReport(False);
frxReport1.ShowPreparedReport;
我们加载第一个报表,并构建他,但不显示. 当我们用同一对象构建第二个报表时,参数 «ClearLastReport» 等于 «False». 这样允许第二个报表添加到之前报表的后,最后在预览窗口中显示构建好的报表。
A:混合报表中的页码
你可以使用«Page,» «Page#,» «TotalPages,» 和«TotalPages#» 等系统变量来显示页码,在混合报表中,这些变量以意义如下:
Page – 当前报表的页码
Page# - 整批报表的页码(意即全局的)
TotalPages – 当前报表的所有页汇总 (a report must be a two-pass one)
TotalPages# - 整批报表的页码汇总.
B:混合报表中组合页
正如上面所说, 报表设计页面中的 PrintOnPreviousPage 属性让你打印时接在前一页, 即 使用前一页的空白空间. 在混合型报表中, 允许你从前一报表的空白开始创建新的报表. 要执行此操作,你在设计每个连续报表的第一页时,打开 PrintOnPreviousPage 属性。
十:交互式报表
交互式报表,在预览窗口所有报表对象定义一个鼠标单击的响应。例如,用户可以单击数据行,并且运行新的报表显示数据行的明细信息。
任何报表都可以成为交互式报表. 要执行此操作,你需要创建一个 TfrxReport.OnClickObject 事件处理,举例如下:
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;
在事件«OnClickObject» 中, 你还可以做以下事情:
- 修改页或报表对象的内容(因此, «Modified» 标志应该指定,因此该修改将考虑在内);
- 调用«TfrxReport.PrepareReport» 方法重建报表。
在上面例子中, Memo2修改了内容,所以设置了Modified := True.
以同样的方式, 可以定义不同的响应方式; 比如你可以, 运行一个新的报表. 需要注意以下几点。在FastReport 3 版本中, 一个TfrxReport组件只能在一个预览窗体中显示 (不像FastReport 2.x 版本). 这就是为什么要运行报表要在一个单独的TfrxReport对象,或在同一个中,但当前的报表必须清除。
在可单击的对象上给用户一个提示信息,我们可以修改光标,设置对象的cursor 属性。
可点击的对象有一个细节问题可. 在简单的报表中可以使用对象的名字或内容,然而,在复杂情况下不能使用. 例如,«Memo1» 的内容是‘12‘. 明细表根据这个获取不能数据。 这就是为什么你需要主键。 FastReport 允许指定一个字符串, 包含任意思数据 (在这个例子中包含一个主键),所有对象使用«TagStr» 属性保存这个字符串。
让我们以 FastReportDemo.exe - ‘Simple list‘ demo为例做说明. 这是一个公司客户的列表, 包含有 «client’s name,» «address,» «contact perso,» etc. 数据源是«Customer.db» 表,来自数据库DBDEMOS。 表的主键是«CustNo» 字段, 没有显示在报表上. 我们决定所有对象用这个键关联到记录, 意即用主键获取数据。要执行此操作, 在Master Data Band 上的所有对象的«TagStr» 属性,输入以下值:
[Customers."CustNo"]
构建报表期间, «TagStr» 属性内容以同样的方式计算, 如同文本对象那样计算; 意即变量的值在所有变量的位置被替换, 在这个特殊情况下的一个变量是被封闭在方括号中的。 类型将包含在«TagStr» 属性中, 一个简单的转换从字符串到整数,将给我们一个主键的值,这样可以找到需要的记录。
如果主键是组合的 (比如包含了多个字段) ,«TagStr» 属性内容像下面这样:
[Table1."Field1"];[Table1."Field2"]
报表构建以后,«TagStr» 属性包含值:‘1000;1‘, 从中得到主键的值是不难的。
十一:在窗体中通过代码访问报表对象
FastReport报表对象(如report page, band, memo-object) 不能从你的代码中直接访问. 需要访问,通«TfrxReport.FindObject» 方法找到对象:
var
Memo1: TfrxMemoView;
…
Memo1 := frxReport1.FindObject(‘Memo1‘) as TfrxMemoView; //这里能用as ?
找到之后可以访问对象的属性和方法。访问page对象,通过 «TfrxReport.Pages» 属性:
var
Page1: TfrxReportPage;
Page1 := frxReport1.Pages[1] as TfrxReportPage;
十二:在窗体中通过代码创建报表
作为一个规则, 多数报表用设计器创建,然而,有些情况(比如报表是未知的) 需要手动创建报表,在代码中。
手动创建报表, 应该按以下顺序步骤:
- clear the report component 清除报表
- add data sources 添加数据源
- add the "Data" page 添加Data 页
- add report’s page 添加一个或多个report 页
- add bands on a page 在页上添加一个或多个band
- set bands’ properties, and then connect them to the data 设置band的属性连接到数据
- add objects on each band 在每个band上添加需要的对象
- set objects’ properties, and then connect them to the data 设置对象的属性,连接到需要的数据字段
让我们看看一个简单«list»类型报表的创建,假设我们有以下组件: frxReport1: TfrxReport 和frxDBDataSet1: TfrxDBDataSet (the last one is connected to data from the DBDEMOS, the «Customer.db» table). 报表将只有一页,包含«Report Title» 和«Master Data» bands.在«Report Title» band 有一个"Hello FastReport!" 文本, 在«Master Data» 包含"CustNo" 字段。
var
DataPage: TfrxDataPage;
Page: TfrxReportPage;
Band: TfrxBand;
DataBand: TfrxMasterData;
Memo: TfrxMemoView;
{ clear a report }
frxReport1.Clear;
{ add a dataset to the list of ones accessible for a report }
frxReport1.DataSets.Add(frxDBDataSet1);
{ add the "Data" page }
DataPage := TfrxDataPage.Create(frxReport1);
{ add a page }
Page := TfrxReportPage.Create(frxReport1);
{ create a unique name }
Page.CreateUniqueName;
{ set sizes of fields, paper and orientation by default }
Page.SetDefaults;
{ modify paper’s orientation }
Page.Orientation := poLandscape;
{ add a report title band}
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;
{ add an object to the report title band }
Memo := TfrxMemoView.Create(Band);
Memo.CreateUniqueName;
Memo.Text := ‘Hello FastReport!‘;
Memo.Height := 20;
{ this object will be stretched according to band’s width }
Memo.Align := baWidth;
{ add the masterdata band }
DataBand := TfrxMasterData.Create(Page);
DataBand.CreateUniqueName;
DataBand.DataSet := frxDBDataSet1;
{ the Top coordinate should be greater than the previously added band’s top + height}
DataBand.Top := 100;
DataBand.Height := 20;
{ add an object on master data }
Memo := TfrxMemoView.Create(DataBand);
Memo.CreateUniqueName;
{ connect to data }
Memo.DataSet := frxDBDataSet1;
Memo.DataField := ‘CustNo‘;
Memo.SetBounds(0, 0, 100, 20);
{ adjust the text to the right object’s margin }
Memo.HAlign := haRight;
{ show the report }
frxReport1.ShowReport;
让我们解释一些细节:
要在报表中使用数据源, 必须把数据源添加到DataSets,本例中调用了«frxReport1.DataSets.Add(frxDBDataSet1)» 。否则, 不能工作。
内部数据如TfrxADOTable可以插入报表的“Data”页,这样的数据集可以放置到“Data”页。
Page.SetDefaults 不是必须的, 本例中使用 À4 格式,边距为 0 mm. SetDefaults 设置了10mm 边距,页大小和对齐方及默认打印机。
在页中添加带, 你应该确保他们不互相重叠. 设置足够的«Top» 和«Height» 坐标。 这里不能修改«Left» 和«Width» 坐标, 因为一个带有页宽度(在垂直带时–你应该设置Left 和Width ,忽略 Top 和 Height)。需要注意的是,在页面上的位置的顺序是非常重要的,总是以同样的方式定位带,在设计器中也以同样的方式。
对象的坐标和大小以像素为单位。由于«Left,» «Top,» «Width,» and «Height» 属性是 «Extended» 类型,你可以设置成一个非整形值。 下面的常量被定义为将像素转换为厘米和英寸(frxClass单元):
fr01cm = 3.77953;
fr1cm = 37.7953;
fr01in = 9.6;
fr1in = 96;
例如, 一个band的高等于 5 mm,你可以设置如下:
Band.Height := fr01cm * 5;
Band.Height := fr1cm * 0.5;
十三:在窗体中通过代码创建对话式报表
十四:修改报表的属性
十五:在代码的帮助下创建报表
十六:打印一个数组
The primary example’s code is located in the «FastReport DemosPrintArray» ( "FastReport DemosBCB DemosPrintArray") directory. 让我们解释几个细节.
To print an array, we use a report with one «Master Data» band, which will be presented as many times, as there are elements in the array. To do this, place a «TfrxUserDataSet» component on the form, and then set it’s properties (it is possible to do it in a code, as shown in our example):
RangeEnd := reCount
RangeEndCount := a number of elements in an array
After that, we connect the data-band to the «TfrxUserDataSet» component. To represent the array element, place a text object with the [element] line inside the «Master Data» band. The «element» variable is filled using a «TfrxReport.OnGetValue» event.
十七:打印一个TStringList
The primary example’s code is located in the «FastReport DemosPrintStringList» ( «FastReport DemosBCB DemosPrintStringList») directory. The method is the same, as in the example with an array.
十八:打印一个文件
十九:打印一个TStringGrid
二十:打印一个TTable和TQuery
二十一:报表继承
二十二:多线程
FastReport可以在不同的线程独立运作,但有一些特点:
- 即使在不同的线程,你不能创建TfrxDBDataSet, 因为全局列表"global list" 被用于搜索,当访问会发生在第一次创建TfrxDBDataSet对象时(你可以关闭使用全局列表,默认情况下它是激活的);
- 如果在报表执行过程中有一些对象属性做了变化(比如在脚本中:Memo1.Left := Memo1.Left + 10), 你需要记住在接下来的操作中,如果TfrxReport.EngineOptions.DestroyForms := False 报表模板将准备修改并需要重新加载或者使用TfrxReport.EngineOptions.DestroyForms := True。 在更新过程中,您不能在线程中使用交互报表, 因为脚本对象在更新后被删除, 这就是为什么在某些情况下,使用TfrxReport.EngineOptions.DestroyForms:=False和更新自己的模板在下一个构建周期中。
If necessary the global list due to which you can search the needed copies of TfrxDBDataSet can be switched off.
{DestroyForms can be switched off, if every time you renew a report from a file or from a current}
FReport.EngineOptions.DestroyForms := False;
FReport.EngineOptions.SilentMode := True;
{ This property switches off the search through global list}
FReport.EngineOptions.UseGlobalDataSetList := False;
{EnabledDataSets plays local list role, you should install it before the template is loaded}
FReport.EnabledDataSets.Add(FfrxDataSet);
FReport.LoadFromFile(ReportName);
FReport.PrepareReport;
(能不用多线程尽量不用)
二十三:缓存报表
The reports and it‘s data can be cached both in memory ( for speed increasing ) and in file on the disk ( for saving RAM recourses). There are several types of caching in Fast Report:
- TfrxReport.EngineOptions.UseFileCache - if the property is installed in True, than the whole text and objects of built report are saved in temporary file on disk, at that TfrxReport.EngineOptions.MaxMemoSize indicates how many MB are meant for the template in RAM .
- TfrxReport.PreviewOptions.PagesInCache - the number of pages which can be kept in cache memory greatly increases preview speed , but spends much memory ( especially when there are pictures in a template).
- TfrxReport.PreviewOptions.PictureCacheInFile - if the property is on, than all the pictures of built report are saved in temporary file on a disk, that greatly reduces memory use in reports with a large amount of pictures, but it reduces the speed.
二十四:MDI窗体样式
FastReport可以创建MDI风格的预览和设计窗体。 The source code of the example is in FastReport DemosMDI Designer catalogue.
值得一提的是,建议每个预览窗口或设计窗口创建自己的TfrxReport ,否则所有的窗口都会指向同一个TfrxReport。
以上是关于深入-FastReport TfrxReport组件使用的主要内容,如果未能解决你的问题,请参考以下文章