如何将adoquery查询到的数据的某些字段动态添加到fastreport报表设计器中

FastReport报表文件保存到数据库及读取问题
[问题点数:20分,结帖人qxa07]
FastReport报表文件保存到数据库及读取问题
[问题点数:20分,结帖人qxa07]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2011年4月 Delphi大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。FastReport报表使用示例Delphi源代码 免费下载 - 维维软件园用FASTREPORT实现WEB应用中自定义报表
核心提示:开发WEB应用系统通常都会遇到报表打印问题,简单应用可利用IE的页面打印功能,用FASTREPORT实现WEB应用中自定义报表,利用HTML标签控制格式来实现,但复杂的业务型应用系统,将C/S应用结构下已非常成熟的报表方案移植过来,使得在WEB应用中也可实现任意复杂的报表设计和打印,报表不仅是组成应用的重要部分,还常常
开发WEB应用系统通常都会遇到报表打印问题。简单应用可利用IE的页面打印功能,利用HTML标签控制格式来实现。但复杂的业务型应用系统,报表不仅是组成应用的重要部分,还常常是相当复杂的。现在很多应用系统都要求提供自定义报表的功能――即客户可以自行设计、修改报表。
在C/S结构系统中,报表问题有很多成熟的解决方法。如DELPHI开发工具不仅自带有报表控件,还可以利用第三方控件来实现快速灵活的报表制作和打印,其中有名的控件是FR-Software & A.Tzyganenko 的FastReport。FastReport提供了能与DELPHI无缝集成的从设计到打印的完整控件包,提供的设计界面友好灵活,对于开发可让用户自定义报表的C/S应用来说,是一种很好的解决方式。
在B/S结构应用中,Crystal Report是一种大型报表系统常用和推荐的解决方案。但Crystal Report目前价格昂贵,而且该系统相当庞大。它的可定制性及精确控制打印效果方面尚不够完善。当然,在目前市场上,它仍是一种首选的WEB应用的报表解决方案。
如果能将C/S应用中成熟的报表解决方案搬到B/S应用中,相信对于大部分开发人员来说,都是非常欢迎的。本文将讲述一个在java环境中利用FastReport实现B/S应用中用户可自定义的报表解决方案。因为笔者近段时间正用DELPHI、JAVA做一些项目,所以样例代码就以DELPHI、JAVA编写。
本解决方案样例的基本环境是:WINDOWS 2000 SERVER+SQL SERVER 2000+TOMCAT 4.0。开发工具:IntelliJ IDEA 3.0,DELPHI 5.0。客户端为IE 5.0浏览器。
方案共要求用DELPHI编写两个程序,一个是将被包含在网页中并在浏览器中运行的ACTIVEX(.ocx),一个是运行在服务器端的报表处理程序,中间通过JAVA程序连接――或任何其他WEB语言都可以,如asp、等。方案的基本原理图如下:
报表设计过程
报表打印过程
REPORT SERVER:可以做成一个普通的WINDOWS程序,也可以做成一个COM程序(Automation Object)。在报表设计过程中,用户端(ACTIVEX)向WEB SERVER发送报表设计请求,请求中包含要设计报表的名称;WEB SERVER 收到该请求后,调用REPORT SERVER请求设计的报表文件;REPORT SERVER收到请求后,先装载报表的数据环境,然后将报表设计文件(.frf)和该报表的数据环境文件压缩成一个包文件(.zip),将该包文件的完整路径名返回给WEB SERVER调用程序;WEB SERVER将包文件回送给用户端(ACTIVEX),用户端将接收到的包文件保存到本地硬盘上,并解压缩,从数据环境文件中恢复数据环境,通过FASTREPORT的相应控件打开报表文件给用户提供可视化设计。用户在ACTIVEX中设计报表时,虽然不能和数据库连接,但因数据环境已存在,所以用户仿如在通常的C/S应用结构下设计报表,能正常地看到报表的数据字典信息。在报表打印过程中,用户端(ACTIVEX)向WEB SERVER发送报表打印/预览请求,请求中包含要打印/预览的报表名称;WEB SERVER 收到该请求后,调用REPORT SERVER请求打印或预览的报表文件;REPORT SERVER收到请求后,先装载报表的数据环境,然后装载报表文件(.frf),接着在无界面状态下运行报表,最后将生成的已准备的报表文件(.frp)压缩成一个包文件(.zip),将该包文件的完整路径名返回给WEB SERVER调用程序;WEB SERVER将包文件回送给用户端(ACTIVEX),用户端将接收到的包文件保存到本地硬盘上,并解压缩,通过FASTREPORT的相应控件打开报表文件(.frp)给用户预览或打印或重新调整格式或输出为其他格式文件。用户在ACTIVEX中预览报表,仿如在通常的C/S应用结构下预览报表。
WEB SERVER:提供通常的WEB服务功能。
ACTIVEX:ActiveX是Microsoft提出的一组使用COM(Component Object Model,部件对象模型)使得软件部件可在网络环境中进行交互的技术集。它与具体的编程语言无关。作为针对Internet应用开发的技术,ActiveX被广泛应用于WEB服务器以及客户端的各个方面。本方案中的ACTIVEX控件主要做两方面的事情,一是利用FASTREPORT控件进行报表处理,包括报表设计(.frf文件)和报表打印(.frp文件)。一是与WEB SERVER进行通信,请求和接收包文件。本文样例的ACTIVEX采用DELPHI 5.0编写。
下面分述各部分的一例具体实现(因为仅为说明方案的实现,所以很多代码细节都进行了简省)。
一、      & REPORT SERVER
REPORT SERVER既可以做成一个普通的WINDOWS程序,也可以做成一个COM程序(Automation Object)。本例中为简化见,采用普通的WINDOWS程序实现。
在DELPHI中NEW一个应用程序。在FORM中加入TfrReport、TfrDBDataSet、ADOConnection、TADOQuery等控件――为了使用FASTREPORT的控件,需要安装该控件包,可从站点http://www. 下载,国内很多软件站点都提供该控件包的下载。其中TfrDBDataSet、TADOQuery控件视应用需要可加入多个,另外为了压缩文件,还要加入一个压缩控件,本例使用VCLZip。在Form1中加入三个函数:PReDesignReport(rpFileName:String),prePrintReport(rpFileName:String),zipReportFiles(rpFileName:String),分别用于准备报表设计文件、准备报表打印文件、压缩报表文件&。Form1.Create方法为:
procedure TForm1.FormCreate(Sender: TObject);
   & rpFileName,mode:S
   & if paramCount&1 then
   & begin
       & mode:=paramStr(1);
       & rpFileName:=paramStr(2);
      &  if mode='d' then  //设计报表
           & if preDesignReport(rpFileName) then
               & zipReportFiles(rpFileName);
       & if mode='r' then  //打印报表
           & if prePrintReport(rpFileName) then
                &zipReportFiles(rpFileName);
   & application.T
