报表单据
随着信息化社会的发展,如今电子报表几乎已经成为各行各业的标配,与之相对的是,由于各行各业中对于报表的实际需求各不相同,且相同行业中大部分报表也缺乏统一标准等原因,并没有出现一个足够简单的、能够满足企业信息化过程中对于定制报表需求的解决方案。
dxsuite为您提供一个简单的、低成本的、经过实际项目验证的定制报表开发解决方案。
包括:
- 一份可满足绝大多数需求的简单报表设计原则,使您在设计报表时有迹可循、轻松自如。
- 一个基于Java优秀开源项目的技术组合方案,帮助您在技术选型阶段决胜千里之外。
- 一套简单的,可配置数据的报表模板与使用示例(可覆盖90%的简单需求)。
技术选型
在dxsuite的技术选型中,我们基于Java的技术栈,综合考察了DynamicReports、JasperReports等若干报表处理工具,并仔细评估了在生成报表时,到底要用纯Java代码的方式来生成报表还是采用先做报表模板,然后通过绑定数据的方式来生成报表。最终我们选定了后者,也就是先做报表模板,然后通过将数据绑定到模板的方式来生成报表。 这样做的理由如下:
- 表现层面上,报表的结构更加清晰,可以通过工具直接预览,更加直观、方便。
- 数据层面上,将数据和表示分离,开发更加简单,后台人员不必关注报表的格式细节,只需要关注报表所需要的数据即可。
- 代码实现层面上,避免了因报表嵌套等问题导致的代码过度抽象,降低了代码实现的复杂度。
项目 | 说明 |
---|---|
JasperReport | JasperReport是一个强大、灵活的报表生成工具,能够展示丰富的页面内容,并将之转换成PDF,HTML,或者XML格式。该库完全由Java写成,可以用于在各种Java应用程序,包括J2EE,Web应用程序中生成动态内容。 |
Jaspersoft Studio | Jaspersoft Studio 是一个基于Eclipse的报表设计工具。它可以让我们方便的制作基于JasperReport的报表模板文件。利用Jaspersoft Studio我们可以创建包含图表,图像,子报表等内容的复杂的报表布局。 |
开发手册
软件版本说明
项目工程开发及运行所需软件:
项目 | 版本 | 说明 |
---|---|---|
Java SE Development Kit | 1.8.221 | Java 开发工具包 |
Jaspersoft Studio | 6.10.0 | 基于 eclipse 的 JasperReport 报表开发工具 |
jasperreports | 6.4.0 | jasperreports 开发工具包 |
可选软件:
项目 | 版本 | 说明 |
---|---|---|
jasperreports-fonts | 6.1.1 | jasperreports 字体扩展包(使用微软雅黑字体时必须添加) |
安装 Java SE Development Kit (JDK)
从下载页面下载对应版本的安装文件,并按照提示安装(注意操作系统的匹配)。
安装 Jaspersoft Studio
从下载页面下载对应版本的安装文件,并按照提示安装(注意操作系统的匹配)。
添加 jasperreports 依赖
maven 工程
在 maven 工程中,我们可以通过在 pom.xml 文件中加入下面的配置内容来添加 jasperreports 的依赖。
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.4.0</version>
</dependency>
一般 java 工程
一般 java 工程的情况下,我们可以通过传统的引入 jar 包的方式来添加 jasperreports 的依赖。
- 从下载页面下载对应版本的 jasperreports 的 jar 包,并将其添加到工程的依赖中。
添加 jasperreports-fonts 依赖
maven 工程
首先,下载jasperreport-fonts-6.1的压缩包,解压得到 jasperreports-fonts-6.1.1.jar
。
然后,将其手动安装到本地 Maven 库(或上传到公司的 Nexus Repository Manager 私有 Maven 库中)。
具体参见:[常见的坑->
jasperreports-fonts
依赖组件的安装]
最后,在 maven 工程的 pom.xml
文件中加入下面的配置内容来添加 jasperreports-fonts 的依赖。
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-fonts</artifactId>
<version>6.1.1</version>
</dependency>
一般 java 工程
下载jasperreport-fonts-6.1的压缩包,解压,将其中的 jasperreports-fonts-6.1.1.jar
添加到工程的依赖中。
导入包含所需 Java 类定义的库
为了在设计报表模板时能够使用我们定义的一些数据模型,我们需要在 jaspersoft-studio 中导入对应的类库。
导入方法如下:
- 右键工程 -> Build Path -> Configure Build Path
- Libraries -> Add External JARS -> 选择要添加的 jar 包
如图所示:
Jaspersoft Studio 配置
Jaspersoft Studio 的主要作用是开发 jrxml 格式的报表模板,这个工具是对 Jasper Report 传统模板设计工具 iReport 设计器的一个基于 Eclipse 平台的完整重构。它能够让你创建包含图表、图片、子报表、交叉表等非常复杂的布局。可以通过 JDBC、TableModels、JavaBeans、XML、Hibernate、CSV 或自定义数据源来读取数据。Jaspersoft Studio 在基于 Jasper Report 的报表开发中具有举足轻重的地位。正是因为Jaspersoft Studio 对于 Jasperreports 开发的重要性,这里将对 Jaspersoft Studio 的配置与使用做一个简单的说明。
官方链接
- 下载地址:https://community.jaspersoft.com/project/jaspersoft-studio/releases
- 说明文档:https://community.jaspersoft.com/documentation?version=49176
创建报表模板
右键工程 -> New -> Jasper Report
选择 Blank A4 -> Next
输入报表模板名称 -> Next
Data Adapter 选择
One Empty Record - Empty rows
-> finish
报表元素
分类 | 元素 | 说明 |
---|---|---|
文本 | Static Text | 静态文本 |
Text Field | 文本域,可以通过表达式输出动态内容 | |
图形 | Line | 直线 |
Rectangle | 矩形 | |
Ellipse | 椭圆 | |
Image | 图像 | |
组 | Frame | 可以作为其他元素的容器,可以根据内容动态拉伸 |
表格 | Table | TODO |
报表 | Subreport | 引用其他报表的内容 |
样式
Jasper Reports 为我们提供了样式表的功能。通过样式表,我们可以将报表模板中大量类似的样式抽出来复用。降低了重复工作的同时,也提高了报表模板的模块化程度。
- 在 Outline 中右键 Styles -> Create Style
- 修改样式的 properties ,设定样式名称、字体等属性。
注意,如果勾选了 Style 中的 Default Style ,那么我们在通过拖拽的方式为报表模板添加元素时,拖入的元素默认会继承 Default Style 中设定的样式。
- 在需要应用样式的元素的 properties 中应用需要的样式。
初始设置
报表模板的各部分说明(按输出顺序排序)
|部分|出现次数|说明| |-|-|-| |Title|第一页|报表的标题,可配置为独占一页| |Page Header|每页|页眉| |No Data|第一页,仅无明细数据时输出|无数据的说明| |Column Header|每页|列表的列头| |Detail|每页|明细数据| |Summary|最后一页|合计信息,可配置为独占一页| |Column Footer|每页|列表的列脚| |Page Footer|无 Last Page Footer 时每页,否则最后一页|页脚| |Last Page Footer|最后一页|最后一页的页脚|
报表模板的 properties 设置
报表模板的属性设置如下:
典型属性说明 |属性|说明| |-|-| |When No Data Type|无详细数据时处理方式的类型,参照下文的 When No Data Type (无详细数据时处理方式)的类型说明| |Title On A New Page|Title 部分独立占用一页| |Summary On A New Page|Summary 部分独立占用一页| |Float Column Footer|默认情况下即使页面未被填满 Column Footer 部分也将位于页面的底端,勾选该选项 Column Footer 将紧随 Summary 之后|
When No Data Type(无详细数据时处理方式)类型说明 |可选值|可选值说明| |-|-| |No Pages|不生成任何页面| |Blank Page|生成空白页,包括静态文本在内的任何项目都不会被输出| |All Section No Detail|输出除 Detail 以外的其他部分| |No Data Section|输出 No Data 部分|
注意事项
- 默认情况下若输入的详细数据为空对象,那么将会输出空白页面(静态文本也不会被输出),参照上文的
When No Data Type
属性设置- 由于编辑区域包含边距,因此必须在开始编辑之前设置页面边距,否则若新的边距大于之前的边距,已绘制的元素将不会被移动
- 各部分输出的顺序并非编辑区域展示的顺序,且不可通过编辑源码变更编辑区域各部分的展示顺序
参数(Parameters)与字段(Fields)
生成报表时 JasperReport 将接收两个运行时对象,分别为一个Map<String, Object>实例和一个 JRDataSource 实例。
生成 PDF 报表的实例代码:
InputStream jasperInputStream = new FileInputStream(new File("/var/www/demo/templates/sample.jasper"));
OutputStream pdfOutputStream = new FileOutputStream(new File("/var/www/demo/reports/sample.pdf"));
Map<String, Object> parameters = new HashMap<>();
parameters.put("DATA", order);
JRDataSource dataSource = new JRBeanCollectionDataSource(order.getItems());
JasperRunManager.runReportToPdfStream(jasperInputStream, pdfOutputStream, parameters, dataSource);
其中,Map<String, Object>
实例的条目可通过 JasperReport 中同名的 Parameter 引用,表达式为 $P{parameter-name}
.
例如,下图中 orderDTO
实例的 consignee.name
的属性值可以通过 $P{DATA}.getConsignee().getName()
取得。
JRDataSource
的实例用于输出到报表的明细部分。
JRDataSource
拥有多个实现类,如 JRBeanCollectionDataSource
、JRBeanArrayDataSource
、JRCsvDataSource
、JRJpaDataSource
等。
JRDataSource
实例(或数组/列表的项目)的属性,可通过 JasperReport 中同名的 Field 引用,表达式为 $F{field-name}
.
当为数组或列表时,数据将在明细部分被循环输出。
注意事项
- 有些时候若未设置 Field 的 Description 属性的值 Jaspersoft Studio 也可能会在源码中自动创建一个内容为空的
<fieldDescription>
标签,生成报表时这将在相应的属性上引发java.lang.NoSuchMethodException: Unknown property '' on class ...
错误。 此时源码中找到以下代码片段并将其删除:<fieldDescription><![CDATA[]]></fieldDescription>
在实践中,本着简单够用的原则,我们将表单分为三类(表单报表、清单报表、嵌套报表),并相应的总结了三条设计原则,这里的设计原则并不能满足所有的需求,但是本着如下的分类与设计原则设计出的报表,应该可以满足大部分的日常需求。
设计原则
表单报表
- 适用范围:适用于有限字段、显示内容确定的报表。报表内不存在同类型循环显示的数据。
- 设计原则:一般采用字段名与字段值横向左右排列的方式,内容较少的字段放置在报表上部,内容较多的字段放置在报表下部。
例:
清单报表
- 适用范围:适用于显示字段确定,并且报表内存在同类型的需要循环显示的数据。
- 设计原则:一般采用第一行显示数据的字段名,第二行开始循环显示第一行字段对应数据的方式。
例:
嵌套报表
表单报表与清单报表之间可以互相嵌套,完成更复杂的需求。
- 适用范围:表单报表与清单报表无法直接满足条件的情况。
- 设计原则:根据需求嵌套使用表单报表与清单报表的格式,嵌套过程中各自遵循表单报表与清单报表的设计原则。
例:
Trouble Shooting
jasperreports-fonts
依赖组件的安装
问题由来
- 为什么需要手动安装
jasperreports-fonts
组件的依赖呢?
答:为了对应生成 PDF 文件时中文显示不正确的问题,我们对jasperreports-fonts
组件进行了重新打包,添加了所需的中文字体。这个操作导致了该组件无法从 Maven 公共仓库取得,所以需要手动安装这个组件的依赖。
组件说明
运行 JasperReport 所需的以下组件无法从 Maven 公共仓库取得,需要手动安装到本地 Maven 库,或上传到 Nexus Repository Manager 私有 Maven 库:
itext-2.1.7.js7.jar
(用于实现 PDF 生成)jasperreports-fonts-6.1.1.jar
(为对jasperreports-fonts
的重新打包,添加了所需的中文字体)
手动安装到本地 Maven 库
在组件的 JAR 文件所在的路径下执行以下命令以将其安装到本地 Maven 库:
$ mvn install:install-file -Dfile=./itext-2.1.7.js7.jar -DgroupId=com.lowagie -DartifactId=itext -Dversion=2.1.7.js7 -Dpackaging=jar
$ mvn install:install-file -Dfile=./jasperreports-fonts-msyh-6.1.1.jar -DgroupId=net.sf.jasperreports -DartifactId=jasperreports-fonts -Dversion=6.1.1 -Dpackaging=jar
上传到 Nexus Repository Manager
登录到 Nexus Repository Manager,选择 Upload > dxsuite-releases
。
分别选择组件的 JAR 文件,然后填写以下内容并上传:
组件 | Extension | Group ID | Artifact ID | Version | Packaging |
---|---|---|---|---|---|
itext-2.1.7.js7.jar | jar | com.lowagie | itext | 2.1.7.js7 | jar |
jasperreports-fonts-6.1.1.jar | jar | net.sf.jasperreports | jasperreports-fonts | 6.1.1 | jar |