解决 Birt 等报表工具制作报表的几个难题
解决Birt等报表工具制作报表的几个难题
在上一篇《Birt 如何实现不规则月份统计》中,我们讲解了如何帮助 Birt 制作这种报表的详细过程,在本文中我们再继续讨论几个类似的制作难题,并把说明集中在如何编写集算器 SPL 脚本上,不再赘述如何在 Birt 中引入 SPL 的步骤了。
1. 组内跨行计算
组内跨行计算是指在计算一行中某个计算列的值时,需要引用到组内其它行的数据来进行计算。比如下面这个例子:
库表 sample 有三个字段,其中 id 是分组字段。需要设计一张分组表,使用 id 分组,明细字段是 v1,v2 以及计算列 crossline, 其中 crossline 的算法是本条记录 v1、v2 之和加上本组上一条记录的 v1、v2 之和。示例源数据如下:
id | v1 | v2 |
1 | 1 | 2 |
1 | 2 | 3 |
2 | 1 | 1 |
2 | 2 | 2 |
3 | 3 | 3 |
最后要展现的报表结果如下图所示:
编写集算器 SPL 代码如下:
A | |
1 | =connect("demo") |
2 | =A1.query("select *, 0 as crossline from sample") |
3 | >A2.group(id).run(~.run(v1+v2+v1[-1]+v2[-1]:crossline)) |
4 | >A1.close() |
5 | return A2 |
A1 连接数据库
A2 查询数据库,同时多产生一列常数备用。
A3 按 id 分组,并在每组数据中修改计算列 crossline,最后合并,其中 v1[-1]、v2[-1] 是集算器特有的定位上一行记录中字段的写法。
A4 关闭数据库
A5 将 A2 中的计算结果数据集返回给报表工具
2. 跨库数据源
制作报表的数据往往来自于多种数据源,比如不同的物理数据库、文本文件、Excel 文件等,这些数据在报表中往往还需要相互关联进行运算。
报表工具本身能实现从多数据源取数,但进行关联运算会有一定的困难,或者运算性能非常差。而由开发者自己编程去做关联运算,工作量一般又会非常大。而集算器 SPL 恰恰能在这一点帮上大忙。
下面这个例子中,订单表 orders 和订单明细表 orderDetail 数据分别来自两个不同的数据库,二者之间要做 join 运算。两表数据如下:
最后想要展现的报表结果如下:
编写集算器 SPL 代码如下:
A | |
1 | =connect("db1") |
2 | =connect("db2") |
3 | =A1.query("select orderID,customer,orderDate from orders") |
4 | =A2.query("select orderID,productID,price,mount from orderDetail order by orderID") |
5 | >A1.close() |
6 | >A2.close() |
7 | =join@1(A3:orderID,A4:orderID) |
8 | =A7.new(#1.orderID,#1.customer,#1.orderDate,#2.productID,#2.price,#2.mount) |
9 | return A8 |
A1 连接数据库 1
A2 连接数据库 2
A3 查询订单表数据
A4 查询订单明细表数据
A5A6 关闭数据库连接
A7 以 A3 的 orderID 和 A4 的 orderID 为主键进行 left join,连接后的结果集有两个字段,第一个字段是 A3 的记录,第二个字段是 A4 的记录。
A8 以 A7 中两个字段的字段形成新的数据集,也就是需要的结果
A9 将 A8 的数据集返回给报表工具
本例只是演示了两个数据源的 left join,其实 SPL 能做关系数据库能完成的任何数据运算,比如各种 join、union、过滤、分组、排序等。
3. 字段拆分成记录
在本例中,数据库表 data 有两个字段,其中 ANOMOALIES 字段是用空格分隔的多个字符串,我们需要把 ANOMOALIES 按空格拆分为多个字符串,并用每个字符串和原 ID 字段形成新的记录。源数据如下:
ID | ANOMALIES |
3903 | B1 D1 CAT1 |
3904 | D7 D2 B1 CAD4 |
最后想要展现的报表结果如下:
编写集算器 SPL 代码如下:
A | |
1 | =connect("db") |
2 | =A1.query("select ID,ANOMALIES from data") |
3 | =A2.conj(ANOMALIES.array(" ").new(A2.ID:ID,~:ANOMALIES)) |
4 | >A1.close() |
5 | return A3 |
A1 连接数据库 1
A2 查询 data 表数据
A3 将ANOMALIES字段值按空格拆分,并与原ID形成新的记录
A4 关闭数据库连接
A5 将 A3 形成的数据集返回给报表工具
4. 主表中动态插入子表字段
在本例中,数据库表 dColThread 是主表,主键是 tID。dColQuestion 是子表,外键是 tID,如下:
dColThread
tID | ApplicationName | User | Phone | Decline |
A01 | mfc | Bill | +70000000 | 1 |
A02 | mfc | John | +18761221 | 2 |
A03 | java | Jack | +8014001231 | 6 |
A04 | mfc | Tim | +008613133123 | 4 |
A05 | db | John | +18761221 | 8 |
dColQuestion
qID | tID | status |
1 | A01 | yes |
2 | A01 | no |
3 | A01 | yes |
4 | A02 | yes |
5 | A03 | no |
6 | A04 | no |
7 | A04 | no |
8 | A05 | yes |
报表需要根据 ApplicationName 查询主表并以列表的形式展现数据。可以看到,在子表中,主表每条记录对应的 status 字段值有多个,但不超过 5 个。我们需要把子表中的这些记录横向排列后插入主表的 Phone、Decline 字段之间,依次命名为 QuestionNo1、QuestionNo2…QuestionNo5。同时,如果某列数据都为空,则这一列不显示。最后的表样形如下图:
用集算器准备数据,SPL 代码如下:
A | B | |
1 | =connect("db") | |
2 | =A1. query("select * from dColThread t,dColQuestion q where t.tID=q.tID and t.ApplicationName=?",arg1) | |
3 | >A1.close() | |
4 | =A2.group(tID) | |
5 | =create(ApplicationName,User,Phone,QuestionNo1,QuestionNo2,QuestionNo3,QuestionNo4,QuestionNo5,Decline) | |
6 | for A4 | =A6.(status)|["","","","",""] |
7 | = A5.record(A6.ApplicationName|A6.User|A6.Phone|B6.to(5)|A6.Decline) | |
8 | return A5 |
A1 连接数据库
A2 执行 SQL,取出主子表关联数据。arg1 是来自报表参数。假如 arg1= "mfc ",则 A1 的计算结果如下:
A4 按照 tID 分组,每组是一条主表记录及其对应的子表记录,如下图:
A5 按照报表中列表的结构新建空二维表。
A6 循环 A4 中的组,每次向 A5 插入一条记录。循环体中可用 A6 引用循环变量,用 #A6 来引用循环计数。
B6 取当前组中 status 的字段值,并补足至少 5 条记录。
B7 向 A5 追加新记录。循环结束后 A5 如下:
A8:返回结果给报表。
隐藏空列的工作交给 BIRT,设计 list 表,模板如下:
如果 QuestionNo 列为空则应当隐藏。动态隐藏的方法有很多,这里介绍其中一种。对于 QuestionNo5(其他列类似),可以先在 dataSet 的 onFetch 方法中使用如下脚本:
if(reportContext.getGlobalVariable("t5")==null){
reportContext.setGlobalVariable("t5",row.QuestionNo5)
}else{
reportContext.setGlobalVariable("t5",reportContext.getGlobalVariable("t5")+row.QuestionNo5)
}
再在 QustionNo5 列的 Visibility 属性中使用如下表达式:BirtStr.trim(reportContext.getGlobalVariable("t5"))==""
预览后可以看到报表结果:
5. 小结
通过以上例子可以看出,报表制作时经常遇到不好处理的数据准备工作,而在集算器的帮助下都可以得到完美的解决。这是因为集算器提供了完备的数据源连接功能,能连接市面上常见的各种数据源并从中取数。同时,SPL 还提供了丰富的函数库,能在库外轻松进行数据的各种关联运算。
解决 Birt 等报表工具制作报表的几个难题相关推荐
- 【ireport工具制作报表使用流程】
[ireport工具制作报表使用流程] 1.ireport使用说明 2.安装包及相关环境下载 3.快速入门上手 如何使用代码生成报表 1.ireport使用说明 ireport 是一款方便实用的报表编 ...
- java 报表_市占率第一的Java报表工具 - FineReport报表工具
作为国产Java报表工具的优秀代表,FineReport报表工具不仅仅在报表设计的简单易用上表现出极大的优势,更在数据分析等复杂报表处理能力和报表管理等报表综合应用上凸显出其报表技术的成熟和领先. 一 ...
- 电脑常识免费报表工具 积木报表(JiMuReport)的安装
电脑常识免费报表工具 积木报表(JiMuReport)的安装 根据IAB E"2021年欧洲广告报告",2021年下半年欧洲数字广告强劲复苏,全年增长6%,达到694亿欧元.刷赞平 ...
- Smartbi如何解决传统报表工具制作的问题
目前Excel仍是最常用的数据分析工具.在日常工作中,Excel因为其简单易用.强大便捷的功能(公式函数.透视表.图表等)以及积累沉淀的大量模板等优势广受欢迎. 对于经常使用Excel的用户,也会发现 ...
- 永洪报表工具_报表工具对比选型系列用例——排名及跨行组统计
继<多源分片报表>后,我们继续考察这些报表工具对复杂报表的支持程度. 排名与跨行组运算也是典型的中国复杂报表形式,这类报表的源数据集通常比较简单,但在表格的单元格之间会有较随意的计算要求. ...
- 一个老鸟的BI之路——转自他人的报表工具java报表软件以及bi的经验分享
闲来无事看到一篇帖子,颇有感触,特此转发一下! 原文链接:https://blog.csdn.net/qq_36128242/article/details/83746582 这人一上年纪就爱回忆之前 ...
- 使用这款0代码免费报表工具,报表开发可以告别996了
随着时代的快速发展,人类进入到了大数据时代,电子同一数据,往往有多种可视化呈现方式.微金时代RDP报表工具,仅在可视化效果上就有数百种选择,令传统报表工具望尘莫及,使用人员零编码,只需要通过拖拽方式即 ...
- 好用的报表工具推荐(报表工具功能)
在这个大数据时代,大数据计算机已成为数据分析人员必备的工具,熟悉数据分析,并从数据快速抽取出经营问题,快速响应市场,才能让数据成为第一生产力. 选择一款合适的报表工具,对数据分析人员来说是非常重要,如 ...
- 使用FastReport报表工具生成报表PDF文档
在我们开发某个系统的时候,客户总会提出一些特定的报表需求,固定的报表格式符合他们的业务处理需要,也贴合他们的工作场景,因此我们尽可能做出符合他们实际需要的报表,这样我们的系统会得到更好的认同感.本篇随 ...
最新文章
- 服务器维护简单的备份方案,服务器备份方案计划.doc
- 【c++】30.为什么可以通过指针或引用实现多态,而不可以通过对象呢?
- C++基础与深度解析第八章:动态内存管理
- mysql5.7 no password_MySQL5.7.20报错Access denied for user 'root'@'localhost' (using password: NO)
- [转载] Java继承概念和关键字
- LINUX下用select实现串口通讯示例
- C语言测量平差课程设计,测量平差课程设计-20210419024415.docx-原创力文档
- 反欺诈模型常用开发工具
- AutoRunner 功能自动化测试项目实训之第二个实战案例(五)
- python实现oa系统_利用Python实现某OA系统的自动定位功能
- 虚拟机dns服务器不可以,windows虚拟机中DNS服务配置
- 常见光纤接头LC、FC、SC、ST
- 【转】C++后台开发应该读的书
- ThreeJs中给立方体设置没有对角线的border
- java面试题大合集(开发者必看)
- 关于我本人阳了个阳一事
- Android调用系统原生分享组件
- C# 在子窗体中调用父窗体的方法
- 利用Snippet快捷键在TeXpad上快速初始化中文环境的LaTeX模板
- 常用的数据可视化工具