程序根据调用参数判断是准备报表设计文件还是准备报表打印文件,接着调用相应的过程来实现。最后的Application.Terminate 是让程序执行功能后即退出――因为这是服务端程序,是不能与用户交互的。
preDesignReport(rpFileName:String)方法:
function TForm1.preDesignReport(rpFileName:String):
……  //其他变量
   & dtfFileName:S
   & ……
dtfFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),'.dtf',
[rfReplaceAll, rfIgnoreCase]);
   & try
rpAdoquery.SQL.Add('…');
        &rpAdoquery.//打开报表的数据环境
       & rpAdoquery.FieldList.SaveToFile(dtfFileName);
       & result:=
   & except
     & on Exception do
       & result:=
函数preDesignReport的作用是准备报表设计文件。报表中可以引用多个DataSet,本例假设报表只引用一个名为rpAdoquery的DataSet。rpFileName 为报表文件名(.frf),DtfFileName为保存数据环境的文件名(.dtf)。因为用户端不能连接数据库,所以将DataSet中的Fileds通过rpAdoquery.FieldList.SaveToFile(dtfFileName)保存到文件,和报表文件一起传送给用户端的ACTIVEX,ACTIVEX利用.dtf文件复现报表的数据环境。
prePrintReport(rpFileName:String)方法:
function TForm1.prePrintReport(rpFileName:String):
   & repFileName:S
   & ……
  repFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),'.frp',
[rfReplaceAll, rfIgnoreCase]);
   & try
rpAdoquery.SQL.Add('…');
       & rpAdoquery.//打开报表的数据环境
       & frReport1.ShowProgress:=F
       & frReport1.C
       & frReport1.LoadFromFile(rpFileName);
       & frDBDataSet1.DataSet :=rpA
       & frReport1.Dataset :=frDBDataSet1;
       & frReport1.PrepareR
       & frReport1.SavePreparedReport(repFileName);
       & result:=
   & except
     & on Exception do
       & result:=
函数prePrintReport的作用是准备打印的报表文件,即先在服务器端装载报表并运行,将运行好的报表保存为文件,用于传送到用户端进行预览或打印。RepFileName是已准备好的报表文件名(.frp)。同样假设报表只引用一个名为rpAdoquery的DataSet。frReport1.ShowProgress:=False 使报表运行过程中不显示进度窗口(服务器端不能显示与用户交互的界面);接下来frReport1.C…装载报表文件及设置相关数据属性;frReport1.PrepareReport 是在不显示预览窗口的情况下运行报表;frReport1.SavePreparedReport(repFileName) 将运行好的报表保存到文件,该文件传送给用户端的ACTIVEX,ACTIVEX可以直接预览或显示该报表。
zipReportFiles(rpFileName:String)方法:
function TForm1.zipReportFiles(rpFileName:String):
   & zipFileName,fileName:S
&    zipCount:I
   & ……
& zipFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),'.zip',
[rfReplaceAll, rfIgnoreCase]);
   & fileName:= ExtractFileName(rpFileName);
   & fileName:= ChangeFileExt(fileName,'.*');
   & try
       & VCLZip1.ZipName:= zipFileN
       & VCLZip1.RootDir:= '.\';
       & VCLZip1.FilesList.Add(fileName);
       & zipCount:= VCLZip1.Z
       & if zipCount = 0 then
           & result:=false
        &else
           & result:=
   & except
     & on Exception do
       & result:=
