示例代码地址
在企业级应用开发中,报表生成、报表打印下载是其重要的一个环节。除了
Excel
报表之外,
目前世面上比较流行的制作PDF
报表的工具如下:
名称 | 介绍 |
---|---|
Jasper Report | 是一个强大、灵活的报表生成工具,能够展示丰富的页面内容,并将之转换成PDF |
Openoffice | openoffice是开源软件且能在windows和linux平台下运行,可以灵活的将word或者Excel转化为PDF文档。 |
iText PDF | iText是著名的开放项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。 |
PDF
,HTML
,或者XML
格式。**该库完全由Java写成,可以用于在各种Java应用程序,包括J2EE,Web应用程序中生成动态内容。**只需要将JasperReport引入工程中即可完成PDF报表的编译、显示、输出等工作。JRXML
:报表填充模板,本质是一个XML. JasperReport已经封装了一个dtd,只要按照规定的格式写这个xml文件,那么jasperReport就可以将其解析最终生成报表,但是jasperReport所解析的不是我们常见的.xml文件,而是.jrxml文件,其实跟xml是一样的,只是后缀不一样。Jasper
:**由JRXML模板编译生成的二进制文件,用于代码填充数据。**解析完成后JasperReport就开始编译.jrxml文件,将其编译成.jasper文件,因为JasperReport只可以对.jasper文件进行填充数据和转换,这步操作就跟我们java中将java文件编译成class文件是一样的Jrprint
:**当用数据填充完Jasper后生成的文件,用于输出报表。**这一步才是JasperReport的核心所在
Exporter
:决定要输出的报表为何种格式,报表输出的管理类。Jaspersoft Studio
是JasperReports库
和JasperReports服务器
的基于Eclipse的报告设计器; 它可以作为Eclipse插件或作为独立的应用程序使用。
图表
,图像
,子报表
,交叉表
等的复杂布局。JDBC
,TableModels
,JavaBeans
,XML
,Hibernate
,大数据(如Hive)
,CSV
,XML / A
以及自定义来源等各种来源访问数据,PDF
,RTF
,XML
,XLS
,CSV
,HTML
,XHTML
,文本
,DOCX
或OpenOffice
。Jaspersoft Studio
是一个可视化的报表设计工具,使用该软件可以方便地对报表进行可视化的设计,设计结果为格式.jrxml
的XML
文件,并且可以把.jrxml
文件编译成.jasper
格式文件方便JasperReport
报表引擎解析、显示。我下载的是js-studiocomm_6.20.5_windows_x86_64.exe
下载完成后无脑安装就行了
左侧切换outline
视图,调整视图的位置
Report editing area(主编辑区域) 通过拖动,定位,对齐和通过 Designer palette(设计器调色板)对报表元素调整大小
Editor Area
Repository Explorer view 包含 JasperServer 生成的连接和可用的数据适配器列表
Outline view 在大纲视图中显示了一个树的形式的方式报告的完整结构
Properties view 控件属性设置
Design tab 以图形方式创建报表中的控件
Report Editor Area介绍
Title
(标题)*只在整个报表的第一页的最上端显示。**只在第一页显示,其他页面均不显示Page Header
(页头):在整个报表中每一页都会显示。
Page Footer
(页脚): **在整个报表中每一页都会显示。**显示在页面的最下端。一般用来显示页码。Detail1
(详细) : 报表内容,每一页都会显示。Column Header
(列头): Detail中打印的是一张表的话,这Column Header就是表中列的列头。Column Footer
(列脚) :Detail中打印的是一张表的话,这Column Footer就是表中列的列脚。Summary
(统计): 表格的合计段,出现在整个报表的最后一页中,在Detail 1 Band后面。主要是用来做报表的合计显示。
- Paramters是一张报表中全局的属性,初始自带了一些属性,也可以自定义属性。大家可以理解为存放一个报表的表头数据
- Paramter的属性可以是任何类型,String,Long,Double,List等等
- Paramter可以用在报表的任何区域,一般用在报表的
Title
,Page Header
,Page Footer
区域
Paramters的创建:在左侧的Outline框,在Paramters上右键 Create Paramter 就可以创建一个新的Paramter,在右侧可以设置名称和类型。使用时直接拖拽到相应的区域即可。如下图所示
在Java程序中可以通过给对应的Paramter赋值,在打印时就可以输出你想要的结果。代码如下所示
//给Paramter赋值
HashMap<String, Object> parameters = new HashMap<String, Object>();
parameters.put("name", "小明");//这里的key要和报表中的Paramter的name对应
parameters.put("age", "18");
//中间代码省略
//核心代码,把Paramters传入JasperReport提供的方法,并返回JasperPrint 对象
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperStream, parameters, dataSource);
- Fields是报表中数据集合中的字段属性,只能自定义Field字段。大家可以理解为一个报表的明细列表数据
- Field的属性可以是任何类型,String,Long,Double,List等等
- Field只能用在报表的
Detail
区域
Fields的创建:在左侧的Outline框,在Fields上右键 Create Field 就可以创建一个新的Field,在右侧可以设置名称和类型。使用时直接拖拽到相应的区域即可。如下图所示
在Java程序中可以通过集合给集合中的每一条数据的Field字段赋值,在打印时就可以输出你想要的结果。代码如下所示
//给Field赋值
List<HashMap> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
HashMap<String, String> item = new HashMap<String, String>();
item.put("Field1", "Field1-" + i);
item.put("Field2", "Field2-" + i);
item.put("Field3", "Field3-" + i);
item.put("Field4", "Field4-" + i);
item.put("Field5", "Field5-" + i);
list.add(item);
}
//中间代码省略
//核心代码,用包含Field字段的集合创建一个JRDataSource,传入JasperReport提供的方法,并返回JasperPrint 对象
JRDataSource dataSource = new JRBeanCollectionDataSource(list);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperStream, parameters, dataSource);
- Detail是打印Field字段的区域,一个报表可以有多个Detail,在Detail上右键可以通过Add Detail Band来增加新的Detail区
- Detail会把传递进来的list的数据,循环打印出来,有多条就会打印多行,一页打印不下就会从下一页继续打印
- 如果通过Detail来打印表格,Detail的高度最好和要打印的Field高度一样,这样每行就不会有缝隙,打印出来和表格一样的效果
- 如果存在多个detail,他们是交替打印
所有动态的组件都是通过Expression表达式来绑定要打印的数据,比如Paramter,Field,Image,Table组件等等。
所有组件都有一块Print When属性
,**其中有一个Print When Expression表达式,可以在返回true的情况下打印,在false的情况下不打印。**这个表达式可以依赖其他Paramter,Field,可以通过它实现一些特殊的打印需求
new Boolean($F{showtitle1})
,new Boolean(true)
创建一个springBoot项目
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.12.RELEASEversion>
<relativePath/>
parent>
<groupId>site.zhouruigroupId>
<artifactId>jasper-report-demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>jasper-report-demoname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>net.sf.jasperreportsgroupId>
<artifactId>jasperreportsartifactId>
<version>6.5.0version>
dependency>
<dependency>
<groupId>org.olap4jgroupId>
<artifactId>olap4jartifactId>
<version>1.2.0version>
dependency>
<dependency>
<groupId>com.lowagiegroupId>
<artifactId>itextartifactId>
<version>2.1.7version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>2.4.1version>
plugin>
plugins>
build>
project>
创建jasper
文件:File
-> New
-> Jasper Report
我选择的空白A4
制作模版
点击Compile Repot
生成Jasper
文件
找到编译后的.jasper文件
编译完成后在下方控制台会提示文件生成地址
找到文件将文件复制到springboot的templates目录下改名为demo.jasper
package site.zhourui.jasperreportdemo.controller;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.util.HashMap;
/**
* @author zr
* @date 2023/7/20 14:52
*/
@RestController
@RequestMapping("/jasper")
public class demoController {
/**
* JasperReport的简单使用
*/
@GetMapping("/test1")
public void createHtml(HttpServletResponse response, HttpServletRequest request) throws Exception {
Resource resource = new ClassPathResource("templates/demo.jasper");
FileInputStream is = new FileInputStream(resource.getFile());
ServletOutputStream os = response.getOutputStream();
try {
/**
* 创建JasperPrint对象
* 数据填充
* is:inputstream params:参数填充 DataSource:数据源填充
*/
JasperPrint jasperPrint = JasperFillManager.fillReport(is, new HashMap<>(), new JREmptyDataSource());
// 写入pdf数据
JasperExportManager.exportReportToPdfStream(jasperPrint, os);
} finally {
os.flush();
os.close();
}
}
}
访问http://localhost:8080/jasper/test1
新增了一个带中文Static Text
再次生成Jasper文件demo2.Jasper放入templates目录下
测试访问http://localhost:8080/jasper/test1
新增的Text英文展示出来了,但是中文没有展示出来
jasperreports的jar包源码中不包含中文字体库。
在JasperReport Studio工具的Window-> Preferences -> font 中add一个微软雅黑的字体
我下载字体的位置
此时就可以选择我们添加的字体了(注意这里有两个微软雅黑要选我们自定义的那个)
然后我们就可以保存文件重新编译一次然后放入templates目录下改名为demo.jasper
在Jaspersoft Studio 打包字体文件Font.jar包
将导出的font.jar导入项目依赖
通过maven引入
maven打包
注意:你的文件路径可能和我的不一样
mvn install:install-file -Dfile=C:\Users\Administrator\JaspersoftWorkspace\MyReports\font\font.jar -DgroupId=site.zhourui.report -DartifactId=font -Dversion=1.0.0 -Dpackaging=jar
maven 引入依赖
<dependency>
<groupId>site.zhourui.reportgroupId>
<artifactId>fontartifactId>
<version>1.0.0version>
dependency>
也可以推送到maven远程仓库这个看你自己
通过Add as Library引入
访问测试http://localhost:8080/jasper/test2
新增两个参数year
,name
创建模板使用我们创建的参数
模板
如果是内容中文记住更换字体
生成Jasper文件demo3.Jasper放入templates目录下
新建测试方法
之前传的是一个空的HashMap
现在传入对应的值
/**
* JasperReport携带参数
* @param response
* @throws Exception
*/
@RequestMapping("/test3")
public void test3(HttpServletResponse response) throws Exception{
Resource resource = new ClassPathResource("templates/demo3.jasper");
FileInputStream is = new FileInputStream(resource.getFile());
ServletOutputStream os = response.getOutputStream();
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("year", "2023");
parameters.put("name", "测试");
try {
/**
* 创建JasperPrint对象
* 数据填充
* is:inputstream params:参数填充 DataSource:数据源填充
*/
JasperPrint jasperPrint = JasperFillManager.fillReport(is, parameters, new JREmptyDataSource());
// 写入pdf数据
JasperExportManager.exportReportToPdfStream(jasperPrint, os);
} finally {
os.flush();
os.close();
}
}
访问测试
测试链接http://localhost:8080/jasper/test3
制作模板
4个属性
如果有中文注意选择字体
生成Jasper文件demo3.Jasper放入templates目录下
新建测试方法
/**
* JasperReport携带参数 ,打印多页表单
* @param response
* @throws Exception
*/
@RequestMapping("/test4")
public void test4(HttpServletResponse response) throws Exception{
Resource resource = new ClassPathResource("templates/demo4.jasper");
FileInputStream is = new FileInputStream(resource.getFile());
ServletOutputStream os = response.getOutputStream();
Random random = new Random();
List<HashMap> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
HashMap<String, String> item = new HashMap<String, String>();
item.put("Field_1", "员工-" + i);
item.put("Field_2", "部门-" + i);
item.put("Field_3", i%2==0?"男":"女");
item.put("Field_4", String.valueOf(random.nextInt(10000 - 8000) + 8000 + 1));//8000-10000
list.add(item);
}
JRDataSource dataSource = new JRBeanCollectionDataSource(list);
try {
/**
* 创建JasperPrint对象
* 数据填充
* is:inputstream params:参数填充 DataSource:数据源填充
*/
JasperPrint jasperPrint = JasperFillManager.fillReport(is, new HashMap<>(), dataSource);
// 写入pdf数据
JasperExportManager.exportReportToPdfStream(jasperPrint, os);
} finally {
os.flush();
os.close();
}
}
测试效果 访问http://localhost:8080/jasper/test4