自定义类

阅读(7989) 标签: class,

本章主要介绍润乾报表自定义类的使用,通过学习,可以更深入的了解自定义类的用途。

自定义函数

自定义函数用法介绍

背景说明:

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

自定义函数的标准写法是:继承润乾报表提供的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.scudata.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.usermodel.Context;

 

public class Encrypt extends Function {

public Object calculate(Context ctx) {

// 判断参数是否为空

 

if (this.param == null) {

throw new ReportError("参数列表不能为空");

}

//参数是否为单值

if (this.param.isLeaf()){

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

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

 

//算出第一个参数值

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

 

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

if (result1 == null) {

return null;

}

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

if (! (result1 instanceof String)) {

MessageManager mm = EngineMessage.get();

throw new ReportError("参数类型错误");

 

// 对第一个参数进行加密,并返回加密结果

String value = PwdUtils.encrypt((String) result1);

return value;

}else{

throw new ReportError("参数无效");

}

}

}

}

◆ 多参数代码示例:

import com.scudata.common.MessageManager;

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 SignFunc 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.invalidParam”));

 }

 // 获取第一个参数的表达式,从 0 开始

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

 // 算出第一个参数值

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

 

 /*

* 当存在多个时,参考以下代码。 this.param.getSubSize() 可以获取到参数的总个数,可以将下面的示例改为遍历取值

 **/

 // 获取第二个参数的表达式

Expression param2=(Expression)this.param.getSub(1).getLeafExpression();   

 // 算出第二个参数值

Object result2 = Variant2.getValue(param2.calculate(ctx),false);

 

 /*

 *.., 当多余 2 个时,按照上面代码以此类推,可定义为遍历方式

**/

return result1.toString();

}

}

  获取数据源代码示例:

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

自定义数据集

自定义数据集介绍

背景说明:

报表的数据来源大部分来自数据库,正常情况润乾报表都能自动处理,但是也会有特殊的情况,例如通过中间件连接数据库而非直连?通过业务程序算出的数据传递给报表进行展现等等。因此需要用户自定义数据集。

自定义数据集常用到的API接口主要包括获取系统数据源连接、获取报表参数、读取定义数据集时定义的传入参数、读取同一报表中已算出的数据集、构造数据集并返回等等

自定义数据集时自定义类需要做如下两步:

1实现润乾报表提供的com.raqsoft.report.dataset.IDataSetFactory接口中的createDataSet方法

2、继承com.raqsoft.report.dataset.CustomDataSetFactory类。该类用于记录数据集数据量,主要为了防止多个数据集时,数据积累溢出

注意:com.raqsoft.report.dataset.CustomDataSetFactory类里已经实现了createDataSet方法,因此在自定义类中必须复写该方法

 

具体请看如下示例:

代码示例:

package api;  //定义类路径

import com.raqsoft.report.dataset.CustomDataSetFactory;

import com.raqsoft.report.dataset.DataSet;

import com.raqsoft.report.dataset.Row;

import com.raqsoft.report.usermodel.Context;

import com.raqsoft.report.usermodel.CustomDataSetConfig;

import com.raqsoft.report.usermodel.DataSetConfig;

import … …; //其他需要引入的相关类包

 

public class MyDataSet extends CustomDataSetFactory  {

public  DataSet createDataSet(Context ctx, DataSetConfig dsc, boolean retrieve) {

//ctx为报表引擎环境,dsc为数据集定义类,reteieve是指是否检查出数据,如果为false,只返回数据集的结构

DataSet ds=null;

……  //主体代码

return ds;  //返回结果数据集

}

}

参考文件:MyDataSet.java

 

注意:要把写好的MyDataSet.java编译后的.class文件放到java类路径下,否则找不到这个类,会提示计算数据集失败。

在设计器中使用自定义类应把编译后的.class文件放在classes\自定义类所在的包名下面。比如MyDataSet.javacom.raqsoft包中,那么就应该把编译后的MyDataSet.class文件放在设计器安装路径\classes\com\raqsoft包中,如果classes下面不包含com.raqsoft包,用户需要自己新建。如下图所示:

 

在服务器中运行使用自定义类的报表文件时应把自定义类编译后的.class文件放在raqsoft\webapps\WEB-INF\classes\自定义类所在的包名下面。比如MyDataSet.javacom.raqsoft包中,那么就应该把编译后的MyDataSet.class文件放在设计器安装路径\raqsoft\report\web\webapps\WEB-INF\demo\classes下的 com\raqsoft包中,如果classes下面不包含com. raqsoft包,用户需要自己新建。如下图所示:

 

 