函数zipReportFiles的作用是把要传送给用户端的报表文件压缩为一个.zip文件,简化文件传送过程,而且压缩了数据量。ACTIVEX接收到.zip文件后,先解压出包中文件,再进行处理。
二、       WEB SERVER
方案中WEB SERVER的作用主要是根据ACTIVEX的请求调用REPORT SERVER,并将REPORT SERVER生成的.zip文件发送给ACTIVEX。样例通过一个report.jsp文件来处理:ACTIVEX通过get请求report.jsp文件,report.jsp文件调用REPORT SERVER处理后,将.zip文件发送给ACTIVEX。
Report.jsp文件:
&%@ page import="…"%&
&%@page contentType=" APPLICATION/OCTET-STREAM" %&
   & String reqFileName = request.getParameter("rpFileName");
String reqMode = request.getParameter("mode");//d为设计报表,r为打印报表
String rpFileName = xxxx.getRpFileName(reqFileName); //根据请求的报表名获得实际的报表文件名,如请求订单报表,而订单报表实际对应的报表文件为order.frf。
   & String  & l_cmd="reportserver.exe "+reqMode+" "+ reqFileN
   & Process l_ps=java.lang.Runtime.getRuntime().exec(l_cmd,null);
   & byte[] l_b=new byte[100];
   & while(l_ps.getInputStream().read(l_b,0,100)!=-1){
&        ;
//发送文件
String zipFileName = xxxx.getZipFileName(reqFileName); //获得压缩文件名
response.setHeader("Content-Disposition"," filename=\"" +
zipFileName + "\"");
 & java.io.FileInputStream fileInputStream =
new java.io.FileInputStream(zipFileName);
 & while ((i=fileInputStream.read()) != -1) {
   out.write(i);
 & fileInputStream.close();
 & out.close();
 & catch(Exception e)
   & ……
String l_cmd="reportserver.exe "+reqMode+" "+ reqFileN 组成调用REPORT SERVER的命令串。while(l_ps.getInputStream().read(l_b,0,100)!=-1){ ; } 等待REPORT SERVER执行完成,否则,程序在启动REPORT SERVER后即执行下一行语句。发送文件的方式有多种,比如也可以由ACTIVEX通过ftp方式取得。
三、ACTIVEX
方案中的ACTIVEX控件主要做两方面的事情,一是报表利用FASTREPORT控件进行报表处理,包括报表设计(.frf文件)和报表打印(.frp文件)。一是与WEB SERVER进行通信,请求和接收包文件。
在DELPHI中NEW一个ActiveForm 应用,取名为reportAForm。在form中加入Combox、button、edit、label等与用户交互的控件;为了处理报表,加入FASTREPORT的多个frSpeedButton用于处理报表事件,如设计、预览、打印、翻页、保存等;加入frReport、frDBDataSet、frDesigner等用于在运行时设计报表;如果设计报表时要使用图形、复选框等内容,也要加入相应的控件;加入frPreview、frTextExport、frRTFExport等控件使可以预览报表并可以将报表输出为text、rtf等格式文件;加入ADOQuery(根据实际需要可加入多个)为报表设计提供数据环境,ADOQuery不OPEN,不与数据库连接;加入NMHTTP用于与WEB SERVER联系。加入四个函数:DesignReport(rpFileName:String),PrintReport(rpFileName:String),unzipReportFiles(rpFileName:String),getReportFile(rpFileName,mode:String)分别用于设计报表、打印报表、解压缩报表和向WEB SERVER发送请求以取得报表文件&。
getReportFile(rpFileName,mode:String)方法:
function TreportAForm.getReportFile(rpFileName,mode:String):
   & zipFileName:S
zipFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),'.zip',
[rfReplaceAll, rfIgnoreCase]);
   & NMHTTP1.inputFileMode := TRUE;
   & NMHTTP1.body:='.\ '+ zipFileN
NMHTTP1.Get('http://www…./../report.jsp?rpFileName='+
rpFileName+'&mode='+mode);
   & on Exception do
   & Result:=
函数getReportFile的作用是向WEB SERVER发送报表请求(通过NMHTTP的Get方法),并将返回的压缩包文件保存到本地硬盘(zipFileName)。
unzipReportFiles(rpFileName:String)方法:
function TreportAForm.unzipReportFiles(rpFileName:String) :
   & zipFileName,fileName:S
   & zipCount:I
   & ……
   & zipFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),'.zip',
[rfReplaceAll, rfIgnoreCase]);
   & fileName:= ExtractFileName(rpFileName);
   & fileName:= ChangeFileExt(fileName,'.*');
   & try
    &    VCLUnZip1.ZipName:= '.\'+ zipFileN
       & VCLUnZip1.DestDir:= '.\';
       & VCLUnZip1.OverwriteMode:= A
       & VCLUnZip1.ReadZ
       & VCLUnZip1.FilesList.Add(fileName);
       & zipCount:= VCLUnZip1.UnZ
       & if zipCount = 0 then
           & result:=false
       & else
           & result:=&
   & except
     & on Exception do
       & result:=
