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”属的缺省值设定预览参数值。(这句翻译的不够好,请参考原文)
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);
导出过滤组件必须是有效的(你必须把他们放到你项目中的窗体上)并调整正确。
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: " + Memo->Text);
if(Memo->Name == "Memo2")
{
Memo->Text = InputBox("Edit", "Edit Memo2 text:", Memo->Text);
Modified = true;
}
}
}
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;
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Delphi FastReport报表常用方法
1. 单据中有多行数据,但预览时只显示部分内容,或者打印内容行与行之间有间隔
FASTREPOR属性中:设置RowCount=0,Start New Page为False;Stretched为True.
说明:
RowCount:控制总共打印几行;RowCount=0是打印全部;
Start New Page:打印前先跳页;每页打印一行;
Stretch:表身自动伸缩根据表身内容;
2. 在打印中设置金额或数量的小数位数
FASTREPOR属性中:使用DisplayFormat(数据显示格式)——数字——1234.50
- %2.0f:以整数形式显示;
- %2.2f:显示两位小数;
- %2.3f:显示三位小数位,可根据情况进行调整。
3. 在打印中设置日期/时间的格式
FASTREPOR属性中:使用DisplayFormat(数据显示格式)——日期/时间——11.28.2002
mm.dd.yyyy:显示月.日.年
mm.dd:显示月.日
mm:显示两位的月
4. 当栏位的值为零时显示为空
FASTREPOR属性中:设置HideZeros(数字前面的0是否显示)为True
5. 自动换行
1)选择数据单元进行群组;
2)StretchMode为smMaxHtight;WordWrap为True;Stretched为True.
说明:
StretchMode:对象伸缩的行为;
WordWrap:文本是否自动换行;
6. 合计
[SUM(<进/销/退/折表身档."AMTN_NET">,MasterData2)]
7. 每页合计
将定义好的合计函数放到‘栏尾’中即可。
8. 全表合计
将定义好的合计函数放到‘报表合计’中即可。
9. 金额大写
在报表设计中使用函数:ConbertNumToChinese()
合计金额大写:[ConvertNumToChinese(SUM(<进/销/退/折表身档."AMTN_NET">,MasterData2))]
负数合计金额大写:[ConvertNumToChinese(Abs(SUM(<进/销/退/折表身档."AMTN_NET">,MasterData2)))]
10. 报表中打印行数
在报表设计中使用变量——系统变量Line#
11. 连打
1) 单据——速查,查出要打印的单据;
2)打印——查询数据——预览——打印,选择多张单据进行连打。
12. 连打打到同一页
打印——设计——页面设置——勾选“打印至前一页”,“伸展至打印区”
13. 打印固定行数,不足补空白行代码(语言:PascalScript)
var PageLine: integer; PageMaxRow: integer=5; //每页打印的行数 procedure Footer1OnBeforePrint(Sender: TfrxComponent); var i: integer; begin i := iif(PageLine=0, PageMaxRow, PageLine); while i < PageMaxRow do begin i := i + 1; Engine.ShowBand(Child1); //印空白表格 end; end; procedure MasterData2OnBeforePrint(Sender: TfrxComponent); begin PageLine := <line> mod PageMaxRow; if (PageLine = 1) and (<line> > 1) then Engine.newpage; end; end.
14. 电子签名代码(语言:BasicScript)
sub MasterData2OnBeforePrint(Sender)
if length(<进销货表头档.”CHK_MAN”>)>0 then picture2.visible=true
end sub
---------------------------------------------------------