获取系统数据源连接

背景说明:

自定义数据集往往需要自行连接数据库获取数据,因此需要调用API获取系统数据源

代码示例:

String datasourceName = dsc.getDataSourceName(); //获取数据集定义里设置的数据源名称

if( datasourceName==null || "".equals(datasourceName) ) //如果数据集里没有指定数据源,则取系统默认

datasourceName = ctx.getDefDataSourceName();  //取系统默认数据源

Connection con;

try {

con = ctx.getConnectionFactory( datasourceName ).getConnection(); //获取数据库连接

System.out.println( "得到的数据源是:"+con );  //把数据库连接打出来看看是否正确

//………  //主体代码

con.close();  //最后所有任务完成,不要忘了关闭数据库连接

} catch (Exception ex) {

ex.printStackTrace();

}

参考文件:MyDataSet.java

 

获取报表参数

背景说明:

自定义数据集里,往往需要根据报表传入的参数来生成返回的数据集,因此需要调用API接口获取报表参数

代码示例:

Map map = ctx.getParamMap(false); //获得当前报表的所有参数对照表

if( map != null ){

Iterator it =map. keySet().iterator();

while( it.hasNext() ){

String key = it.next().toString();  //获取参数名

Object value = map.get(key);  //获取参数值

System.out.println("报表传入的参数"+key+"的值是:"+value);  //打出参数名和参数值

//……  //主体代码

}

}

参考文件:MyDataSet.java

 

读取定义数据集时定义的传入参数

背景说明:

定义数据集时,允许为自定义数据集单独传入一些参数,必须注意的是,此时传入的参数值都为字符型。如果有特殊需要,可以在获取参数值后自行进行数据类型的转换。如果传入的参数值需要是表达式,那么也以字符串的形式传进去,然后在自定义数据集里把字符串转换成表达式,再把表达式算出来。

 

如上图所示,假设我们定义数据集的时候定义了三个传入参数,这三个参数分别为整数、字符、表达式,可是我们在自定义数据集里接收到的都是字符串,请看如下代码,如何进行转换:

 

代码示例:

 

//读取定义数据集时定义的传入参数

CustomDataSetConfig cdsc = (CustomDataSetConfig)dsc; //把数据集定义类转成自定义数据集类

String[] args = cdsc.getArgNames();  //获取自定义数据集传入参数名的集合

String[] vals = cdsc.getArgValue();  //获取自定义数据集传入参数值的集合

int intValue=0;

Object expValue=null;

if( args != null ){

for( int i=0; i<args.length; i++ ){  //依次获取传入参数值

String key = args[i];

if(key==null) continue;

String value = vals[i];

System.out.println("定义数据集时传入参数"+key+"的值是:"+value); //打出传入参数值

if(key.equalsIgnoreCase("intValue")){  //把传入参数转成整型

intValue=Integer.parseInt(value);

}

else if(key.equalsIgnoreCase("expValue")){  //把传入参数解析成表达式并计算出表达式值

Expression exp=new Expression(ctx,value);

expValue=exp.calculate(ctx);

}

System.out.println("定义数据集时传入参数"+key+"的值是:"+ expValue); //打出计算后的参数值

//………  //主体代码

}

}

参考文件:MyDataSet.java

 

读取同一报表中已算出的数据集

背景说明:

润乾报表支持多数据集,因此就出现了这样的需求:同一个报表中,某个数据集的生成依赖于另一个数据集的结果数据。

  为了实现这种依赖关系,同时也为了避免循环引用等,润乾报表规定了数据集的运算顺序,严格按照定义时的顺序进行运算。即定义在前面的数据集先算,定义在后面的后算,后面的数据集可以引用前面的数据集。

  于是,自定义数据集也必然出现了这样的需求:引用报表中已经算出的数据集的值。请看如下例子代码:

 

代码示例:

DataSet ds = ctx.getDataSet("ds1");  //根据数据集的名称获取已算出的数据集

if(ds==null) return null;

int colCount=ds.getColCount();  //获得数据集的行数列数

int rowCount=ds.getRowCount();

for(int i=1;i++;i<=rowCount){  //注意数据集的行号列号从1开始

for(int j=1;j++;j<=colCount){

Object value = ds.getData(i, j);  //获取某行某列的数据值

System.out.print(""+i+"行第"+j+"列的值为");  //逐个打出数据集的值

System.out.println(value);

//…….  //主体代码

}

}

