目前世面上比较流行的制作 PDF 报表的工具如下:
-
iText PDF :iText 是著名的开放项目,是用于生成 PDF 文档的一个 java 类库。通过 iText 不仅可以生成PDF 或 rtf 的文档,而且可以将 XML、Html 文件转化为 PDF 文件。
-
Openoffice :openoffice 是开源软件且能在 windows 和 linux 平台下运行,可以灵活的将 word 或者Excel 转化为 PDF 文档。
-
Jasper Report :是一个强大、灵活的报表生成工具,能够展示丰富的页面内容,并将之转换成 PDF
一.JasperReport
1.1介绍
JasperReport 是一个强大、灵活的报表生成工具,能够展示丰富的页面内容,并将之转换成 PDF,HTML,或者 XML格式。该库完全由 Java 写成,可以用于在各种Java应用程序,包括 J2EE,Web应用程序中生成动态内容。只需要将 JasperReport 引入工程中即可完成 PDF 报表的编译、显示、输出等工作。数据源支持更多,常用 JDBC SQL 查询、XML 文件、CSV 文件 、HQL(Hibernate 查询),HBase,JAVA集合等。还允许你义自己的数据源,通过 JASPER 文件及数据源,JASPER 就能生成最终用户想要的文档格式。
1.2开发步骤
通常我们提到PDF报表的时候,浮现在脑海中的是最终的PDF文档文件。在JasperReports中,这只是报表生命周期的最后阶段。通过 JasperReports 生成 PDF 报表一共要经过三个阶段,我们称之为 JasperReport 的生命周期,这三个阶段为: 设计(Design )阶段、执行(Execution )阶段以及输出(Export )阶段。
-
设计阶段( De sign ):所谓的报表设计就是创建一些模板,模板包含了报表的布局与设计,包括执行计算的复杂公式、可选的从数据源获取数据的查询语句、以及其它的一些信息。模板设计完成之后,我们将模板保存为JRXML 文件(JR 代表 JasperReports),其实就是一个 XML 文件。
-
执行阶段(Execution ):使用以 JRXML 文件编译为可执行的二进制文件(即.Jasper 文件)结合数据进行执行,填充报表数据。
-
输出阶段(Export ):数据填充结束,可以指定 输出为多种形式的报表。
Tips: 综上得知,对于使用JasperReport进行开发,我们重点关注如下几点即可:
-
制作报表模板并进行编译
-
构造数据并填充模板
-
输出报表
1.3模板工具Jaspersoft Studio
Jaspersoft Studio 是一个可视化的报表设计工具,使用该软件可以方便地对报表进行可视化的设计,设计结果为格式.jrxml 的 XML 文件,并且可以把.jrxml 文件编译成.jasper 格式文件方便 JasperReport 报表引擎解析、显示。
官网下载:https://community.jaspersoft.com/community-download
(关于Jaspersoft Studio的使用这里不做介绍)
制做好模板并编译为 .jasper文件, 将模板文件拷贝到项目中(使用中文,需要拷贝模板中使用到的相应字体文件),目录结构如下:
webapp/jasper/dintalk.jasper | 模板文件
resources/stsong/fonts.xml /stsong.TTF | 字体文件
<!--jasper坐标--> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>6.5.0</version> </dependency> <dependency> <groupId>org.olap4j</groupId> <artifactId>olap4j</artifactId> <version>1.2.0</version> </dependency> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency>
/** * 生成用户的采购表单 * @param id */ @RequestMapping(value = "/userPdf",name = "下载用户采购单") public void userPdf(String id) throws IOException, JRException { //1.读取jasper文件 String realPath = session.getServletContext().getRealPath("/jasper/dintalk.jasper"); InputStream in = new FileInputStream(realPath); //2.根据用户的id查询用户,将其转为Map User user = userService.findById(id); Map<String, Object> map = BeanMapUtils.beanToMap(user); //3.使用用户的id,查询所购商品信息 ProductExample productExample = new ProductExample(); productExample.createCriteria().andUserIdEqualTo(id); List<Product> Products = productService.findAll(productExample); //4.创建jrdatasource :数据源 JRDataSource jrDataSource = new JRBeanCollectionDataSource(products); //5.创建pdf的输出对象,参数(模板输入流, map, 数据源 ) JasperPrint jasperPrint = JasperFillManager.fillReport(in,map,jrDataSource); //==========设置pdf下载时的文件名称, 及解决文件名称中文乱码问题=============== //6.设置页面下载文件名称 String fileName = user.getName()+"采购单.pdf"; //7.处理中文文件名乱码问题:根据user-agent获取浏览器类型 fileName = DownloadUtil.getName(request.getHeader("user-agent"),fileName); //7.1 设置此响应头,则点击下载链接后直接完成下载 //response.setHeader("Content-Disposition", "attachment;filename="+fileName); //7.2 设置此响应头,则点击后在浏览器预览(若链接有设置,可打开新页面),可再下载 //response.setHeader("content-Disposition","filename="+fileName); //==========设置pdf下载时的文件名称, 及解决文件名称中文乱码问题=============== //8.输出pdf JasperExportManager.exportReportToPdfStream(jasperPrint,response.getOutputStream()); //9.关闭流 in.close(); }
1.关于修改下载文件名(若不进行设置,则默认下载文件名为 : userPdf.do 请求链接的结尾部分)
2.DownloadUtil.getName(request.getHeader("user-agent"),fileName);
public static String getName(String agent, String filename) throws UnsupportedEncodingException { if (agent.contains("Firefox")) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它浏览器 filename = URLEncoder.encode(filename, "utf-8"); } return filename; }
<script> function isIE(){ //获取当前浏览器相关信息 var explorer = window.navigator.userAgent.toLowerCase() ; //判断是否是ie浏览器 if (explorer.indexOf("msie") >= 0 || explorer.indexOf("rv:11.0) like gecko") >= 0) { return true; }else { return false; } } //ww 是下载链接的id,使用时修改 window.onload = function () { if(isIE()){ //在是IE浏览器的情况下,对中文请求参数编码 var str = document.getElementById("ww").href; str = encodeURI(str); document.getElementById("ww").href = str; } }; </script>
1.BeanMapUtils.beanToMap(user);
import org.springframework.cglib.beans.BeanMap; import java.util.HashMap; import java.util.Map; public class BeanMapUtils { /** * 将对象属性转化为map结合 */ public static <T> Map<String, Object> beanToMap(T bean) { Map<String, Object> map = new HashMap<String, Object>(); if (bean != null) { BeanMap beanMap = BeanMap.create(bean); for (Object key : beanMap.keySet()) { map.put(key+"", beanMap.get(key)); } } return map; }
关注微信公众号, 随时随地学习