润乾报表实现多数据源混合计算

报表数据经常来自于多个数据源,如不同的数据库、文件、分布式文件系统等。传统报表工具往往要借助第三方程序(如 JAVA 自定义数据源)完成多数据源的访问,过程复杂、代码难写,而且会导致应用系统与报表系统耦合度过高,从而增加后期维护难度。而润乾报表除了支持自定义数据源外,还可以用脚本数据集直接进行多数据源的混合计算。下面通过实际例子分别来看一下这两种方法。

这里以查询某发货时间段内所有订单的客户信息为例,业务系统中,订单信息存储于 JSON 格式的文件,报表查询时需要读取 JSON 格式文件,并与数据库表(维表)进行联合查询。

orders.json 部分内容如下:

{

"orders":[

    {

        "订单ID": "10248",

        "订单编号": [

            {

                "订单ID": "10248",

                "产品ID": "5",

                "单价": 12,

                "折扣": 0,

                "数量": 1

            }

        ],

        "客户ID": "VINET",

        "发货日期": "2000-07-16",

        "到货日期": "1996-08-01",

        "运货费": 32.38

    },

……

    {

        "订单ID": "10400",

        "客户ID": "EASTC",

        "发货日期": "1997-01-16",

        "到货日期": "1997-01-29",

        "运货费": 83.93

    }

]

}

目标报表格式要求:

imagepng

其中,左半部分来源订单 JSON 文件;右半部分来源数据库客户表;二者通过客户编号关联。

自定义数据集实现

1、连接数据源

在报表设计器中连接数据源

imagepng

2、设置报表参数

新建报表,并设置报表参数(发货起止日期)

imagepng

3、设置报表数据集

imagepng

其中 ds1 为自定义数据集,用于解析 JSON 文件:

imagepng

ds2 为 SQL 数据集,读取数据库客户表信息:

SELECT * FROM 客户

JSONDataSet.java 内容如下

public class JSONDataSet implements IDataSetFactory {
 
public DataSet createDataSet(Context ctx, DataSetConfig dsc,
boolean retrieve) {
// 取得参数列表并分别取得它的参数名与值,宏与之类似
Map map = ctx.getParamMap(false);
String begin = null;
String end = null;
if (map != null) {
begin = map.get("begin").toString();
end = map.get("end").toString();
}
 
DataSet ds1 = new DataSet("ds1");
String[] filds = { "订单ID", "发货日期", "客户ID" };
for (int i = 0; i < filds.length; i++) {
ds1.addCol(filds[i]);// 设置数据集的字段
}
String JsonContext = new JSONDataSet().ReadFile("D:\\orders.json");
try {
JSONObject jo = new JSONObject(JsonContext);
JSONArray ja = jo.getJSONArray("orders");
 
for (int i = 0; i < ja.length(); i++) {
String tdate = ja.getJSONObject(i).getString("发货日期");
if (tdate.compareTo(begin) >= 0 && end.compareTo(tdate) >= 0) {
Row rr = ds1.addRow();
String id = ja.getJSONObject(i).getString("订单ID");
String cusid = ja.getJSONObject(i).getString("客户ID");
rr.setData(1, id);
rr.setData(2, tdate);
rr.setData(3, cusid);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ds1;
}
 
public String ReadFile(String Path) {
BufferedReader reader = null;
String laststr = "";
try {
FileInputStream fileInputStream = new FileInputStream(Path);
InputStreamReader inputStreamReader = new InputStreamReader(
fileInputStream, "GBK");
reader = new BufferedReader(inputStreamReader);
String tempString = null;
while ((tempString = reader.readLine()) != null) {
laststr += tempString;
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return laststr;
}
}

注意,这里使用了 json_org.jar 解析 JSON 串,使用时需要引入。

4、编辑报表表达式

imagepng

这就是通过自定义数据集实现多数据源混合计算的过程。可以看到,润乾报表的自定义数据集接口提供了较大的灵活性,用户可以自由编写代码完成数据源准备。不过和传统报表工具借助第三方程序一样,编码较为复杂,因此自定义数据源的使用难度较大,本例中只解析 JSON 串并过滤,代码就已经很长,如果再完成关联运算将会更加复杂。

而润乾报表提供的脚本数据集(结合集算器实现)可以很好解决上述问题,下面来看实现过程。

脚本数据集实现

1、报表参数设置

如上

2、设置数据集

在数据集设置窗口选择“脚本数据集”,编写脚本同时读取 JSON 格式文件和数据库表完成关联查询,十分简单:

imagepng

脚本配置如下:

A
1 =file(“D:\\orders.json”).read().import@j().(orders)
2 =A1.select(发货日期 >=begin && 发货日期 <=end)
3 =demo.query(“select * from 客户”)
4 =A3.switch(客户 ID; 客户 ID:A3)
5 =A4.new(订单 ID, 发货日期, 客户 ID. 客户 ID: 客户编号, 客户 ID. 公司名称: 公司名称, 客户 ID. 联系人姓名: 姓名, 客户 ID. 电话: 电话, 客户 ID. 地址: 地址)
6 result A5

代码说明:

A1:通过指定选项 @j 通过 import 函数读取订单信息 JSON 格式文件

A2:根据发货日期范围过滤数据

A3:查询数据库客户表信息

A4:根据客户 ID 关联文件和数据表,完成混合计算

A5:根据关联结果新建结果集,并返回给报表

3、编辑报表表达式

根据脚本数据集返回的结果,编写如下报表表达式,完成报表制作

imagepng

可以看到,使用脚本数据集的方法除了代码简单易懂之外,还有个显著优点:关联运算在脚本中完成,执行效率更高。