参考文件:MyDataSet.java

 

构造数据集

背景说明:

自定义数据集的最终目的是生成数据集并返回,因此必不可少的一步是构造数据集,请看如下例子代码:

代码示例:

//构造一个数据集

int rowCount=100

int colCount=3    //这是指为列信息分配的空间,一般与实际列数相等为宜   

String dsName="ds2";   //定义数据集名

String[] colNames=……;  //定义列名数组

DataSet ds2 = new DataSet(rowCount, colCount, dsName); //构造数据集的时候最好直接指定差不多的行数列数,否则每次追加行、列的时候不停地分配空间影响性能

for (int i = 0; i < colCount; i++) {  //添加列,注意:添加列要在添加行之前

ColInfoBase ci = new ColInfoBase();  //逐列构造列信息对象

ci.setColName(colNames[i]);  //设置列英文名

ci.setColTitle(colNames[i]);  //设置列中文名,这里省略,直接用英文名代替

ci.setDataType(com. raqsoft.report.usermodel.Types.DT_STRING);  //设置列的数据类型

ds2.addColInfo(ci);

//仅用于数据集运算时不需要如此多的信息,可直接调用ds.addCol(colName)即可

}

//设置数据集中的数据

//添加行

for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {

Row row = ds.addRow();  //添加行

Object[] rowData = ……;  //主体代码,构造每一行的数据

for (int i = 0; i < colCount; i++) {

try {

row.setData(i + 1, rowData[i]);  //逐行逐列设置数据集的数据

} catch (Exception e) {

throw new ReportError(e.getMessage(),e);

}

}

}

参考文件:MyDataSet.java

 

集算器文件数据转成DataSet

背景说明:

在自定义数据集时,有时候有些数据可能来自集算器文件某单元格,那我们就需要通过计算集算器文件读取数据,并转成润乾报表的数据集DataSet

  代码示例:

// 设置报表数据集中使用的数据源名称

ctx.setDefDataSourceName(dsc.getDataSourceName());

……

EsProcDataSetFactory esprocfactory = new EsProcDataSetFactory();

EsProcDataSetConfig esprocConfig = new EsProcDataSetConfig();

//设置使用自定义数据集的数据集名称

esprocConfig.setName(dsc.getName()); //

CustomDataSetConfig customConfig = (CustomDataSetConfig) dsc;

// 获取报表自定义数据集窗口中设置的参数名称和参数值

String[] argname = customConfig.getArgNames();

String[] argvalue = customConfig.getArgValue();

if (argname != null && argvalue != null&& argname.length == argvalue.length) {

List<String> esprocNames = new ArrayList<String>();

List<String> esprocValues = new ArrayList<String>();

for (int i = 0; i < argname.length; i++) {

String arg = argname[i];

// 判断是否有参数名为splPath的参数,splPath为集算器文件的路径

if ("splPath".equalsIgnoreCase(arg)) {

//设置加载集算器文件

esprocConfig.setSplFileName(argvalue[i]);

} else {

esprocNames.add(argname[i]);

esprocValues.add(argvalue[i]);

}

}

// 设置集算器文件中参数名称和参数值

esprocConfig.setParamNames(esprocNames);

esprocConfig.setParamExps(esprocValues);

… …

}

// 计算集算器文件

DataSet dataset = esprocfactory.createDataSet(ctx, esprocConfig, true);

参考文件:MyDmDataSet.java

报表计算监听类

报表计算监听类介绍

背景说明:

报表计算监听类主要用于系统执行报表计算前后进行业务处理的类,用户可以自行实现监听类,从而在报表计算前和计算后实现自己的业务处理。

报表计算监听类实现以后,需要把class文件部署到java的类路径下,然后打开报表在报表属性中设置监听类名,系统计算报表时会自动根据该类名调用相应的监听类。

 

报表计算监听类必须实现润乾报表提供的监听接口:

com.raqsoft.report.usermodel.IReportListener

该类有几个重要的变量:

protected Context context;  //计算报表时的上下文环境 

protected IReport report; //计算前后的报表对象 

获取报表计算耗用时间

背景说明:

报表计算监听类提供了计算前和计算后两种方法,可以在报表计算前后对报表进行一些操作,也可以获取在报表计算前后某个指标信息,从而比较前后的不同,比如计算一个报表计算所耗用的时间。

代码示例:

