生成pdf文件
文件要素
- 文件中包含图片
- 文件中包含列表
- 文件中包含表格
- 文件中包含循环嵌套写入的内容
- 文件需要后端生成echarts图表数据
基于以上几点考虑
技术选取
方式一
itext7是一款用于生成PDF文档的一个java类库,通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。
网上资料比较少, 可以通过写段落/图片/表格,也可以定制pdf模板然后通过填充域属性值,达到生成PDF文件的结果;
难点; 通过代码写PDF,某些排版不好配置, 可以通过PDF模板生成,据说不能太复杂
官网: https://kb.itextpdf.com/home/it7kb
方式二 常用的JAVA POI 写WORD 文件 转PDF
通过WORD 作为文件模板,填充数据->WORD转PDF
使用原生POI API 方式难度比较大
后端生成Echarts图片是一个难点(不通过浏览器响应)
WORD模板填充数据后,转PDF, 样式问题,排版问题,技术选择问题
POI-TL 转为模板
官网: http://deepoove.com/poi-tl/1.9.x/
poi-tl是一个免费开源的Java类库,你可以非常方便的加入到你的Java项目中, 替换目模板,很方便;案例都可以去官网看看,文档中大部分功能已经满足使用, 一目了然.
方案 | 移植性 | 功能性 | 易用性 |
---|---|---|---|
Poi-tl | Java跨平台 | Word模板引擎 | 基于Apache POI |
Apache POI | Java跨平台 | Apache项目,功能丰富 | 文档不全,这里有一个教程:Apache POI Word快速入门 |
Freemarker | XML跨平台 | 仅支持文本,很大的局限性 | 不推荐,需要维护XML结构,代码后期不可维护 |
OpenOffice | 部署OpenOffice,移植性较差 | - | 需要了解OpenOffice的API |
HTML浏览器导出 | 依赖浏览器的实现,移植性较差 | HTML不能很好的兼容Word的格式 | - |
Jacob、winlib | Windows平台 | - | 复杂,完全不推荐使用 |
引擎功能 | 描述 |
---|---|
文本 | 将标签渲染为文本 |
图片 | 将标签渲染为图片 |
表格 | 将标签渲染为表格 |
列表 | 将标签渲染为列表 |
图表 | 条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、饼图(3D饼图)等图表渲染 |
If Condition判断 | 隐藏或者显示某些文档内容(包括文本、段落、图片、表格、列表、图表等) |
Foreach Loop循环 | 循环某些文档内容(包括文本、段落、图片、表格、列表、图表等) |
Loop表格行 | 循环渲染表格的某一行 |
Loop表格列 | 循环渲染表格的某一列 |
Loop有序列表 | 支持有序列表的循环,同时支持多级列表 |
图片替换 | 将原有图片替换成另一张图片 |
书签、锚点、超链接 | 支持设置书签,文档内锚点和超链接功能 |
强大的表达式 | 完全支持SpringEL表达式,可以扩展更多的表达式:OGNL, MVEL… |
标签定制 | 支持自定义标签前后缀 |
文本框 | 文本框内标签支持 |
样式 | 模板即样式,同时代码也可以设置样式 |
模板嵌套 | 模板包含子模板,子模板再包含子模板 |
合并 | Word合并Merge,也可以在指定位置进行合并 |
用户自定义函数(插件) | 在文档任何位置执行函数 |
贴一段生成动态表格代码
public class MyDynamicTableCountPolicy extends DynamicTableRenderPolicy {
// 填充数据所在行数
private int startDataRow;
// 实体类型:属性自己添加的,想依据不同属性做不同的事情
private String optType;
// 需要填充的表格的列数
private int cellNum;
public InstanceResourceTableCountPolicy(int startDataRow, int cellNum) {
this.startDataRow = startDataRow;
this.cellNum = cellNum;
}
public InstanceResourceTableCountPolicy(String optType, int startDataRow, int cellNum) {
this.startDataRow = startDataRow;
this.cellNum = cellNum;
this.optType = optType;
}
@Override
public void render(XWPFTable table, Object data) throws Exception {
table.removeRow(startDataRow);
if (ObjectUtil.isEmpty(data)) return;
List<RowRenderData> rowDataList = (List<RowRenderData>)data;
// 循环插入行
for (RowRenderData rowData : rowDataList ){
XWPFTableRow insertNewTableRow = table.insertNewTableRow(startDataRow);
for (int j = 0; j < cellNum; j++) {
XWPFTableCell cell = insertNewTableRow.createCell();
cell.setWidthType(TableWidthType.NIL); //不设置列宽
}
TableRenderPolicy.Helper.renderRow(table.