自定义函数

阅读(660) 标签: function, dsfunction, customfunctions,

自定义函数用法介绍

背景说明:

润乾报表提供了大量的内置函数,但是再多的函数也无法完全满足五花八门的业务需求,用户往往需要自定义函数。

  自定义函数的标准写法是:继承润乾报表提供的Function类或者DSFunction,实现其中的calculate方法,并返回运算结果。

  自定义函数的登记:在java的类路径的config目录下,找到customFunctions.properties文件(如果没有需要自己创建),并在其中进行自定义函数类及函数名的登记。customFunctions.properties的位置路径如下图所示:

 

 

代码示例1

import com.raqsoft.report.model.expression.Function;  //普通函数抽象类

import com.raqsoft.report.usermodel.Context;

 

public class SimFunction extends Function {  //继承普通函数抽象类

  public Object calculate(Context ctx) { //标准接口,ctx为运算环境

 

    Object value=null;

    ……  //函数主体代码

    return value;

  }

}

代码示例2

import com.raqsoft.report.model.expression.DSFunction;  //数据集函数抽象类

import com.raqsoft.report.usermodel.Context;

 

public class DsFun extends DSFunction {  //继承数据集函数抽象类

  public Object calculate(Context ctx) { //标准接口,ctx为运算环境

    Object value=null;

    ……  //函数主体代码

    return value;

  }

}

customFunctions.properties示例:

  //0代表普通函数,1代表数据集函数

sim=0,com. raqsoft.report.selfdefine.SimFunction

dsfun=1,com. raqsoft.report.selfdefine.DsFun

 

参考文件:customFunctions.properties

 

普通函数

背景说明:

普通函数的逻辑比较简单,一般是传入参数,然后根据业务逻辑,对传入的参数进行各种运算,最后返回结果值对象。

常用的方法是:接受函数的传入参数表达式,判断参数个数,计算参数表达式,判断结果参数值的数据类型,进行业务逻辑运算,返回运算结果值

可能比较复杂的情况:需要获取系统数据源,和数据库进行交互

代码示例:

import com.raqsoft.common.MessageManager;

import com.raqsoft.common.PwdUtils;

import com.raqsoft.common.ReportError;

import com.raqsoft.report.model.expression.Expression;

import com.raqsoft.report.model.expression.Function;

import com.raqsoft.report.model.expression.Variant2;

import com.raqsoft.report.resources.EngineMessage;

import com.raqsoft.report.usermodel.Context;

 

public class Encrypt extends Function {

  public Object calculate(Context ctx) {

    //判断参数个数

    if (this.param == null || this.param.getSubSize() !=0) {

      MessageManager mm = EngineMessage.get();

    throw new ReportError("encrypt:" + mm.getMessage("function.missingParam"));

    }

    //取得第一个参数,默认为表达式,需要把该表达式算出来,结果才是函数的参数值

    Expression param1=(Expression)this. param.getLeafExpression();

    if (param1 == null) { //判断参数是否为空

      MessageManager mm = EngineMessage.get();

      throw new ReportError("encrypt:" + mm.getMessage("function.invalidParam"));

    }

    //算出第一个参数值

    Object result1 = Variant2.getValue(param1.calculate(ctx), false);

    //判断第一个参数值是否为空

    if (result1 == null) {

    return null;

    }

    //判断第一个参数值的数据类型

    if (! (result1 instanceof String)) {

    MessageManager mm = EngineMessage.get();

    throw new ReportError("encrypt:" + mm.getMessage("function.paramTypeError"));

    }

}

 

  获取数据源代码示例:

import ……  //引入相关类包

public Object calculate(Context ctx) {

IConnectionFactory conFactory = null;  //数据连接工厂

Connection cn = null;  //数据库连接对象

try {

String dbName = ctx.getDefDataSourceName();  //获取系统数据源名称

DataSourceConfig dsc = ctx.getDataSourceConfig(dbName);  //获取系统数据源配置

cn = ctx.getConnection(dbName);  //获取数据库连接对象

if (cn == null ) {

conFactory = ctx.getConnectionFactory(dbName); //未取到数据库连接,取同名数据连接工厂

if (conFactory == null){  //无法获取正确数据库连接,返回错误信息

MessageManager mm = DataSetMessage.get();

throw new ReportError(mm.getMessage("error.noConnection", dbName, dbName));

}

cn = conFactory.getConnection();

}

if (cn == null || cn.isClosed()) {  //无法获取正确数据库连接,返回错误信息

MessageManager mm = EngineMessage.get();

throw new ReportError("query:" + mm.getMessage("function.noConnetion"));

}

String dbCharset = dsc.getDBCharset();  //获取数据库字符集

if (dbCharset == null) dbCharset = "GBK";

String clientCharset = dsc.getClientCharset();  //获取本地字符集

if (clientCharset == null) clientCharset = "GBK";

……  //其它函数主体代码

return ……  //返回函数结果值

}

 

参考文件:Encrypt.javaQuery.java

 

数据集运算函数

背景说明:

数据集函数除了涉及到2.4.1.2中介绍的参数输入输出以外,最重要的是还涉及了数据集的调用与访问,本小节重点介绍如何在自定义函数中访问数据集。

代码示例:

public Object calculate(Context ctx) {

//……  //获取参数,以及对参数的合法性进行各种判断,参见2.4.1.2

boolean isRoot=true;  //是否根集

Group group = null;

if (!isRoot) {  //获取当前行集,其中isRoot表示是否根集

DsValue cur = this.ds.getCurrent();  //当前行集

if (cur instanceof Row) {

( (Row) cur).setValue(selectExp.calculate(ctx));

return cur;

}

group = (Group) cur;

}

else {

    group = this.ds.getRootGroup();  //获取根集

  }

  Expression filterExp=……;  //过滤表达式

  Expression sortExp=……;  //排序表达式

  Expression selectExp=……;  //取出表达式

 

group = group.filter(filterExp, ctx);  //对当前行集过滤

group = group.sort(sortExp, true, ctx);  //对当前行集排序

  int count = group.getRowCount();  //获得当前行集的记录数

  Object result=null;  //用于存放最大值的变量

  Row retRow=null //用于存放最大值对应的记录行对象

  for (int i = 0; i < count; i++) {  //逐行获取表达式值,并做相应业务处理

    Row row = group.getRow(i);

    Object v = Variant2.getSingleValue(row.evaluate(selectExp, ctx), false);

    //……  //做相应的业务处理,例如求最大值等

  }

  if (result != null) {  //将求得的最大值放进最大值对应的行对象并返回

    retRow.setValue(result);

    return retRow;

  }

  return ds.getNullRow();

}

参考文件:DSMax.java