public class CalculateListener implements IReportListener {

long starttime,endtime ;

public void afterCalc(Context arg0, IReport arg1) {

starttime = System.currentTimeMillis();  //获取报表计算前系统时间

}

public void beforeCalc(Context arg0, IReport arg1) {

endtime = System.currentTimeMillis();  //获取报表计算后系统时间

//计算时间间隔,对时间间隔做相应的业务处理

System.out.println(“time:”+(endtime-starttime));

……

}

}

参考文件:CalculateListener.java

参数监听类

参数监听类介绍

u  背景说明:

参数监听类用于参数模板提交后传递给报表前对参数做业务处理的类,可以在此类中对参数进行增删、判断访问报表的权限、还可以对参数值进行保存和读取,从而实现查询条件的保存等功能。

参数监听类必须继承润乾报表提供的参数监听抽象类: com.raqsoft.report.usermodel.input.AbstractParamProcessor

请看如下代码示例:

u  代码示例:

package api;

import com.raqsoft.report.usermodel.input.*;

public class MyParamProcessor extends AbstractParamProcessor{

public void process() throws Exception {

//…… //主体代码,进行参数预处理

}

}

参考文件: MyParamProcessor.java

 

获取系统数据库连接

u  背景说明:

在参数监听类里,需要对参数进行业务处理,例如保存参数值或者读取之前保存的参数值,如果参数值存在数据库中,此时需要访问数据库,因此需要调用API接口获得系统数据库连接。

u  代码示例:

//获得系统默认数据源的连接对象,其中context为监听类固有的变量

Connection con=context.getConnectionFactory(context.getDefDataSourceName()).getConnection();

 

String dataSource=……; //指定数据源名称

Connection con=context.getConnectionFactory(dataSource).getConnection(); //获得指定数据源的连接对象

参考文件: MyParamProcessor.java

 

获得/修改/追加传入的参数

u  背景说明:

参数监听类里,可以获得前端传入的参数值并保存,也可以把保存的参数值取出来添加到当前参数池中,因此,需要调用API接口获取参数、追加、修改参数

u  代码示例:

//参数监听类里有一个固有变量params,存放了前端提交的所有参数,private Hashtable params;通过该变量可以获取所有参数的名称和参数值。

Enumeration paramNames=params.keys(); //获得参数名集合

while(paramNames.hasMoreElements()){

Object o=paramNames.nextElement();

if(o==null) continue;

String paramValue=getParamValue((String)o); //获得参数值

//…… //主体代码,例如保存参数值等

}

putParam("arg1","value"); //追加或者修改参数值

 

获取sessionapplication等信息

u  背景说明:

参数监听类里,有可能需要到用户的session里把用户身份有关的信息读出来,作为参数追加到当前的参数池中,从而在报表中实现用户权限的控制。同理,也可能把application里存放的一些全局变量取出来传递给报表。

u  代码示例:

Object o=session.getValue("userId"); //session是参数监听类的固有变量,可以直接引用

if(o!=null){

putParam("userId",(String)o);

}

自定义图片

自定义图片介绍

背景说明:

润乾报表提供了丰富的统计图,但是仍旧难以满足五花八门的业务需要,因此用户需要自定义图形。自定义图形有几种应用层次,首先从属性编辑来看,可以在自定义类中定义参数名,然后在报表中加载参数设置参数值即可,下面逐个进行介绍。

自定义图片

实现思路:

自定义图片类必须实现ICustomGraph接口。必须实现的方法包括:draw(Graphics2D arg0, StringBuffer arg1)getParamNames ()setContext (Context arg0) setHeight(float arg0)setParams(Map arg0)setWidth(float arg0)

  类写好后放在java类路径下,然后在设计器中点击【报表】->【图片】菜单,选择“自定义”,点击编辑按钮,如下图所示:

 

弹出自定义图形编辑框,如下图所示:

点击加载参数按钮,加载参数,设置参数值:

注意:

参数名为getParamNames设置的参数名列表,基格为数据的计算基准格。

 

  代码示例:

package ……;

 

import java.awt.Color;

import java.awt.Graphics2D;

import java.util.*;

import com.raqsoft.report.usermodel.Context;

import com.raqsoft.report.usermodel.graph.ICustomGraph;

public class CustomGraph implements ICustomGraph{

/**

* 自定义画图

*/

public void draw(Graphics2D arg0, StringBuffer arg1){ 

……

}

/**

* 设置自定义图形参数名,此方法方便终端用户了解底层属性设置

* 可以通过设计器菜单直接增加参数

*/

public String[] getParamNames(){

   

return  ……;

}

 

/**

* 设置上下文环境变量

*/

public void setContext(Context arg0){

……

}

/**

* 设置图片高度

*/

public void setHeight(float arg0){

……

}

/**

* 设置参数值

*/

public void setParams(Map arg0){

……  //调用此方法,设置之前设计器中传递的图片参数值

}

/**

* 设置图片宽度

*/

public void setWidth(float arg0) {

……

}

}

