抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

前言

最近遇到了一个需求:后台根据存储数据生成一个PDF报表,里面还会有各种分析图表,经过技术调研后,大体技术栈如下

  1. 使用poi-tl来作为报表模板,生成word文档
  2. 使用jfreechart来进行各种分析图表生成
  3. 随后将生成word文档转换为PDF即可

开放思路理清后,下面就来了解一下怎么编码把~

poi-tl

poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档

上面就是官方的介绍,它支持动态将标签渲染为文本、图片、表格、图表等,能够满足我们的各种需求。

同时官方还列举了与其他word模板框架的对比:

方案 移植性 功能性 易用性
Poi-tl Java跨平台 Word模板引擎,基于Apache POI,提供更友好的API 低代码,准备文档模板和数据即可
Apache POI Java跨平台 Apache项目,封装了常见的文档操作,也可以操作底层XML结构 文档不全,这里有一个教程:Apache POI Word快速入门
Freemarker XML跨平台 仅支持文本,很大的局限性 不推荐,XML结构的代码几乎无法维护
OpenOffice 部署OpenOffice,移植性较差 - 需要了解OpenOffice的API
HTML浏览器导出 依赖浏览器的实现,移植性较差 HTML不能很好的兼容Word的格式,样式糟糕 -
Jacob、winlib Windows平台 - 复杂,完全不推荐使用

那么下面就来写个demo试试,是否能够满足我的需求~

demo例子

首先创建一个word文档,创建了一个文本标签和图片标签

1
2
3
// quick-start.docx
{{str}}
{{@img}}

随后在项目中引入相关依赖

1
2
3
4
5
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void testPoiTl() throws IOException {
InputStream inputStream = this.getClass().getResourceAsStream( "/word/quick-start.docx" );
JFreeChart barChart = generateJFreeChart();
BufferedImage bufferedImage = barChart.createBufferedImage( 640, 480 );
XWPFTemplate template = XWPFTemplate.compile( inputStream ).render(
new HashMap<String, Object>() {{
put( "str", "Hi, poi-tl Word模板引擎" );
put( "img", Pictures.ofBufferedImage( bufferedImage, PictureType.PNG ).size( 640,480 ).create() ); // 先不用理这一行
}} );
template.writeAndClose( new FileOutputStream( "./word/output.docx" ) );
}

上面的代码可以分为三部分:

  1. 调用compile方法对word模板进行编译,读取相关标签
  2. 调用render方法替换标签,进行渲染数据操作
  3. 随后将渲染后的word文档进行输出

将其称为:TDO模式:Template + data-model = output

jfreechart

通过上面的代码,可以看到图表的生成我使用了JFreeChart类,这是jfreechart中条状图的实现类。

JFreeChart是一个适用于Java™平台的综合免费图表库,可以在客户端(JavaFX和Swing)或服务器端使用,可导出多种格式,包括SVG、PNG和PDF。

该项目的文档可能比较少,不过官方提供了一个demo库来让我们学习相关API:jfree/jfree-demos: Various demo programs for JFree projects (github.com)

demo例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Test
public void testGenerateChart() throws IOException {
JFreeChart barChart = generateJFreeChart();
ChartUtils.saveChartAsJPEG( new File( "./word/chart.jpeg" ), barChart, 640, 480 );
}

public JFreeChart generateJFreeChart() {
// 条状图的标题
String chartTitle = "测试条状图";

// 行名称
String departmentName1 = "文商学院";
String departmentName2 = "汽车学院";
String departmentName3 = "创意学院";
// 需要注意中文图表需要使用Font类来进行设置,否则会乱码

Font font = new Font( "宋体", Font.BOLD, 15 );
DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
// 设置图表值
categoryDataset.setValue( 90, departmentName1, departmentName1 );
categoryDataset.setValue( 91, departmentName2, departmentName2 );
categoryDataset.setValue( 81, departmentName3, departmentName3 );


JFreeChart barChart = ChartFactory.createBarChart(
chartTitle,
"部门",
"分数",
categoryDataset,
PlotOrientation.VERTICAL,
true, true, false
);

// 设置font类型
barChart.getTitle().setFont( font );
barChart.getLegend().setItemFont( font );
CategoryPlot categoryPlot = barChart.getCategoryPlot();
CategoryAxis domainAxis = categoryPlot.getDomainAxis();
domainAxis.setLabelFont( font );
domainAxis.setTickLabelFont( font );
categoryPlot.getRangeAxis().setLabelFont( font );
categoryPlot.getRangeAxis().setTickLabelFont( font );
return barChart;
}

最终生成的图表图片如下图:

chart

小结

通过上面两个例子就可以看到,使用poi-tl和jfreechart框架就可以实现各种报表文档的生成拉,如果还有其他需求就去官方看看把。