自定义数据集

自定义数据集介绍

背景说明:

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

自定义数据集常用到的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