开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
前言
最近遇到了一个需求:后台根据存储数据生成一个PDF报表,里面还会有各种分析图表,经过技术调研后,大体技术栈如下
- 使用
poi-tl来作为报表模板,生成word文档 - 使用
jfreechart来进行各种分析图表生成 - 随后将生成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文档,创建了一个文本标签和图片标签
// quick-start.docx
{{str}}
{{@img}}
随后在项目中引入相关依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.0</version>
</dependency>
@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" ) );
}
上面的代码可以分为三部分:
- 调用compile方法对word模板进行编译,读取相关标签
- 调用render方法替换标签,进行渲染数据操作
- 随后将渲染后的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例子
@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;
}
最终生成的图表图片如下图:
小结
通过上面两个例子就可以看到,使用poi-tl和jfreechart框架就可以实现各种报表文档的生成拉,如果还有其他需求就去官方看看把。