# 15 | 前端技术应用(二):如何设计一个报表工具?
众所周知,很多软件都需要面向开发者甚至最终用户提供自定义功能,在[开篇词](https://time.geekbang.org/column/article/118016)里,我提到自己曾经做过工作流软件和电子表单软件,它们都需要提供自定义功能,报表软件也是其中的典型代表。
在每个应用系统中,我们对数据的处理大致会分成两类:一类是在线交易,叫做OLTP,比如在网上下订单;一类是在线分析,叫做OLAP,它是对应用中积累的数据进行进一步分析利用。而报表工具就是最简单,但也是最常用的数据分析和利用的工具。
本节课,我们就来分析一下,如果我们要做一个通用的报表工具,需要用到哪些编译技术,又该怎样去实现。
## 报表工具所需要的编译技术
如果要做一个报表软件,我们要想清楚软件面对的用户是谁。有一类报表工具面向的用户是程序员,那么这种软件可以暴露更多技术细节。比如,如果报表要从数据库获取数据,你可以写一个SQL语句作为数据源。
还有一类软件是给业务级的用户使用的,很多BI软件包都是这种类型。带有IT背景的顾问给用户做一些基础配置,然后用户就可以用这个软件包了。Excel可以看做是这种报表工具,IT人员建立Excel与数据库之间的连接,剩下的就是业务人员自己去操作了。
这些业务人员可以采用一个图形化的界面设计报表,对数据进行加工处理。我们来看看几个场景。
**第一个场景是计算字段。**计算字段的意思是,原始数据里没有这个数据,我们需要基于原始数据,通过一个自定义的公式来把它计算出来。比如在某个CRM系统中保存着销售数据,我们有每个部门的总销售额,也有每个部门的人数,要想在报表中展示每个部门的人均销售额,这个时候就可以用到计算公式功能,计算公式如下:
```
人均销售额=部门销售额/部门人数
```
得到的结果如下图所示:
![](https://static001.geekbang.org/resource/image/f6/b8/f6abaebc36fc515e8cf1dd7ec3b5cdb8.jpg)
**进一步,我们可以在计算字段中支持函数。**比如我们可以把各个部门按照人均销售额排名次。这可以用一个函数来计算:
```
=rank(人均销售额)
```
rank就是排名次的意思,其他统计函数还包括:
* min(),求最小值。
* max(),求最大值。
* avg(),求平均值。
* sum(),求和。
还有一些更有意思的函数,比如:
* runningsum(),累计汇总值。
* runningavg(),累计平均值。
这些有意思的函数是什么意思呢?因为很多明细性的报表,都是逐行显示的,累计汇总值和累计平均值,就是累计到当前行的计算结果。当然了,我们还可以支持更多的函数,比如当前日期、当前页数等等。更有意思的是,上述字段也好、函数也好,都可以用来组合成计算字段的公式,比如:
```
=部门销售额/sum(部门销售额) //本部门的销售额在全部销售额的占比
=max(部门销售额)-部门销售额 //本部门的销售额与最高部门的差距
=max(部门销售额/部门人数)-部门销售额/部门人数 //本部门人均销售额与最高的那个部门的差
=sum(部门销售额)/sum(人数)-部门销售额/部门人数 //本部门的人均销售额与全公司人均销售额的差
```
怎么样,是不是越来越有意思了呢?现在你已经知道了在报表中会用到普通字段和各种各样的计算公式,那么,我们如何用这样的字段和公式来定义一张报表呢?
## 如何设计报表
假设我们的报表是一行一行地展现数据,也就是最简单的那种。那我们将报表的定义做成一个XML文件,可能是下面这样的,它定义了表格中每一列的标题和所采用字段或公式:
```