集算报表继承了润乾报表的宏机制来处理动态报表,对于简单的动态报表使用宏实现非常方便。对于一些复杂的动态报表,集算报表还提供了脚本数据集来处理动态报表,适合宏无法实现的场景,而润乾报表中要实现复杂动态报表时则需要编写自定义数据集来完成。下面通过几个例子来详细比较一下集算报表和润乾报表在处理动态报表时的相同与不同点。
相同点
集算报表和润乾报表都提供了宏,使用方式几乎完全一致,且都包含普通宏和动态宏。
普通宏常用于静态内容替换,如在员工表中同时只希望查看薪金或奖金,开发两张报表显然是繁冗的,使用普通宏在一张报表来完成很简单,如下报表:
预览报表输入参数和宏:
当参数arg1值为BONUS,宏macro值为BONUS时,可得到如下报表结果:
当参数arg1值为SALARY,宏macro值为SALARY时,可得到如下报表结果:
相对普通宏只能替换静态内容,动态宏则可以编写动态表达式,完成动态内容的替换,从而完成动态报表制作。比如这样的动态报表,针对指定表根据用户选择的字段和条件进行查询,报表中显示选择的字段及其数据。由于字段和条件都是动态的,所以需要先在报表中将SQL拼好再交由数据库进行查询,这时就需要在动态宏中进行拼接。如下报表:
其中报表参数和宏设置为:
输入cols值:订单ID,客户ID,订购日期,发货日期,到货日期,运货费
输入where值:where 货主地区=‘华北‘ and 货主城市 in (‘北京‘,‘天津‘,‘张家口‘,‘秦皇岛‘)
其值为:"select"+cols+" from 订单"+where,宏类型为动态宏。
设置数据集SQL为:${sql},预览报表可以得到如下动态报表结果:
以上为使用宏(普通宏和动态宏)开发相对简单(只静态内容或通过简单的表达式完成)的动态报表,而对于复杂的动态报表,往往需要经过复杂计算才能完成,而这类复杂情况使用宏往往很难甚至无法完成,这时集算报表和润乾报表处理的方式则有很大不同。
不同点
集算报表提供了脚本数据集的方式可以完成上述提到的复杂动态报表的开发,由于脚本内置且语法简单,很容易处理这类报表。而润乾报表只能通过自定义数据源在JAVA中完成,使用的简易性则略逊一筹。下面还是通过例子来看一下。
由用户针对特定表指定选择列和条件,如用户在订单表中选择列时,订单ID、雇员ID和订购日期是必选列,即使用户没有选择,在查询后仍然显示。这就需要在拼接SQL的时候事先判断必选列是否在用户的选出列中,如果不在,则在后面添加,同时要保证用户选出列的次序。
通过宏实现的难点在于,由于需要判断每个必选列是否在用户选择字段的列表中,如果没有则附加,有多少个必选列就要比较几次,在必选列较多的时候非常复杂。
下面是集算报表通过脚本数据集的实现(报表参数与表达式与上例一致):
上述脚本在A2中将所选字段集合与必选字段集合做并集即获得了所有查询字段,拼接SQL进行查询后为报表返回结果集,过程很简单。
而润乾报表在这种情况一般要采用自定义数据集了,下面是润乾报表通过自定义数据集的实现(主要代码):
<span style="font-size:14px;">public class QueryData implements IDataSetFactory { public DataSet createDataSet(Context ctx, DataSetConfig dsc, boolean isinput) { Map map = ctx.getParamMap(false); // 获得当前报表的所有参数对照表 String cols = ""; String where = ""; if (map != null) { Iterator it = map.entrySet().iterator(); cols = map.get("cols").toString(); // 获取参数值 where = map.get("where").toString(); // 获取参数值 } DataSet ds1 = new DataSet("ds1"); Connection con = null; try { con = ctx.getConnectionFactory("demo").getConnection(); Statement stmt = con.createStatement(); String sql = "select " + cols + " from 订单 " + where; ResultSet rs = stmt.executeQuery(sql); ResultSetMetaData rsmd = rs.getMetaData(); int colCount = rsmd.getColumnCount(); //设置列名 for (int i = 1; i <= colCount; i++) { ds1.addCol(rsmd.getColumnName(i)); } //设置数据集数据 if (rs != null) { while (rs.next()) { Row rr = ds1.addRow(); for (int i = 1; i <= colCount; i++) { rr.setData(i, rs.getObject(i)); } } } rs.close(); stmt.close(); con.close(); } catch (Exception ex) { ex.printStackTrace(); } return ds1; } } </span>
上述自定义数据集首先获取了报表参数和当前数据源连接,其次根据参数拼接出要执行SQL,而后根据获得的ResultSet为数据集分别设置列名和数据,最后返回创建的数据集。在使用时,将编译后的class(QueryData.class)放到应用的classpath中方才完成。
通过以上实现过程可以看到,对于复杂的动态报表(如上例),使用脚本数据集实现更为简单,除了其拥有简洁的语法,脚本数据集内置在报表中无需其他程序文件附加,则更为便捷。