基于业务需求,我们需要将试题组装成试卷,然后导出 .docx 格式的 word 文档,同时需要支持公式数据在 word 中正常展示,并且能够重新编辑。
以下为调研 word 导出方案之后的各个方案对比
方案 | 移植性 | 功能性 | 易用性 |
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平台 | - | 复杂,完全不推荐使用 |
Poi-tl 简介
Poi-tl 是Word模板引擎,能够基于Word模板和数据生成新的文档。
Poi-tl API
所有标签默认以 {{ 作为开头,以 }} 作为结尾。以下介绍不同格式的数据各自的填充方式。
文本标签
{{name}}
{{author}}
{{link}}
{{anchor}}
数据格式
Map<String, Object> data = new HashMap<>();
data.put("name", "Sayi");
data.put("author", new TextRenderData("000000", "Sayi"));
data.put("link", new HyperlinkTextRenderData("website", "http://deepoove.com"));
data.put("anchor", new HyperlinkTextRenderData("anchortxt", "anchor:appendix1"));
图片标签以@开始 (注意:图片实体必须设置size)
{{@localImg}}
{{@streamImg}}
{{@urlImg}}
{{@bufferImg}}
数据格式
Map<String, Object> data = new HashMap<>();
// 本地图片
data.put("localImg", Pictures.ofLocal("sayi.png").size(120, 120).create());
// 图片流
data.put("streamImg", Pictures.ofStream(new FileInputStream("logo.jpeg"), PictureType.JPEG)
.size(100, 120).create());
// 网络图片(注意网络耗时对系统可能的性能影响)
data.put("urlImg", Pictures.ofUrl("http://deepoove.com/images/icecream.png", PictureType.PNG)
.size(100, 100).create());
// java 图片
data.put("bufferImg", Pictures.ofBufferedImage(bufferImage, PictureType.PNG)
.size(100, 100).create());
表格标签以#开始
{{#table}}
数据格式
// 一个2行2列的表格
Map<String, Object> data = new HashMap<>();
data.put("table", Tables.of(new String[][] {
new String[] { "00", "01" },
new String[] { "10", "11" }
}).border(BorderStyle.DEFAULT).create());
特殊格式–区块对:
区块对由前后两个标签组成,开始标签以?标识,结束标签以/标识
{{?person}}
Hi {{name}}!
{{?models}}
{{modelName}}
{{/models}}
{{/person}}
数据格式
Map<String, Object> name = new HashMap<>();
name.put("name", "Sayi");
List<Map<String, Object>> models = new ArrayList<>();
Map<String, Object> modelName = new HashMap<>();
modelName.put("modelName", "model");
models.add(modelName);
Map<String, Object> modelMap = new HashMap<>();
modelMap.put("models", models);
List<Map<String, Object>> person = new ArrayList<>();
person.add(name);
person.add(models);
Map<String, Object> data = new HashMap<>();
data.put("person", person);
使用区块对可以更加方便灵活的处理数据,当区块对中的值为 null 时,该数据则不会被填充;区块对支持遍历输出,同时支持区块对嵌套。
Getting Started
添加 maven 依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.9.1</version>
</dependency>
新建Word文档template.docx,word 内容包含标签 {{title}}
代码实现 word 导出
XWPFTemplate template = XWPFTemplate.compile("template.docx").render(
new HashMap<String, Object>(){{
put("title", "Hi, poi-tl Word模板引擎");
}});
template.writeAndClose(new FileOutputStream("output.docx"));
参考:
poi-tl API:http://deepoove.com/poi-tl