Fastreport使用经验(转)在Delphi程序中访问报表对象
Fastreport使用经验(转) 在Delphi程序中访问报表对象
最基本的方法就是frxReport1.FindObject。
然后把返回的对象强制转换成它的类型,当然,在报表中必须真的有这么个东东。如改变一个
Tfrxmemoview的内容,可以这样写TfrxMemoView(frxReport1.FindObject('memo1')).Text:='jade';
还可以用TfrxReportPage的FindBand方法,这个方法的参数是Band类,如报表抬头就可以直接使用这个方法,因为抬头一个页中只有一个,如
果有多个同样的类。则不能使用这种方法。如果要使用TfrxreportPage,一般可以用这样的代码 TfrxReportPage(frxReport1.Pages[0])。
当然,如果你的这个页是对话框型的,则不行了。但一般都是报表型的。
******使用上下标 在Fastreport中使用上下标是很简单的,只要用一个Tfrxmemoview,把AllowHTMLTags属性设为真,
就可以使用网页标签来实现上下标了,如
12<sup>2</sup>与24<sub>3</sub>。
就分别是2为上标,3为下标。
******
打印页码 打印页码是很简单的,只要加入一些常量即可,
如打印第几页共几页就可以使用 第[Page#]页 共[TotalPages#]页 这里要注意的一点是如果想正确显示总页数,必须选中二次报表。
******
动态建立变量及变量组 建立变量组名 frxreport1.Variables.Add.Name:=' '+变量组名;
建立变量名 frxreport1.Variables.AddVariable('组名,如果为不存的组或空,则为默认组,
这里不需要空格',变量名,变量初始值); 例如要建立变量组Yuan,二个变量Yuan1,Yuan2,则为 frxreport1.Variables.Add.Name:=' Yuan';注意前面是空格 frxreport1.Variables.AddVariable('Yuan',Yuan1,初始值) frxreport1.Variables.AddVariable('Yuan',Yuan2,初始值)
******
共用TFrxreport及TfrxDBDataSet 一个程序中,不管多么大的程序,只要打印或预览时是模式的,
则完全可以共用一个TFrxreport变量及几个TfrxDBDataSet。只不过,要注意完
成一个报表程序的步骤,主要是下面几步
1)清除报表,得到一个全新的报表内容。
Frxreport1.clear。
2)设置要使用的TfrxDBDataSet的别名,如果不需要可以省略这一步,但一般最好不同的报表用不同的别名。
注意这一步要在加载报表文件之前,因为一般设计报表文件时已经包含了别名信息。 frxDBDataSet1.UserName:=别名;
3)加载报表或动态建立一个TfrxReportPage。 Frxreport1.LoadFromFile(报表文件的完整文件名);
4)关联TfrxDBDataSet与TDataset,并设置要使用哪些TfrxDBDataSet。
Frxreport1.DataSets.Clear;//先清除原来的数据集
frxDBDataSet1.DataSet:=dataset1; //关联Fastreport的组件与TDataset数据集。
Frxreport1.DataSets.Add(frxDBDataSet1);//加载关联好的TfrxDBDataSet到报表中。
经过这几步后,就可以像单独使用一个Tfrxreport一样使用共用的报表组件了。
******
加入自定义函数 Fastreport可以自己加入需要的函数,来实现特定的功能。过程就是:
1)添加函数到报表中。 frxreport1.AddFunction('完整的函数声明');
如有一个自定义函数,为GetName(Old:String):String;这个函数通过数据集的一个字段,得到另一个返回值。
则语句为:frxreport1.AddFunction('Function GetName(Old:String):String;'); 2)脚本中使用函数。
在脚本中或报表中使用自定义函数,就像使用其它Fastreport内置函数一样。 3)程序中处理函数。
使用函数是通过frxreport1的OnUserFunction函数来实现的。
OnUserFunction的声明如下:
Function(const MethodName: String;var Params: Variant): Variant; 比如上面的函数,首先要有一个函数,这个函数是GetName的实现部分。
如有一个在程序中实现的函数。 function RealGetName(Old:String):String;这个函数名是无所谓的,也可以是GetName。
在OnUserFunction的事件处理中有如下代码即可完成自定义函数在报表中的使用。
if CompareText(MethodName,'GetName')=0 then Result:=RealGetName(VarToStr(Params[0]));
我一般都是使用CompareText来比较函数名,因为我发现二个版本的Fastreport,一个是MethodName全部自动变成了小写,一个是全部自动变成
了大写,所以干脆用CompareText来比较,肯定不会出错。
如果有多个参数,则依次传递Params[0],Params[1]即可,要保持顺序一致。 这里要注意一点,如果参数为指针,则不能直接使用Pointer(Integer(Params[0]))。
因为实际传递过来的是指针的整数值,可以使用Pointer
(StrToInt(VarToStr(Params[0])))。
******
使用脚本,脚本中使用变量 很多时候,我们希望把对报表的控制放到报表的脚本中,通常我这样做有二个原因: 1)能够根据字段内容的变化而使用不同的设置,因为如果想在程序中实现这样功能,就不得不用自定义函数,函数的实现要放到程序中,函数
可能需要传递很多参数,效率低下。 2)把不同报表的控制放到脚本中,可以实现报表的模块化,程序只是简单的设置数据集的关系,并加载硬盘上的报表文件,不同报表的不同实
现方式,显示方式,均放到报表文件中,程序简洁,易维护,易升级。 当然,这样的缺点就是程序中加载报表时的数据集别名必须与设计报表时的别名一致。 脚本的使用与通常程序的使用并没有太多的区别,就是像正常的程序那样引用控件的名称即可。 但注意对变量的使用,需要把变量名或表达式用<>括起来。
******在脚本中根据字段名改变Tfrxmemoview的内容 假设有数据表“用户”,字段ID为用户标识,Name为用户名,打印时要求,如果用户名为空,则打印“无用户名”,否则打印出“用户名:实
际的用户”,则可以在ID的Tfrxmemoview控件的OnAfterData事件中写如下脚本。 if <frxDBDataSet1."Name">='' then Memo2.Text:='无用户名' else Memo2.Text:='用户名:[frxDBDataSet1."Name"]' Memo2是放置用户名称数据的Tfrxmemoview控件。 这里注意,要在脚本中访问变量需要把变量用<>包括起来。
******实现连续打印 很多人认为Fr不能实现连续打印,以为只能通过自己写函数调用打印函数来实现连续打印,实际上,Fr可以轻易的实现连续打印,同时,实现
时又是非常简单,你甚至可以在你的程序的打印设置中简单的让客户选择是否连续打印,其它都可以保持不变。
function PelsTomm(Pels:Extended):Extended; begin Result:=Pels/Screen.PixelsPerInch*25.4; end;
procedure PrintSerial(Frx:TFrxReport;SequencePage:Byte=0); var P:TfrxReportPage; R,R1:Extended; begin {必须是二遍报表,否则无法计算总页数。 下面的方法只适用于没有页脚的情况,因为如果有页脚的话 FreeSpace就始终为0了。可以用报表脚来代替。 因为是连续打印,也可以看作只有一页,报表脚也就相当于页脚了} if not Frx.Engine.DoublePass then Exit; //SequencePage指要连续打印的页面,普通报表就是0 P:=TfrxReportPage(Frx.Pages[SequencePage]); R1:=P.TopMargin+P.BottomMargin; while Frx.PrepareReport do begin if (Frx.Engine.TotalPages<=1) then Break; R:=Pelstomm(Frx.Engine.TotalPages*Frx.Engine.PageHeight- Frx.Engine.FreeSpace)+R1; P:=TfrxReportPage(Frx.Pages[SequencePage]); P.PaperHeight:=R; end; {必须用上面的循环代码来得到准确的空白区域 不能用通过计算总页数减去各页的页边距的方法来获得空白区域 因为如果碰到一条记录过宽的情况导致换页,就不准确了。} R:=Pelstomm(Frx.Engine.TotalPages*Frx.Engine.PageHeight- Frx.Engine.FreeSpace)+R1; P:=TfrxReportPage(Frx.Pages[SequencePage]); P.PaperHeight:=R; end;
在预览或打印前先调用PrintSerial即可。
也谈为Delphi中数据库报表加网格开发者在线 Builder.com.cn 更新时间:2007-11-02作者:佚名 来源:中国计算机报社 本文关键词: delphi 数据库 报表 网格 看了贵报第63期《为Delphi 3.0中数据库报表加上网格线》一文,笔者发现原文中的程序在不同分辨率的打印机(如180dpi的针式打印机和
600dpi的激光打印机)上打印表格,效果会完全不同。如作者以针打作为他的输出打印机设计的程序,在激光打印机上输出,就会发现表格和
文字错位,而且表格会打印得很小。而且原文中打印坐标的确定,必须靠反复的试验才能达到比较满意的效果。
针对原目标,笔者设计了一段程序。首先在窗体上添加一个DBGrid来显示我们所要打印的数据,在这里,DBGrid不只是起到显示数据的作
用,而且用户对DBGrid作的调整,例如改变了各字段的排列顺序,各字段的显示宽度等,都将直接反映到打印结果中去,也就是说,我们实际
上就是要把DBGrid的内容直接输出到打印机。以下程序在Win 98+Delphi 4下编译通过,代码如下:
procedure TForm1.Button2Click(Sender: TObject); const LeftBlank=1; //定义页边距,单位厘米 RightBlank=1; TopBlank=1; BottomBlank=1; var PointX,PointY:integer; PointScale,PrintStep:integer; s:string; x,y:integer; i:integer; begin //获取当前打印机的分辨率 PointX:=Trunc(GetDeviceCaps(Printer.Handle,LOGPIXELSX)/2.54); PointY:=Trunc(GetDeviceCaps(Printer.Handle,LOGPIXELSY)/2.54);
//根据打印机和屏幕的分辨率计算出从屏幕转换到打印机的比例 PointScale:=Trunc(GetDeviceCaps(Printer.Handle,LOGPIXELSX) /Screen.PixelsPerInch+0.5); //横向打印 printer.Orientation:=poLandscape;
//打印的字体和大小 printer.Canvas.Font.Name:=′宋体′; printer.canvas.Font.Size:=10;
//根据字体的大小确定每行的高度 s:=′漳州市刑警支队′; PrintStep:=printer.canvas.TextHeight(s)+16;
//打印的起点位置 x:=PointX*LeftBlank; y:=PointY*TopBlank;
//DataSource1是DBGrid1所连接的数据源
if ((DataSource1.DataSet).Active=true) and ((DataSource1.DataSet).RecordCount〉0) then begin printer.BeginDoc; (DataSo e1.DataSet).First; while not (DataSource1.DataSet).Eof do begin //打印DBGrid中的所有列 for i:=0 to DBGrid1.FieldCount-1 do begin //假如所要打印的列超出了打印范围,则忽略该列 if (x+DBGrid1.Columns.Items[i].Width*PointScale)〈=(Printer.PageWidth-PointX*RightBlank) then begin //画表格线 //每页的第一行打印表头 Printer.Canvas.Rectangle(x,y,x+DBGrid1.Columns. Items[i].Width*PointScale,y+PrintStep); if y=PointY*TopBlank then Printer.Canvas.TextOut(x+8,y+8,DBGrid1.Columns[i].Title.Caption) else Printer.Canvas.TextOut(x+8,y+8,DBGrid1.Fields[i].asString); end; //计算下一列的横坐标
x:=x+DBGrid1.Columns.Items[i].Width*PointScale; end;
if not (y=PointY*TopBlank) then (DataSource1.DataSet).next;
x:=PointX*LeftBlank; y:=y+PrintStep; //换页 if (y+PrintStep)〉(Printer.PageHeight-PointY*BottomBlank) then begin Printer.NewPage; y:=PointY*TopBlank; end; end;
printer.EndDoc; (DataSource1.DataSet).First; Application.MessageBox(′打印完成′,′打印′,32); end; end;
来源:http://blog.sina.com.cn/s/blog_5558f98d01009555.html
Fastreport使用经验(转)在Delphi程序中访问报表对象的更多相关文章
- 在java程序中访问windows有用户名和密码保护的共享目录
在java程序中访问windows有用户名和密码保护的共享目录 Posted on 2015-11-20 14:03 云自无心水自闲 阅读(3744) 评论(0) 编辑 收藏 --> Jav ...
- 远程控制篇:在DELPHI程序中拨号上网
用MODEM拨号上网,仍是大多数个人网民选择上网的方式.如果能在我们的应用程序中启动拨号连接(如IE浏览器程序中的自动拨号功能),无疑将会方便我们的软件用户(不用再切换应用程序,运行拨号网络),提高我 ...
- Silverlight程序中访问配置文件
以下代码为本人在一Silverlight程序中访问Web端配置文件的代码: private void GetLoadNeed() { // 项目名称读取配置文件 WebClient wcConfigX ...
- delphi程序中定义热键
delphi程序中定义热键 用到3个API函数 BOOL RegisterHotKey ( HWND hWnd, //响应该热键的窗口句 ...
- PHP程序中使用PDO对象实现对数据库的增删改查操作的示例代码
PHP程序中使用PDO对象实现对数据库的增删改查操作(PHP+smarty) dbconn.php <?php //------------------------使用PDO方式连接数据库文件- ...
- C#程序中访问配置文件
在C#编程中,有时候会用到配置文件,那么该如何在程序中获取或修改配置文件中的相关数据呢?下面采用一个简单的C#控制台程序来说明. 新建一个C#控制台程序,打开“解决方案资源管理器”,如下图: 可以看到 ...
- java程序中访问https时,报 PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
在java中使用https访问数据时报异常: Caused by: sun.security.validator.ValidatorException: PKIX path building fail ...
- net abp core的appservice中访问httpcontext对象
private readonly IHttpContextAccessor _httpContext; /// <summary> /// Initializes a new instan ...
- 【转】资源文件在Delphi编程中的应用
段东宁 计亚南 (郴州职业技术学院, 湖南 郴州 423000) 摘要: 资源文件是一种能有效地组织.管理和使用资源的文件形式,在软件开发中有着广泛的应用.本文详细介绍了在Delphi编程中资源文件 ...
随机推荐
- Hibernate-清理一级缓存
Session执行一些sql语句把内存中的对象的状态同步到数据库,这个过程被称为session清理. 在默认情况下,Session会在下面的时间点清理缓存. 1 当应用程序调用net.sf.hiber ...
- 【CodeForces 624D】Array GCD
题 You are given array ai of length n. You may consecutively apply two operations to this array: remo ...
- Mac OS X系统下编译运行C代码
1.使用编译器将源文件中的代码转换为二进制代码,这个过程叫做编译. 将终端的工作路径切换到源文件所在的路径. cc -c 源文件的名称.例如:cc -c main.c 如果没有意外的话,就会在当前工作 ...
- Java集合类: Set、List、Map、Queue使用
目录 1. Java集合类基本概念 2. Java集合类架构层次关系 3. Java集合类的应用场景代码 1. Java集合类基本概念 在编程中,常常需要集中存放多个数据.从传统意义上讲,数组是我们的 ...
- BZOJ1001 狼抓兔子(裸网络流)
Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一 ...
- groovy-脚本和类
在groovy中定义类和java中是一样的.类的方法可以是static,也可以是非static的. groovy中的方法可以是public, protected, private,同时也支持java中 ...
- App接口简介
- Java初学(五)
一.成员变量和局部变量区别(成员变量默认为包内访问权限,即使是子类,不在一个包内也无法访问) 1.在类中的位置不同 成员变量:在类中方法外: 局部变量:在方法定义中或者方法声明上 2.在内存中的位置不 ...
- 点击cell弹出一个日期选择器
- (void)setUpGroup2 { ILGroupItem *group = [[ILGroupItem alloc] init]; // 结束时间 ILSettingItem *endTim ...
- Hibernate unsaved-value 属性
Session的saveOrUpdate方法是由Hibernate来判断被操作对象究竟是一个持久化对象还是临时自由状态对象.这需要在对象映射文件的主键id中定义unsaved-value属性,如果不显 ...