参考文件:customgraph.javacustomgraph.rpx

数据集监听类

数据集工厂侦听器类

背景说明

数据集工厂侦听器类是在数据集创建前、创建后由用户进行业务处理的类,常见的用法是:数据集创建前往数据库里创建临时表,或者调用某个存储过程;数据集创建后删除数据库里的临时表或者调用某个存储过程。

因此,总体来说,数据集监听类主要用于数据集创建前后对数据库进行业务操作。

所以,数据集监听类最常用的API主要是获取系统数据库连接、获取报表参数、获取session信息等

代码示例

package ......;  //指定类路径

import com.raqsoft.report.usermodel.*;

import ...... ;  //其他需要引入的类包

public class MyDatasetListener implements IDataSetFactoryListener{  //实现IDataSetFactoryListener接口

public void beforeCreated( Context ctx, DataSetConfig dsc, DataSet ds ){ //数据集产生之前执行的方法

//获得系统默认数据源的连接对象

Connection con=ctx.getConnectionFactory(context.getDefDataSourceName()).getConnection();

 

//String dataSource=……;  //指定数据源名称

//Connection con=ctx.getConnectionFactory(dataSource).getConnection();  //获得指定数据源的连接对象

Map params=ctx.getParamMap(false);  //获得当前报表的参数

javax.servlet.http.HttpSession session=ctx.getHttpSession();  //获得session,从而可以得到用户信息

//........  //主体代码,例如整理数据库等

}

public void afterCreated( Context ctx, DataSetConfig dsc, DataSet ds ){ //数据集产生之后执行的方法

}

}

数据集工厂过滤器类

背景说明

数据集工厂过滤器类是在计算数据集时,如果设定了过滤类,则在生成数据集的每一条记录时都会做判断。

因此,总体来说,数据集工厂过滤器类主要用于在数据集计算过程中对记录进行业务操作。

代码示例

package api;  //指定类路径

import java.sql.Connection;

import ……    //其他需要引入的类包

 

public class datasetFiltertest implements IDataSetFilter{    //实现IDataSetFilter接口

//数据库返回ResultSet之后对每条记录进行过滤,该行数据满足条件返回true,否则返回false

public boolean filter(Object[] arg0) {

StringBuffer sb = new StringBuffer();

//主体代码,循环获取当前记录

for(int i=0;i<arg0.length;i++){

……

}

int id = Integer.parseInt(arg0[0].toString());

if(id>10800){

return true;

}else{

return false;

}

}

public void setContext(Context arg0) {    //设定上下文环境

}

public void setDataSet(DataSet arg0) {    //设定数据集,以在过滤时获取相关信息

}

public void setDataSetConfig(DataSetConfig arg0) {    //设定数据集配置信息

}

}

参考文件:datasetFiltertest.java

自定义菜单

背景说明与实现思路

润乾报表设计器提供的菜单项可以由用户自定义,用户可以追加一些菜单项,也可以替换一些现有的菜单项。目前可以追加菜单项的有文件菜单、编辑菜单、报表菜单、填报菜单、工具菜单、帮助菜单或重定向系统菜单。

 

菜单的定制包括两个步骤:1、写程序实现菜单的功能2、增加菜单按钮

 

自定义菜单类必须继承com.raqsoft.report.ide.configmenu.CMAction,实现其public void actionPerformed(ActionEvent e)方法,该类有两个保护变量:

protected String argument;

protected ICMHandler handler;

argument  即在配置菜单按钮时配置文件指定的argument字符串

handler  ICMHandler,这是一个润乾报表提供的消息处理类,程序员可以通过这个接口发送消息以获取到自己想得到的一些东西。

 

◆ com.raqsoft.report.ide.configmenu.ICMHandler

public Object processMessage(String desc, Object argument);  //此方法供程序员发送消息并接收返回值

desc  消息的简短描述,大小写无关

argument 传给润乾报表

返回值 润乾报表执行消息后返回给程序员的想要得到的东西

 

另外:润乾报表设计器中com.raqsoft.report.ide.GVIde是一静态类,里面包含了润乾报表设计器IDE的界面组成构件,用户可以直接访问该类的属性以获取自己感兴趣的IDE构件。

