cover_image

基于antlr的中国式报表的设计与实现

空山雪林 Sumslack团队
2022年01月22日 02:11

概述

上文介绍了打造您自己的开发语言,这篇我们利用自定义开发语言设计灵活报表。本系统基于ureport上二次开发,使用它可以完成任意复杂的中国式报表。类似Excel的方式以极简方式开发自定义报表,本文详细介绍了常见的几类报表,包含不限于复杂表头报表,查询报表,图表结合,数据钻取报表,分组小计合计报表,预警报表,套打等。

计算模型

单元格之间存在依赖关系,对于任意一个单元格都可以设置它的左父格上父格。单元格父格是可选的,默认情况下,单元格的左父格就是其最近左边与其位于同一行的单元格;上父格则是其最近上方与其位于同一列的的单元格。如果一个单元格位于第一行,那默认它就没有上父格,同样,如果位于第一列,默认它就没有左父格。

图片

任意单元格在绑定数据集中某个字段时,如果这个字段有一条以上的数据,那么单元格就可以展开以显示这些数据。对于父格而言,父格展开时会带动子格一起展开,如父格向下展开,则带其下所有子格及子格的子格一起向下展开;同时,如果子格中绑定的数据集与父格中数据集同属一个,则子格中的数据将受父格限制。子格绑定的数据集字段数据在展开时,同样也会带动其下子格一起展开,而当前子格的父格如与子格处于同一行或列,则会将父格拉大。

利用上述迭代单元格的特性,我们就可以制作出各种复杂的报表样式,掌握了这一报表计算模型的特点,是开发报表的前提。

表达式语法

采用antlr4自定义词法和语法

类型:数字,字符串和布尔型运算符:+,-,(如果是字符串,则表示重复次数),/,%(取余),like(包含),not like(不包含),in(在列表里),not in(不在列表里)逻辑运算符:&&(and),||(or),not(!)支持三元表达式:A1>1000 ? "正常值" : "低值"内置函数常用函数:count,sum,avg,max,min,row(取行号,从1开始),column(取列号,从1开始),order(对列表排序),list(列表函数),param(取外部参数值),emptyparam(判断参数是否为空),formatdate(日期格式化),formatnumber(数字格式化)分页函数:所谓分页相关函数,是指这些函数是在分页的时候进行计算,比如计算当前页有多少条记录、当前页某个单元格值累加后是多少、平均值是多少、最大值是多少等等,包括pcount,psum,pmax,pmin,page,pages数学函数:chn(数字转中文),rmb(数字转中文人民币),median(求中位数),mode(众数),vara(求方差),stdevp(求标准差)日期函数:day,month,year,week等字符串函数:indexof,length,lower,repalce,substring,json等

语法扩展

  • 支持在单元格返回true,false语法:listof("abc","b")>=1

  • 增加其他有用函数:如rangedateCalhttp

  • 修复了条件bug:支持增加like,not like条件:支持类似数据库的%,如ab%为开始匹配,如果输入ab则等价于%ab%

  • 按需扩展语法:为了增强报表表现力,增加条件表达式,扩展return语法等

  • 前端增加快捷键

常用报表开发

简单图表查询报表

数据预警:机构名带“银行”两次字体颜色标绿报表查询:可以按机构名模糊查询图形统计:加入一个饼图按省份统计机构个数数据钻取模拟:给机构名加上链接,如果带“银行”两字跳到baidu,其他跳到bing网站并传参(ID值非当前单元格的值)

图片

动态列报表

使用表达式定义一个静态列表list('北京','上海','浙江')或使用动态列表(采用select),选择数据展开向右即可。

图片

这时,底下展开的数据可以使用单元格坐标拿到表头数据,然后指定select拿到动态数据

分组报表

分组报表定义比较简单,定义需要分组的数据集,然后定义针对数据集的分组使用group函数即可,如下图:

定义分组

图片

定义数据

图片

最后效果

图片

小计与合计的设置比较简单,主要指定对应的左父或上父即可针对这批数据序列算sum,count等操作

交叉表

通过数据的不同展开方向来定义,在标题栏的列上使用向右展开数据,在第一列使用group向下展开数据,交叉点位置就可以使用group来获取上方数据和左边数据的交叉点来获取,如下图:

定义标题栏的动态列

图片

定义动态行

图片

定义交叉点的位置数据

图片

最后效果

图片

同比环比报表

如果需要定义同步环比报表,需要理解单元格引用单元格坐标,因为环比一般是针对上个月数据/本月数据,本单元格数据可以通过#或单元格坐标获取,但上个月数据只能通过针对当前单元格的引用来完成。以下是单元格引用语法:

A1(直接写类似Excel的单元格坐标即可),但要注意,被引用的单元格是否在同行或同列中,如果不在,则可能会产生多个值,用逗号隔开(找这个单元格和引用的单元格共同的左父对应下的多个值) 为了实现更复杂的单元格引用,我们可以使用单元格坐标,语法如下:单元格名称[Li:li,Li-1:li-1,…;Ti:ti,Ti-1:ti-1…]{条件...}

$单元格:在单元格名称前加$符号,表示取相对于目标单元格的单元格的值,比如:C2[A2:-1]{B2==$B2}表示,A2单元向上一格数据的C2单元格的值(可能多个,在分组中),同时,取当前单元格B2的值和定位后C2单元格对应的B2单元格的值

图片

&单元格:如&A2,指的是相对于当前单元格 A2 单元格展开后的序号,可以采用“&单元格名称”的方式标记某个单元格展开后的序号,需要注意的是,使用“&单元格名称”来标记目标单元格展开后的序号时,当前单元格必须是目标单元格的子格或间接子格#:表达式取当前单元格值,比如给单元格配置链接传递参数时,可以使用这个符号,#.属性名表示取当前行属性名对应的值
综上所述,我们对ureport的语法进行了加强,大大增强了报表的表现力,随着报表开发需求的多样性,未来还会加入更多功能,也会整合认证。有了它,开发业务报表大大降低。未来还会加入报表定期发送,预报指标预警等功能。

推荐阅读

脚本开发工具的设计与实现为SDP提供本地Python编程能力两种方式破解图片验证码利用binlog进行MySQL数据闪回NLP — 文本分类和BIO实体标注异地异构数据同步传输平台的设计与实现各种形状印章的去除


欢迎关注我的公众号“Sumslack”,原创技术文章第一时间推送。


图片




继续滑动看下一个
Sumslack团队
向上滑动看下一个