ReportBuilder如何增加自定义函数?(100分)

  • 主题发起人 主题发起人 softdog
  • 开始时间 开始时间
S

softdog

Unregistered / Unconfirmed
GUEST, unregistred user!
如题,谢谢!
 
借花献佛

实现方法
先确定一下我们要实现什么?
在RAP中,我们增加一个这样的函数:
Function GetCorpName:String//取得软件用户的公司名称。
注意,我们是要在RAP中实现。如果对于Delphi的代码,这很易实现,比如这是在Delphi实现代码:
Function GetCorpName:String
Var
LsIni:TiniFile;
begin
With lsIni.Create(‘test.ini’)do
Try
Result:=ReadString(‘main’,’CorpName’,’’);
Finally
Free;
end;
end;
现在已经知道了要干什么了。那么如何利用RB的方案来实现呢?具体来说,要经过如下几步来实现:
1定义TraSystemFunction的子类;
2重载TraSystemFunction几个方法;
3利用raRegisterFunction注册实现的子类;
第一步,如何定义 TraSystemFunction?
在RAP中,已经实现了TraSystemFunction类的5个子类,因此我们要实现的类可以直接从现有的子类中继承。看一下这几个子类:
TraSystemFunction
|
-- TraStringFunction
|
-- TraConversionFunction
|
-- TraFormatFunction
|
-- TraDateTimeFunction
|
TraMathFunction
由于要定义的函数GetCorpName返回的是String,所以从TraStringFunction继承就是了。具体定义如下:
TmyGetCorpNameFunction=class (TmyStringFunction)
Public
Procedure ExecuteFunction(aParams:TraParamList);override;
Class Function GetSignature:String;override;
Class Function HasParams:Boolean;override;
end;
这里,TraSystemFunction及raRegisterFunction在raFunc单元中定义,因此你一定要在uses子句中引用raFunc。
第二步,重载TraSystemFunction的方法
通过第一步的定义,已经看到在TmyGetCorpNameFunction类中定义了三个方法,那你一定知道要重载的具体内容了。
1.Procedure ExecuteFunction(aParams:TraParamList);override;
从其名称不难看出,这里的代码就是在RAP中具体调用的Delphi原生代码!参数aParams的作用是:引入自定义函数参数列表及返回函数的结果。比如:自定义的函数的格式为:
Function MaxNum(I,I :integer):Boolean;
那么,当在RAP中以这样的格式调用MaxNum(12,20),那么12,20会通过aParams传进去,其Boolean型结果也会通过aParams返回。为了取得传进的参数,我们会用到
GetParamValue(ParamIndex,LocalVar);
接上例MaxNum,为了得到12及20,这样写代码:
GetParamValue(0,lsInteger1);//返回12
GetParamValue(1,lsInteger2);//返回20
这里,ParamIndex对应传进参数的序号;LocalVar是接受参数值的临时变量,也就是需要在ExecuteFunction中声明的,当然是有几个参数需要定义几个这样的变量。
如何返回函数的结果呢?这要用到
SetParamValue(MaxParamIndex,lsResult);
接上例,则这样调用:SetParamValue(2,lsResult);
为什么MaxParamIndex传进2作为其值呢?通过上面的GetParamValue就可以看出来,不是吗?
2. Class Function GetSignature:String;override;
这个函数返回RAP中自定义函数的声明,注意,不是Delphi版本中声明。
例如,对于上文中提到GetCorpName函数,应这样实现:
class Function TmyGetCorpName.GetSignature:String;
begin
result:=’function GetCorpName:String’;
end;
实际上,此函数结果在注册后会出现在报表设计器CALC页中的Tool Language中,以供用户使用。
3.Class Function HasParams:Boolean;override;
此函数从其名称可以猜到是判断自定义函数是否有参数。实际就是如此。如果返回True,则自定义函数有参数,否则没有参数。对于GetCorpName自定义函数,就要这么写代码:
class function HasParams:Boolean;override;
begin
result:=false;//此定义函数无参数
end;
实际上,HasParams就是针对无参数的自定义函数而作,如果要实现的自定义函数有参数,那就不需要重载此函数。
关于此要重载的函数,除了上述说明外,还有一个isFunction,如果你定义的函数是一个过程,则需要重载,以返回False.实现过程同HasParams差不多。
第三步,注册为定义函数而定制的类
这里要用到raRegisterFunction(const aFunctionName: String;
aClass: TraSystemFunctionClass);
一个定制的类,只有通过raRegisterfunction的注册,才能使其实现在函数出现在 RAP的Code ToolBox中。此外,注册函数应写在单元的initialization段中。
如:
initialization
raRegisterFunction(‘GetCorpName’,TmyGetCorpFunction);
写到这里,一个无参数的自定义函数GetCorpName已经定义完成,最后让我们看看其完整的代码:
unit myRAPFUC;
interface
uses
SysUtils, Windows, Messages, Classes, Graphics, Controls,
Forms, Dialogs, raFunc, ppRTTI, DataMdl;
type
TMyGetCorpNameFunction = class(TraStringFunction)
public
procedure ExecuteFunction(aParams: TraParamList);
override;
class function GetSignature: string;
override;
class function HasParams: boolean;
override;
end;