函数unzipReportFiles的作用是将压缩包中的文件解压出来,供ACTIVEX使用。它与REPORT SERVER程序中的zipReportFiles刚好是个相反的过程。
DesignReport(rpFileName:String)方法:
function TreportAForm. DesignReport (rpFileName:String) :
   & dtfFileName,rpFileName:S
   & fldlist:TStringL
   & T: TStringF
   & i:I
   & ……
   & dtfFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),'.dtf',
[rfReplaceAll, rfIgnoreCase]);//获得数据环境文件名
   & fldlist:=TStringList.C
   & fldlist.LoadFromFile(dtfFileName);
   & rpAdoquery.Fields.C
   & for i := 0 to fldlist.Count - 1 do
   & begin
       & T := TStringField.Create(nil);
       & T.FieldName := fldlist[i];
       & T.Name := rpAdoquery.Name + T.FieldN
       & rpAdoquery.Fields.add(T);
   & FrReport1.LoadFromFile(rpFileName);
   & FrReport1.DesignR
函数DesignReport先从.dtf(由REPORT SERVER生成)文件中恢复报表的数据环境,接着使用FASTREPORT的FrReport控件设计报表。在FASTREPORT中,对DataSet中的Field只关心名称(全部通过Variant类型处理),而并不关心数据类型,所以恢复报表的数据环境时,所有字段都当作String类型加入。样例假设报表只有一个名为rpAdoquery的DataSet。报表设计运行时窗口在ACTIVEX进程空间运行。
用户端设计好报表并保存后,需要将保存的报表文件(.frf)回送给服务器存储。文件上传对于大部分开发人员来说应该都是熟悉而简单的,该部分程序本文就省略了。
PrintReport(rpFileName:String)方法:
function TreportAForm. PrintReport (rpFileName:String) :
   & repFileName:S
   & ……
   & repFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),'.frp',
       & [rfReplaceAll, rfIgnoreCase]);//获得已准备的报表文件名
   & try
       & frPreview1.
       & FrReport1.Preview:=
       & FrReport1.
       & FrReport1.LoadPreparedReport(repFileName);
       & FrReport1.Preview :=frPreview1;
       & FrReport1.ShowPreparedR
       & result:=
   & except
     & on Exception do
       & result:=
函数PrintReport装入由REPORT SERVER运行好的报表.frp文件,通过调用FrReport的ShowPreparedReport方法在ACTIVEX端预览和打印。
方案实现方法的介绍结束。本方案具有的优点为:保持应用的结构形式不变(B/S),将C/S应用结构下已非常成熟的报表方案移植过来,使得在WEB应用中也可实现任意复杂的报表设计和打印,以及对打印效果进行精确控制。
赞助商链接[转载]Delphi中用FastReport制作报表
Delphi中用FastReport制作报表
报表作为系统信息的典型输出形式之一,是大多数应用系统特别是MIS系统的重要功能。是否具有一个良好的打印功能,往往从一定程度上关系到系统的成败。Delphi有很强的报表功能,但是它的报表功能还不能满足我们的需要。于是许多Delphi高手相继推出了不少优秀的报表控件(模块),作为QuickReport的补充,其中FastReport就是一个代表。
  FastReport综合了QuickReport和Re
portBuilder的优点,个头小,速度快,并带有全部源码。笔者在开发一个药品管理系统时,用FastReport2.51成功制作出了和药品验收单、药品调拨单一模一样的表单式报表。下面给朋友们介绍一下。
  FastReport
V3.19.4下载地址:/view/52.html。
  报表的需求分析
  在医院工作的朋友都知道,药品入库时要填写药品验收单,药房工作人员领取药品时要填写药品调拨单。笔者单位使用的药品验收单和调拨单不是专用的,而是通用的商品验收单和调拨单。与百货业、电信系统使用的报表不同,它的形状为条形,每张固定可填五种药品,内容包括发货单位、发货单号、收货单位、品名、规格、单位、价格、金额等,一式三联。
  综上所述,我们可以把报表设计的需求归纳如下:
大小为:长21cm,宽10cm;
每张可以打印5种药品,表单下面有本页小计。
多于5种药品时开始新一张表单的打印,不足5种药品时要用空行补足。
  报表设计
  1.打开FastReport的报表设计器,按照图1设计出“药品验收单”。
  另外,InHJ、OutHJ、CaHj、LineCount这几个变量分别表示“入库合计”、“出库合计”、“差价合计”和“数据总行数”,在程序中将对这几个变量赋值。
  2.按F11键,调出对象查看器,选中Band2,在它的OnBeforPrint事件中输入如下代码:
-1 &&0  and LINE# -1  mod 5=0 
  代码中用FastReport的内置函数 LINE#
取得当前行号,如果满足条件,就显示页头和Child3,开始新的一张表单。
  3.选中Child3,在它的OnBeforPrint事件中输入如下代码:
lin = lineCount
//在程序中要对该变量赋值
while lin mod
child2  //打印空行
  这段代码的用途是如果最后数据行不够一张表单显示时,就打印空行。