可以访问的构件说明:

1.  appMenu :设计器的主菜单对象。类型(JMenu

2.  dsActive :当前活动的数据源定义,类型(com.raqsoft.report.ide.base.DataSource

3.  dsModel :数据源列表定义,类型(com.raqsoft.report.ide.base.DataSourceListModel

4.  toolBarProperty :设计器第一个工具条,可设置颜色的那条。类型(com.raqsoft.report.ide.ToolBarProperty

5.  toolBarEditor 设计其第二个工具条,可设置表达式的那条,类型(com.raqsoft.report.ide.ToolBarEditor

 

自定义菜单类

代码示例

package one.client;

 

import javax.swing.*;

import java.net.*;

import java.io.*;

import java.awt.event.ActionEvent;

import java.util.*;

 

import com.raqsoft.report.ide.configmenu.CMAction;

 

public class OneRpx extends CMAction {

  public void actionPerformed( ActionEvent e ) {

public void actionPerformed( ActionEvent e ) {

…………

}

}

参考文件:MyMenu.java

 

自定义菜单按钮的配置

菜单按钮的配置在reportsystemconfig_zh.xml文件中,该文件所处位置应为类路径可以搜索到的位置。

 

文件结构:

<REPORT>

<CONFIG_MENU>

<F_20000 argument="" classname="one.client.MyMenu" hotkey="ctrl+h" text="打开报表" object="report" />

</CONFIG_MENU>

<CONFIG splashFile="config/runqiansplash.jpg">

</CONFIG>

</REPORT>

 

F_10为菜单项的数字标识号,

F_ 前缀表示菜单将添加到润乾报表的文件菜单中;

E_ 前缀表示菜单将添加到润乾报表的编辑菜单中;

R_ 前缀表示菜单将添加到润乾报表的报表菜单中;

I_ 前缀表示菜单将添加到润乾报表的填报菜单中;

T_ 前缀表示菜单将添加到润乾报表的工具菜单中;

C_ 前缀表示菜单将添加到润乾报表的远程菜单中;

H_ 前缀表示菜单将添加到润乾报表的帮助菜单中。

 

后面跟的序号原则上大于 20000。但是如果小于20000而和系统的其他命令冲突则会造成程序菜单混乱。但是和以下的系统菜单序号相同时,则程序不追加新的配置菜单项,而会把如下列出的系统菜单的行为重定向到配置菜单指定的操作。

 

可替换的系统菜单命令列表:

报表菜单

文件菜单

编辑菜单

报表菜单

新建

5

撤销

205

参数

505

新建报表向导

6

重复

210

510

新建报表组

7

剪切

215

数据集

515

新建填报

9

复制

220

报表组设置

520

新建行式填报

2005

粘贴

225

报表属性

350

打开

10

插入

 

行属性

305

打开填报

11

插入行

405

列属性

310

快速打开

15

插入列

410

边框设置

325

关闭

30

追加数据行

415

统计图

335

关闭全部

35

追加数据列

420

条形图

345

保存

20

插入格

441

第三方图形

346

另存为

25

追加格

443

表达式

348

打印

50

局部报表

430

子报表

340

预览

55

行区域

455

数据类型

330

导出

 

列区域

456

图片

331

excel文件

101

删除

 

数据图层

333

分页excel文件

102

删除行

261

编辑风格

365

带公式excel

103

删除列

263

设置密码

366

word文件

106

删除前格

265

 

 

pdf文件

104

清除

 

工具菜单

分页pdf文件

105

设为空白格

230

添加到样式

610

文本式pdf文件

111

设为初始格

235

添加为预定义格

611

文本式分页pdf文件

112

清除格式

240

配色方案

618

Text文件

108

清除内容

245

JSP编辑器

615

Html文件

110

清除编辑风格

246

脚本编辑

616

Xml文件

109

清除数据图层

247

导入Excel

612

excel文件

121

移动

 

上载文件

622

分页excel文件

122

上移行

461

报表迁移

620

带公式excel

123

下移行

463

数据源

605

最近文件

97

左移列

465

多维数据库

650

最近连接

98

右移列

467

选项

625

退出

60

上移单元格

471

 

 

 

 

下移单元格

473

远程菜单

帮助菜单

左移单元格

475

登录

801

关于

1005

右移单元格

477

注销

802

技术支持

1015

搜索

250

连接数据源

811

清理内存

1010

替换

255

上传文件

812

 

 

 

 

打开文件

810

 

填报菜单

文件菜单

编辑菜单

填报菜单

新建

5

撤销

2115

参数

2301

新建报表向导

6

重复

2117

格间校验

2305

新建报表组

7

剪切

2121

页属性

2315

新建填报

9

复制

2123

行属性

2325

新建行式填报

2005

粘贴

2125

列属性

2331

打开

10

插入

 

边框设置

2335

打开填报

11

插入行

2101

单元格校验

2321

快速打开

15

插入列

2102

编辑风格

2323

关闭

2030

追加数据行

2104

数据图层

2333

关闭全部

2035

追加数据列

2105

数据处理

2311

保存

2020

插入表格

2111

上载文件

2313

另存为

2025

追加表格

2113

数据源

605

最近文件

97

删除

 

选项

2341

最近连接

98

删除行

2107

 

 

退出

60

删除列

2108

远程菜单

 

 

删除表格

2139

登录

2801

帮助菜单

清除

 

注销

2802

关于

1005

设为初始格

2131

连接数据源

2811

技术支持

1015

清除格式

2133

上传文件

2812

清理内存

1010

清除内容

2135

打开文件

2810

 

 

清除填报属性

2137

 

 

 

 

移动

 

 

 

 

 

上移行

2141

 

 

 

 

下移行

2143

 

 

 

 

左移列

2145

 

 

 

 

右移列

2147

 

 

 

 

左移表格

2151

 

 

 

 

右移表格

2153

 

 

 

Argument 为任意意义的字符串参数,用户在自定义的类里面可以使用该参数,当然也可以不用。

Classname 增加的菜单项需要执行的类名, 且该类必须实现com.raqsoft.report.ide.configmenu.CMAction抽象类。

Text  菜单显示的中文名称

Hotkey 为菜单项指定热键,只能为某个字母,或者 ctrl+字母  两种格式。

Object  增加的菜单项显示在报表菜单还是填报菜单,有reportinputall三个取值。

report时表示只在报表菜单上增加

input时表示只在填报菜单上增加

object不填或all时表示是公用的,报表和填报都增加

 

CONFIG 系统的配置选项:

Splahfile IDE启动时的splash 画面文件。该文件为类路径上搜索的相对路径。

不指定该选项则不启动splash窗口。

 

自定义设计器右下角数据集面板

背景说明:

润乾报表设计器提供的数据集面板可以由用户重新自定义,用户可以根据自己的需求自定义数据集面板。

自定义数据集面板需要实现润乾报表提供的com.raqsoft.report.ide.custom.IPanelDataSet接口,请看如下示例:

代码示例

package ......;  //指定类路径

import com.raqsoft.report.ide.custom.IPanelDataSet;

import ......; 

public class CustomPanelDataSetDemo extends JPanel implements IPanelDataSet {  //实现IPanelDataSet接口,自动引入以下两个方法

public Component getComponent() {   //返回面板控件

… …

return this;

}

public void refresh(Map<String, Vector<String>> dsColsMap) {  //用于刷新数据集面板的方法,以下方法体内容仅为示例,用户自己掌握

… …

System.err.println("my custom dataset panel!");  

for (Map.Entry<String, Vector<String>> entry : dsColsMap.entrySet()) {  //遍历报表内部获取并传入的键值形式的数据集

System.err.println(entry.getKey()+":"+entry.getValue());

}

… …

}

}

参考文件:CustomPanelDataSet.java

自定义设计器数据集编辑器

背景说明:

润乾报表设计器提供的自定义数据集编辑器可以由用户重新自定义,用户可以根据自己的需求自定义数据集编辑器。

自定义数据集编辑器需要实现润乾报表提供的com.raqsoft.report.ide.custom.ICustomDataSetEditor接口,请看如下示例:

代码示例

package ......;  //指定类路径

import com.raqsoft.report.ide.custom.ICustomDataSetEditor;

import com.raqsoft.report.usermodel.CustomDataSetConfig;

import com.raqsoft.report.usermodel.DataSetConfig;

import ......; 

public class MyCustomDataSetEditor extends JDialog implements ICustomDataSetEditor {  //实现ICustomDataSetEditor接口,自动引入以下三个方法

 

public void setDataSetConfig(DataSetConfig dsConfig) {  //设置要编辑的自定义数据集配置,必须是CustomDataSetConfig类型

… …

}

public DataSetConfig getDataSetConfig() {    //获取编辑完成的自定义数据集配置,必须是CustomDataSetConfig类型

  … …

}

… …

public int getOption() { //编辑窗口的操作选项;

// return int,取值为JOptionPane.OK_OPTION,JOptionPane.CANCEL_OPTION,当返回值为JOptionPane.OK_OPTION,表示用户确认当前编辑,否则就是取消编辑

return … …;

}

… …

}

参考文件:MyCustomDataSetEditor.java

自定义远程服务

背景说明:

很多时候用户不仅需要操作本地的报表模板,还要操作远程服务器上的报表模板,比如修改远程服务器的报表或者将本地模板上传至远程服务器等。为了满足这种需求,润乾报表提供了远程服务接口。可在设计器中通过用户权限控制远程服务,用户可以根据自己的需求自定义远程服务接口,实现登陆、注销、打开文件、连接数据源、上传文件等操作。

自定义远程服务需要实现润乾报表提供的com.scudata.ide.custom.Server接口,请看如下示例:

代码示例

 

package api; //指定类路径

import com.scudata.ide.custom.Server;

import ......;

public class CustomServer implements Server{ //实现Server接口,自动引入接口中的所有方法

… …

public boolean login(String user, String pwd) {

… …

//通过httpclient等工具,根据user参数请求业务系统中提供的servlet,获取到对应用户密码PWD

if (PWD == null)

if (pwd != null)

return false;

if(PWD.equals(pwd) || PWD2.equals(pwd)){

loginState = LOGIN;

return true;

}

return false;

}

public InputStream open(String fileName) {

…… //通过httpclient等类似工具,向web服务器发起报表文件流请求,读取web服务器上的报表文件,这里需要告诉用户所请求应用读取报表的url,如果没有登陆就调用 这个方法,需要弹出对话框提示用户没有登陆。下面这行代码没用,去掉

File remoteFile = new File(url, fileName);

return new FileObject(remoteFile.getAbsolutePath()).getInputStream();

}

 

/**

* 保存文件到服务器

*

* @param fileName

*  服务端文件名

* @param fileBytes

*  文件转成的字节数组

*/

public void save(String fileName, byte[] fileBytes) {

……//这个方法是保存当前打开的报表的字节流到远程web端。字节流通过httpclient等工具发送到web端的servlet

… …

JOptionPane.showConfirmDialog(null, "保存文件:"+fileName+"至服务器"+getName()+"成功!");

}

 

/**

* 上传本地文件到服务器

*

* @param fileName

*  服务端文件名

* @param localFile

*  本地文件

*/

public void save(String fileName, File localFile) {

… …

}

 

/**

* 返回指定目录下的文件信息

*

* @param path

*  path=null/时表示根

* @return 指定目录下文件信息

*/

public List<FileInfo> listFiles(String path) {

… …

File remoteFile;

if (path == null) {

remoteFile = new File(url);

} else {

remoteFile = new File(url, path);

}

if (remoteFile.isDirectory()) {

File[] files = remoteFile.listFiles();

if (files != null && files.length > 0) {

List<FileInfo> fileInfos = new ArrayList<FileInfo>();

… …

return fileInfos;

}

}

return null;

}

 

/**

* 取当前用户可用的数据源配置

*

* @return 数据源列表(用户有权限访问的)

*/

public List<DBConfig> getDBConfigList() {

//数据源信息需要自行处理成DBConfig

… …

dbcs.add(dbconfig);

return dbcs;

}

 

/**

* 注销

*/

public void logout() {

loginState = LOGOUT;

System.out.println("注销");

}

… …

}

参考文件:CustomServer.java

自定义加密实现类

背景说明:

数据源密码加密级别为密码加密时,用户可使用自己的加密解密方式对数据源密码进行加密和解密。

自定义加密实现类需要实现润乾报表提供的com.scudata.common.IPwd接口,请看如下示例:

 

代码示例

package ......;  //指定类路径

import com.scudata.common.IPwd;

import java.util.Date;

public class CustomPwd implements IPwd {

/**

* 加密

* @param pwd 密码

* @return 加密后的密码

*/

public String encrypt(String pwd){

if (pwd == null) {

return null;

}

String p0 = "ABC";

System.out.println("密码加密:加上ABC" + "-------" + new Date());

return pwd + p0;

}

 

/**

* 解密

* @param pwd 加密的密码

* @return 原密码(解密后)

*/

public String decrypt(String pwd){

if (pwd == null) {

return null;

}

System.out.println("密码解密:去掉ABC"+ "-------" + new Date());   

return pwd.substring(0, pwd.length() - 3);

}

}