implementation
procedure TmyGetCorpNameFunction.ExecuteFunction(aParams: TraParamList);
var
lsResult: string;
begin
lsResult := dm.czyMC;
SetParamValue(0, lsResult);
end;

class Function tmyGetCorpNameFunction.GetSignature: string;
begin
result := 'Function GetCorpName:String;';
end;

class function TmyGetCorpNameFunction.HasParams: Boolean;
begin
result := false;
end;

initialization
raRegisterFunction('GetCorpName', TmyGetCorpNameFunction);
end.
所附单元在delphi4+rb5enterprise通过,我作了最大的简化以减少入门的难度,当你掌握此处的实现方法,就可以进一步学习定义带参数的自定义函数等等,实际上,你可以在ExecuteFunction中尽情的发挥你的想象力,好让你的用户在自定义报表过程中不受你Delphi代码的束缚!
尽情享受Report builder带给我们的自由空间吧。
I love Delphi,I love Report Builder.
为RB定制支持参数的自定义函数
通过昨天的短文,检阅过的朋友已经了解如何为Report Builder的RAP建立一个简单的自定义函数,同时我亦提到,发挥自已的想象力,就可以将诸多的Delphi原生代码呈现给你的用户,当然也包括你自身,站在用户角度去完成应用报表的最终定义,从而将编程与应用分为,减少开发者的麻烦。在我的编程经历中,最讨厌的就是为用户画报表,太无聊亦无意义的事情,莫过如此。我宁愿花几小时的时候去调试我的代码,也不愿花10分钟去为用户画一个报表。不知道你有没有同感……正因为如此,所以我想尽可能的通过自定义函数的形式,去增加用户可用的报表定义功能,是一件非常用意义的事情。
为了感谢大家对我的鼓励,所以想继续完成上文中没有提到的部分,作一个支持带参数的自定义函数,先确定一下具体的任务,实现下面的函数,在RAP中返回如下的页数格式‘第n页 共m页’,原型如下:
Function ChinesePageNo(PageNo,PageCount):String;
现在,任务已经确定,接下来看一下如何在Delphi中完成这样的任务。
第一步,为ChinesePageNo定义类;
TMyChinesePageNoFunction=class(TmyNewCategoryFunction)
public
procedure ExecuteFunction(aParams:TraParamList);override;
class function GetSignature:String;override;
end;
第二步,实现类ChinesePageNo;
这里的关键是如何实现ExecuteFunction,使用户能够在RAP中通过参数调用ChinesePageNo。为此,按下面步骤进行即可:
1. 从aParams取得参数;
2. 调用delphi的实现过程;
3. 利用aParams返回结果;
下面是具体的实现代码:
procedure TmyChinesePageNoFunction.ExecuteFunction(aParams:TraParamList);
var
lsInteger1,lsInteger2:integer;
lsResult:String;
begin
GetParamValue(0,lsInteger1);
GetParamValue(1,lsInteger2);
lsResult:=Format('第%d页 共%d页',[lsInteger1,lsInteger2]);
SetParamValue(2,lsResult);
end;
在上述代码中,通过GetParamValue取得传进的参数,SetParamValue返回结果。
其次,为了让最终用户能够在RAP中看到并使用ChinesePageNo,还需要实现类方法
class function GetSignature:String;overrive;并在单元的Initialization部分注册这个函数。
以下是实现代码:
class function TmyChinesePageNoFunction.Getsignature:String;
begin
result:='Function ChinesePageNo(const PageNo,TotalPage:Integer):String;';
end;
initialization
raRegisterFunction('ChinesePageNo',TmyChinesePageNoFunction);
end.
综上,我们已经完成了整个函数的定义。最后来看看如何在RAP中调用。以下过程是在Report Builder的RAP中实现的。
1. 在报表的Footer条上放一个Variable,右键选取“计算”菜单,进入具体的编码过程;
2. 假定使用的ppReport的UserName为[Report],则为Variable写如下代码:
Value :=ChinesePageNo(Report.PageNo , Report.PageCount);
3. 最后,预览一下报表,会看到在Variable处正确的显示了’第1页 共1页’。
 
ReportBuilder有没有象eReport那样简单的实现向报表中传递变量的方法?
 
接受答案了.
 
后退
顶部