选中Band3,在它的OnBeforPrint事件中输入如下代码:
child1  //到达报表结束时显示表单底部的内容
  5.将报表保存后回到Delphi开发环境。
  Delphi编程部分
  在Delphi编程部分我们主要完成报表所需参数的传递,因为要在好几个过程中访问这些参数,所以要将这几个参数设为全局变量:
  private
line1 line2
integer //保存行号
inputXj intemp
//入库小计 ,每5行后清零,下同
outXj outemp
//出库小计
CajiaXj catemp
Real //差价小计
下面是几个主要过程的代码清单。
//单张表单数据合并过程
TInputForm.frDBDataSet1Next Sender TObject 
Adoruku.RecordCount
Inc line1  //
该变量传至报表文件控制打印空行
Inc line2  //
该变量控制清零小计值
Adoruku.Eof then
=inputXj+ADORuku.fieldByName '入库金额' .AsFloat
=outXj+Adoruku.fieldByName '出库金额' .AsFloat
=CajiaXj+AdorukuJXCJ.AsFloat
//每5行后将小计值清零
if line2 mod 5
= 0  and ReCount& line2 div 5  5  
//到达数据集末尾时给变量赋值
if Adoruku.Eof
  以上程序在Windows
2000/XP+Delphi6.0中调试通过。至此,我们已经完成了药品验收单的设计工作,其他的类似报表设计可以参照以上过程。图2是程序运行时生成的报表预览效果。
原文来自:
一、使用TfrxReport 组件工作
1、加载并存储报表
默认情况下,报表窗体同项目窗体构存储在同一个DFM文件中。多数情况下,无须再操作,因而你就不必采用特殊方法加载报表。如果你决定在文件中存储报表窗体或者是数据库的
Blob字段(他提供了非常大的弹性,你能够在非编译程序中修改),你必须使用“TfrxReport”提供的加载和存储方法。
function LoadFromFile(const FileName:
S ExceptionIfNotFound: Boolean = False):
从一个给定名字文件中加载报表。如果第二个参数等于“True”并且文件没找到,那么他会触发一个异常。如果文件加载成功,他返回“True”。
procedure LoadFromStream(Stream:
从流中加载报表。
procedure SaveToFile(const FileName:
用特殊名称文件存储报表。
procedure SaveToStream(Stream:
把报表存在流中。
frxReport1.LoadFromFile('c:1.fr3');
frxReport1.SaveToFile('c:2.fr3');
frxReport1-&LoadFromFile("c:\1.fr3");
frxReport1-&SaveToFile("c:\2.fr3");
2.设计报表
通过“TfrxReport.DesignReport”方法调用报表设计器。你必须在你的项目中包含报表设计器(必要条件是:要么使用“TfrxDesigner”组件,要么增加“frxDesgn”单元到uses
“DesigReport”方法接受两个默认参数:
procedure DesignReport(Modal: Boolean =
T MDIChild: Boolean = False);
Modal参数决定设计器是否被模态,MDIChild参数允许把设计器窗体作为一个MDI子窗体。
frxReport1.DesignR
3.运行报表
应用下面两个“TfrxReport”方法中的一个启动报表:
procedure ShowReport(ClearLastReport:
Boolean = True);
启动报表并在预览窗体中显示。如果“ClearLastReport”参数等于“False”,报表将会增加先前的一个报表结果,否则清除前一个报表结构。
function PrepareReport(ClearLastReport:
Boolean = True): B
启动报表,没有打开预览窗体,参数赋值与“ShowReport”方法同名。如果报表构造成功,他返回“True”。
多数情况下,使用第一种方法更为方便一些。在报表被构造的同时,他会立刻显示一个预览窗体。
当需要增加另一个报表到前一个报表中的时候,“ClearLastReport”参数显得方便些。(此类技术用于批量报表打印)。
frxReport1.ShowR
4.预览报表
使用两种途径显示一个报表是可能的:两者都是调用“TfrxReport.ShowReport”方法(先前描述过了),或者使用“TfrxReport.ShowPreparedReport”方法来帮助实现。在第二
种情况下,报表构造没有被执行,但显示了一个完成的报表。也就是说,你要么在“PreparedReport”方法帮助下构造他,要么在构造前从文件中加载报表(查看“加载/存储完
成的报表”)
frxReport1.PrepareReport then
frxReport1.ShowPreparedR
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
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.PrepareR
frxReport1.P
同时,你可以在显示的打印对话框中设置打印参数,你也可以使用默认设定值。取消打印对话框,请参考“TfrxReport.PrintOptions”属性帮助
6.载入并存储报表
这个功能可以在预览窗口中执行。也可以使用手工方法执行,帮助参考“TfrxReport.PreviewPages”方法:
&function LoadFromFile(const FileName: S
ExceptionIfNotFound: Boolean = False): B
&procedure SaveToFile(const FileName:
&procedure LoadFromStream(Stream:
&procedure SaveToStream(Stream:
赋值和参数化类似与TfrxReport相应的方法。文件包含了完成的报表,默认情况下以“FP3”为扩展名。
frxReport1.PreviewPages.LoadFromFile('c:1.fp3');
frxReport1.ShowPreparedR
frxReport1-&PreviewPages-&LoadFromFile("c:\1.fp3");
frxReport1-&ShowPreparedReport();
注意,完成的报表加载完毕后,预览方法是通过“ShowPreparedReport”
方法执行的。
7.导出报表
他可以从预览窗口中执行。也可以手动操作,通过“FfrxReport.Export”方法,及这个方法中的参数,你可以导出你想要导出的文件类型:
frxReport1.Export(frxHTMLExport1);
导出过滤组件必须是有效的(你必须把他们放到你项目中的窗体上)并调整正确。
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.SetF
要让TfrxPreview同鼠标滚轮工作,你必须创建OnMouseWheel事件句柄,并且调用TfrxPreview.MouseWheelScroll方法。
procedure TForm1.FormMouseWheel(Sender:
TO Shift: TShiftS&
WheelDelta: I MousePos: TP var
Handled: Boolean);
frxPreview1.MouseWheelScroll(WheelDelta);
9.建立复合报表(批量打印)
在某些情况下,需要立刻组织几个报表打印,或者在一个打印预览窗体中封装并呈现几个报表。要执行这些,在FastReport中有些工具能够允许建立一个新的报表附加在一个
已经存在的报表上。“TfrxReport.PrepareReport”方法中有一个选项“ClearLasReport”布尔类型参数,默认情况下他等于True,这个参数定义了是否有必要在建立报表时清除
前一个报表。下面的方法展示了如何从两个报表中建立一个批量报表:
frxReport1.LoadFromFile('1.fr3');
frxReport1.PrepareR
frxReport1.LoadFromFile('2.fr3');
frxReport1.PrepareReport(False);
frxReport1.ShowPreparedR
frxReport1-&LoadFromFile("1.fr3");
frxReport1-&PrepareReport(true);
frxReport1-&LoadFromFile("2.fr3");
frxReport1-&PrepareReport(false);
frxReport1-&ShowPreparedReport();
我们加载并建立第一个报表,但并没有显示他。然后我们加载第二个报表到同一个TfrxReport对象,并使用“ClearLastReport”参数,让他等于False。这就允许第二个报表
附加在先前建立的报表之后。接下来,我们在预览窗口中显示一个完成的报表。
复合报表中的页数
你可以使用“Page”,“Page#”,“TotalPages”和“TotalPages#”系统变量显示页数或总页数,在复合报表中,这些变量以下面的方式工作:
Page - 当前报表页数
Page# - 批量报表页数
TotalPages -
当前报表总页数(报表必须两遍)
Totalpages# - 批量报表总页数
合并符合报表页数
正如上面所说的,报表设计页中的“PrintOnPrevousPage”方法让你在打印报表的时候使用前一页的剩余空间接合报表。在复合报表中,允许你在前一个报表的最后一页的剩
余空间创建一个新的报表。要执行这个,要使能每一个连续报表的第一个设计页“PrintOnPreviousePage”属性[SPAN]10.交互报表
在交互报表中,你可以在预览窗口定义任意报表对象的鼠标单击反应。例如,一个用户能够单击数据线,结果运行一个带有选择线的明细数据。
任何报表都能交互。要执行他,你仅仅需要创建TfrxReport.OnClickObject事件句柄。下面代码是这个事件句柄的示例:
procedure TForm1.frxReport1ClickObject(Page:
TfrxP View: TfrxV
& Button: TMouseB
Shift: TShiftS var Modified: Boolean);
& if View.Name = 'Memo1'
ShowMessage('Memo1 contents:' + #13#10 +
TfrxMemoView(View).Text);
& if View.Name = 'Memo2'
TfrxMemoView(View).Text := InputBox('Edit', 'Edit Memo2 text:',
TfrxMemoView(View).Text);
Modified := T
void __fastcall
TForm1::frxReport1ClickObject(TfrxView *Sender,
& TMouseButton Button, TShiftState Shift, bool
&Modified)
& TfrxMemoView *
& if(Memo =
&dynamic_cast &TfrxMemoView
*& (Sender))
if(Memo-&Name == "Memo1")
& ShowMessage("Memo1 contents:nr" +
Memo-&Text);
if(Memo-&Name == "Memo2")
& Memo-&Text = InputBox("Edit",
"Edit Memo2 text:", Memo-&Text);
& Modified =
在对象的单击事件句柄上,你可以做如下事情:
修改一个对象或页的内容,传递句柄(结果,被修改的将被特殊标记,因此修改的内容应该引起重视);
由于使用重构或重新建立报表,调用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属性内容,同时计算文本对象的内容;这就意味着变量值会替代所有变量的位置。变量细节使用方括号括起来。那就是为什么行值
'2112'等类似值了。在报表建立后,包含TagStr属性对象的类型取决与主数据栏。一个简单的从字串到整形的转换就会提供给我们一个主键的值,这也是所需记录能够
找到的主键。
如果主键是复合的(包含多个字段),TagStr属性的内容可能是如下值:
[Table1."Field1"];[Table1."Field2"]
在构造一个报表完成后,TagStr属性包含“1000;1”类型值,
此值不同比相同要好。
11.从代码中存取报表对象
报表对象(例如:report page, band,
memo-object)是不能在你的代码中直接存取的。这就意味着你不能通过名字寻址对象。例如,当你在你的窗体上寻址一个按钮。要寻址一
个对象,在TfrxReport.FindObject方法中找到帮助:
Memo1 := frxReport1.FindObject('Memo1') as
TfrxMemoView * Memo
dynamic_cast &TfrxMemoView
(frxReport1-&FindObject("Memo1"));
然后,你就能够寻址对象的属性和方法。你也使用“TfrxReport.Pages”属性寻址报表页。
TfrxReportP
Page1 := frxReport1.Pages[1] as
TfrxReportP
TfrxReportPage * Page1 = dynamic_cast
&TfrxReportPage *&
(frxReport1-&Pages[1]);
12.从代码中创建报表
作为一项规则,你将在设计器中创建多数报表。然而,在某些情况下(例如,当报表窗体未知的时候),使用代码手工创建一个报表是是十分必要的。
想要手工创建一个报表,你需要执行下面的顺序步骤:
清除报表组件
添加数据源
添加数据页
添加报表页
设置栏属性,接着把他们同数据相连
在每个栏上加入对象
设置对象属性,接着把他们同数据相连
让我们来检查一下创建一个简单报表的类型列表。假设我们拥有如下组件:frxReport1:
TfrxReport and frxDBDataSet1:
TfrxDBDataSet(最后一个连接到DBDEMOS数据,
Customer.db表)。我们的报表将包含一个带有报表标题和主数据栏的页。在报表标题栏上有一个带有“Hellow
FastReport”文本的对象,主数据栏包含一个带有连接到“CustNo”
字段的对象。
& DataPage:
TfrxReportP
& DataBand:
TfrxMasterD
清除报表 }
frxReport1.C
为报表添加数据集到可存取的列表中 }
frxReport1.DataSets.Add(frxDBDataSet1);
添加"Data"页 }
DataPage :=
TfrxDataPage.Create(frxReport1);
TfrxReportPage.Create(frxReport1);
创建唯一名称 }
Page.CreateUniqueN
设置默认字段大小, 纸张和打印方向 }
修改纸张方向 }
Page.Orientation :=
添加一个报表标题栏 }
TfrxReportTitle.Create(Page);
Band.CreateUniqueN
it is sufficient to set the ?Top? coordinate and height for a band
both coordinates are in pixels }
Band.Top := 0;
Band.Height := 20;
为标题栏添加一个对象 }
TfrxMemoView.Create(Band);
Memo.CreateUniqueN
Memo.Text := 'Hello
FastReport!';
Memo.Height := 20;
这个对象将伸展坐标到栏的宽度 }
Memo.Align := baW
添加主数据栏 }
DataBand :=
TfrxMasterData.Create(Page);
DataBand.CreateUniqueN
DataBand.DataSet :=
frxDBDataSet1;
顶端的调整应当比先前加入栏的顶部+高度大一些 }
DataBand.Top := 100;
DataBand.Height := 20;
在主数据栏上添加一个对象 }
TfrxMemoView.Create(DataBand);
Memo.CreateUniqueN
连接数据 }
Memo.DataSet :=
frxDBDataSet1;
Memo.DataField :=
Memo.SetBounds(0, 0, 100,
调整文本到右侧的对象边缘 }
Memo.HAlign := haR
显示报表 }
frxReport1.ShowR
TfrxDataPage * DataP
TfrxReportPage * P
TfrxBand * B
TfrxMasterData * DataB
TfrxMemoView * M
frxReport1-&Clear();
在报表上添加一个数据集到数据集存取列表
frxReport1-&DataSets-&Add(frxDBDataset1);
添加“数据”页
DataPage = new
TfrxDataPage(frxReport1);
Page = new
TfrxReportPage(frxReport1);
创建一个不重复的名称
Page-&CreateUniqueName();
设置域大小, 纸张和默认的打印方向
Page-&SetDefaults();
修改纸张的打印方向
Page-&Orientation =
增加一个报表标题栏
Band = new
TfrxReportTitle(Page);
Band-&CreateUniqueName();
为栏充分设置顶部坐标和高度
在像素上包含坐标
Band-&Top =
Band-&Height =
在报表标题栏加入一个对象
Memo = new
TfrxMemoView(Band);
Memo-&CreateUniqueName();
Memo-&Text = "Hello
FastReport!";
Memo-&Height =
此对象将会被按照栏的宽度延展
Memo-&Align =
添加主数据栏
DataBand = new
TfrxMasterData(Page);
DataBand-&CreateUniqueName();
DataBand-&DataSet =
frxDBDataset1;
顶部坐标应该大于前边添加栏的顶部坐标+高度
DataBand-&Top =
DataBand-&Height =
主数据上加入一个对象
Memo = new
TfrxMemoView(DataBand);
Memo-&CreateUniqueName();
连接到数据
Memo-&DataSet =
frxDBDataset1;
Memo-&DataField =
Memo-&SetBounds(0, 0, 100,
调整文本到右侧对象的空白
Memo-&HAlign =
frxReport1-&ShowReport(true);
让我们来解释一些细节:
所有在报表中使用的数据集都必须添加到数据源列表中,在我们示例中,是用frxReport1.DataSets.Add(frxDBDataSet1)这一行执行的。否则,报表就不会工作。
数据页对于插入内部数据集是必要的,例如TfrxADOTable。这些数据集只能放在数据页。
调用Page.SetDefaults不是必须的,因为在这个案例中页A4纸张设置和页边距都是0毫米。默认值设置10毫米页边距,并捕获打印机页大小和对齐方式。
在增加栏到页面的同时,你要确认他们没有互相重叠在一起。要执行他,顶部和高度的坐标是相似的。总是要在设计器中定位相同的位置的。
对象的坐标和大小是以像素为单位的,因为所有对象的left, Top,
Width和Height属性都拥有扩展类型,你能够指出非整形值。下面常量用于转化像素到厘米和英寸:
fr01cm = 3.77953;
fr01in = 9.6;
例如,一个栏的高度等于5毫米如下设定:
Band.Height := fr01cm *
Band.Height := fr1cm *
12.代码中创建对话框
我们知道,报表可以包含对话框窗体。下面的例子展示了如何创建一个带有OK按钮的对话框窗体:
&{ for working with
dialogue objects the following unit should be used
uses frxDC
TfrxDialogP
TfrxButtonC
TfrxDialogPage.Create(frxReport1);
创建唯一名称 }
Page.CreateUniqueN
设置大小 }
Page.Width := 200;
Page.Height := 200;
设定位置 }
Page.Position :=
添加一个按钮 }
TfrxButtonControl.Create(Page);
Button.CreateUniqueN
Button.Caption := 'OK';
Button.ModalResult :=
Button.SetBounds(60, 140, 75,
显示报表 }
frxReport1.ShowR
//使用对话框对象工作,会用到下面的单元
#include "frxDCtrl.hpp"
TfrxDialogPage * P
TfrxButtonControl *
//添加一页
Page = new
TfrxDialogPage(frxReport1);
//创建唯一名称
Page-&CreateUniqueName();
//设置大小
Page-&Width =
Page-&Height =
//设定位置
Page-&Position =
添加一个按钮
Button = new
TfrxButtonControl(Page);
Button-&CreateUniqueName();
Button-&Caption =
Button-&ModalResult =
Button-&SetBounds(60, 140,
//显示报表&
frxReport1-&ShowReport(true);
--------------------------------------------------------
Delphi FastReport报表常用方法
单据中有多行数据,但预览时只显示部分内容,或者打印内容行与行之间有间隔
FASTREPOR属性中:设置RowCount=0,Start New
Page为False;Stretched为True.
RowCount:控制总共打印几行;RowCount=0是打印全部;
Page:打印前先跳页;每页打印一行;
Stretch:表身自动伸缩根据表身内容;
&在打印中设置金额或数量的小数位数
FASTREPOR属性中:使用DisplayFormat(数据显示格式)——数字——1234.50
%2.0f:以整数形式显示;
%2.2f:显示两位小数;
%2.3f:显示三位小数位,可根据情况进行调整。
&在打印中设置日期/时间的格式
FASTREPOR属性中:使用DisplayFormat(数据显示格式)——日期/时间——11.28.2002
mm.dd.yyyy:显示月.日.年
mm.dd:显示月.日
mm:显示两位的月
&当栏位的值为零时显示为空
FASTREPOR属性中:设置HideZeros(数字前面的0是否显示)为True
1)选择数据单元进行群组;
2)StretchMode为smMaxHtight;WordWrap为True;Stretched为True.
StretchMode:对象伸缩的行为;
WordWrap:文本是否自动换行;
[SUM(&进/销/退/折表身档."AMTN_NET"&,MasterData2)]
将定义好的合计函数放到‘栏尾’中即可。
将定义好的合计函数放到‘报表合计’中即可。
在报表设计中使用函数:ConbertNumToChinese()
合计金额大写:[ConvertNumToChinese(SUM(&进/销/退/折表身档."AMTN_NET"&,MasterData2))]
负数合计金额大写:[ConvertNumToChinese(Abs(SUM(&进/销/退/折表身档."AMTN_NET"&,MasterData2)))]
&报表中打印行数
在报表设计中使用变量——系统变量Line#
单据——速查,查出要打印的单据;
2)打印——查询数据——预览——打印,选择多张单据进行连打。
&连打打到同一页
打印——设计——页面设置——勾选“打印至前一页”,“伸展至打印区”
&打印固定行数,不足补空白行代码(语言:PascalScript)
PageMaxRow: integer=5;
//每页打印的行数
procedure Footer1OnBeforePrint(Sender:
TfrxComponent);
:= iif(PageLine=0, PageMaxRow, PageLine);
while i & PageMaxRow do
Engine.ShowBand(Child1);
//印空白表格
procedure MasterData2OnBeforePrint(Sender:
TfrxComponent);
PageLine :=
&line& mod
(PageLine = 1) and (&line&
&电子签名代码(语言:BasicScript)
MasterData2OnBeforePrint(Sender)
length(&进销货表头档.”CHK_MAN”&)&0
then & picture2.visible=true
---------------------------------------------------------
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 fastreport 字段运算 的文章

 

随机推荐