1.poi-tl简介
poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库(官方文档: Poi-tl Documentation)
2.poi-tl特性
1.支持注入的模板类型
-
文本
-
图片
-
列表
-
区块对
-
嵌套
-
多系列图表
-
单系列图表
-
组合图表
2.poi-tl使用步骤
1.引入依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.0</version>
</dependency>
2.核心使用代码
XWPFTemplate template = XWPFTemplate.compile("template.docx").render(
new HashMap<String, Object>(){{
put("title", "Hi, YC");
}});
template.writeAndClose(new FileOutputStream("output.docx"));
3.常用方法
XWPFTemplate template = XWPFTemplate.compile("filePath"); // 编译模板
template.render(填充的数据map或对象) //渲染数据
template.write(输出流out) //输出到流
4.具体实现
1.构建word模板
模板中填充位置占位符语法: {{name}}
2.引入模板
XWPFTemplate template = XWPFTemplate.compile("filePath")
3.模板中填充数据类型
3.1 Map: 键为占位符名称, 值为填充的具体数据
3.2 对象: 对象中的属性为占位符名称
4.构建word文件并导出
// 数据转换
Map<String, Object> fillMap = new HashMap<>();
// 文件名称
String fileName = URLEncoder.encode("文件名称", StandardCharsets.UTF_8);
// 指示响应内容的格式
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");
try (OutputStream out = response.getOutputStream();
XWPFTemplate template = getTemplate(filePath)) {
// 数据填充
template.render(fillMap);
template.write(out);
out.flush();
} catch (IOException ex) {
throw new IOException(ex);
}
3.poi-tl进阶使用
1.常用标签
1.1文本
语法: {{var}}
数据模型:
String
:文本
TextRenderData
:有样式的文本
HyperlinkTextRenderData
:超链接和锚点文本
Object
:调用 toString() 方法转化为文本
示例:
示例1(new 操作符):
put("name", "Sayi");
put("author", new TextRenderData("000000", "Sayi"));
put("link", new HyperlinkTextRenderData("website", "http://deepoove.com"));
put("anchor", new HyperlinkTextRenderData("anchortxt", "anchor:appendix1"));
示例2(工厂 Texts 和链式调用):
put("author", Texts.of("Sayi").color("000000").create());
put("link", Texts.of("website").link("http://deepoove.com").create());
put("anchor", Texts.of("anchortxt").anchor("appendix1").create());
//TextRenderData详解(自定义内容格式)
//先定义文本对象
TextRenderData textRenderData = new TextRenderData();
//设置文本内容
textRenderData.setText("张三");
//设置文本格式
Style style = new Style();
style.setBold(true);
style.setColor("000F00");
style.setFontSize(20);
textRenderData.setStyle(style);
//将文本数据和模板中变量对应
data.put("name", textRenderData);
//TextRenderData的结构体 Style的属性
{
"text": "Sayi",
"style": {
"strike": false, //删除线
"bold": true, //粗体
"italic": false, //斜体
"color": "00FF00", //颜色
"underLine": false, //下划线
"fontFamily": "微软雅黑", //字体
"fontSize": 12, //字号
"highlightColor": "green", //背景高亮色
"vertAlign": "superscript", //上标或者下标
"characterSpacing" : 20 //间距
}
}
1.2图片
语法: {{@var}}
数据模型:
String
:图片url或者本地路径,默认使用图片自身尺寸
PictureRenderData
ByteArrayPictureRenderData
FilePictureRenderData
UrlPictureRenderData
示例:
//示例1: 直接指定图片路径
put("image", "logo.png");
// svg图片
put("svg", "https://img.shields.io/badge/jdk-1.6%2B-orange.svg");
//示例2:通过使用工厂 Pictures 构建图片模型
// 设置图片宽高
put("image1", Pictures.ofLocal("logo.png").size(120, 120).create());
// 图片流
put("streamImg", Pictures.ofStream(new FileInputStream("logo.jpeg"), PictureType.JPEG)
.size(100, 120).create());
// 网络图片(注意网络耗时对系统可能的性能影响)
put("urlImg", Pictures.ofUrl("http://deepoove.com/images/icecream.png")
.size(100, 100).create());
// java图片
put("buffered", Pictures.ofBufferedImage(bufferImage, PictureType.PNG)
.size(100, 100).create());
//FilePictureRenderData的结构体
{
"pictureType" : "PNG", //图片类型
"path": "logo.png", //图片路径
"pictureStyle": {
"width": 100,
"height": 100
},
"altMeta": "图片不存在" //当无法获取图片时展示的文字
}
1.3表格
语法:{{#var}}
数据类型: TableRenderData
示例:
//示例1 基础表格示例
// 一个2行2列的表格
put("table0", Tables.of(new String[][] {
new String[] { "00", "01" },
new String[] { "10", "11" }
}).border(BorderStyle.DEFAULT).create());
//示例2 表格样式示例
// 第0行居中且背景为蓝色的表格
RowRenderData row0 = Rows.of("姓名", "学历").textColor("FFFFFF")
.bgColor("4472C4").center().create();
RowRenderData row1 = Rows.create("李四", "博士");
put("table1", Tables.create(row0, row1));
//示例3 表格合并示例
// 合并第1行所有单元格的表格
RowRenderData row0 = Rows.of("列0", "列1", "列2").center().bgColor("4472C4").create();
RowRenderData row1 = Rows.create("没有数据", null, null);
MergeCellRule rule = MergeCellRule.builder().map(Grid.of(1, 0), Grid.of(1, 2)).build();
put("table3", Tables.of(row0, row1).mergeRule(rule).create());
//TableRenderData实现更复杂的表格
//TableRenderData的结构体
{
"rows": [ //行数据
{
"cells": [ //单元格数据
{
"paragraphs": [ //单元格内段落
{
"contents": [
{
[TextRenderData] //单元格内文本
},
{
[PictureRenderData] //单元格内图片
}
],
"paragraphStyle": null //单元格内段落文本的样式:对齐
}
],
"cellStyle": { //单元格样式:垂直对齐方式,背景色
"backgroundColor": "00000",
"vertAlign": "CENTER"
}
}
],
"rowStyle": { // 行样式:行高(单位cm)
"height": 2.0f
}
}
],
"tableStyle": { //表格样式:表格对齐、边框样式
"width": 14.63f,
"colWidths": null
},
"mergeRule": { //单元格合并规则,比如第0行第0列至第1行第2列单元格合并
"mapping": {
"0-0": "1-2"
}
}
}
1.4列表
语法: {{*var}}
数据模型:
List<String>
NumberingRenderData
示例:
//使用工厂 Numberings 构建列表模型
put("list", Numberings.create("Plug-in grammar",
"Supports word text, pictures, table...",
"Not just templates"));
//Numberings.of(NumberingFormat) 来指定编号样式
DECIMAL //1. 2. 3.
DECIMAL_PARENTHESES //1) 2) 3)
BULLET //● ● ●
LOWER_LETTER //a. b. c.
LOWER_ROMAN //i ⅱ ⅲ
UPPER_LETTER //A. B. C.
2.引用标签
2.1图片
语法: {{var}}, 使用位置在默认图片上,右键,可选文字
数据模型: 同图片标签一致, PictureRenderData
示例:
put("img", Pictures.ofLocal("sayi.png").create());
2.2多系列图表指条形图(3D条形图)、柱形图(3D柱形图)等
语法: 语法: {{var}}, 使用位置在默认图片上,右键,可选文字
数据模型: ChartMultiSeriesRenderData
示例:
//使用工厂 Charts 构建图表模型
ChartMultiSeriesRenderData chart = Charts
.ofMultiSeries("ChartTitle", new String[] { "中文", "English" })
.addSeries("countries", new Double[] { 15.0, 6.0 })
.addSeries("speakers", new Double[] { 223.0, 119.0 })
.create();
put("barChart", chart);
//ChartMultiSeriesRenderData的结构体
{
"chartTitle": "ChartTitle", //图表标题
"categories": [ //种类
"中文", "English"
],
"seriesDatas": [ //所有系列
{
"name": "countries", //当前系列名称
"values": [ //当前系列对应每个种类的值
15, 6
]
},
{
"name": "speakers",
"values": [
223, 119
]
}
]
}
2.3单系列图表, 指的是饼图(3D饼图)、圆环图等
语法: {{var}}, 使用位置在默认图片上,右键,可选文字
数据模型:ChartSingleSeriesRenderData
示例:
//使用工厂 Charts 构建图表模型
ChartSingleSeriesRenderData pie = Charts
.ofSingleSeries("ChartTitle", new String[] { "美国", "中国" })
.series("countries", new Integer[] { 9826675, 9596961 })
.create();
put("pieChart", pie);
//ChartSingleSeriesRenderData的结构体
{
"chartTitle": "ChartTitle", //图表标题
"categories": [ //种类
"美国",
"中国"
],
"seriesData": { //单系列
"name": "countries", // 单系列名称
"values": [ //单系列对应每个种类的值
9826675,
9596961
]
}
}
2.4组合图表
语法: {{var}}, 使用位置在默认图片上,右键,可选文字
数据模型: ChartMultiSeriesRenderData
示例:
ChartSingleSeriesRenderData comb = Charts
.ofComboSeries("MyChart", new String[] { "中文", "English" })
.addBarSeries("countries", new Double[] { 15.0, 6.0 })
.addBarSeries("speakers", new Double[] { 223.0, 119.0 })
.addBarSeries("NewBar", new Double[] { 223.0, 119.0 })
.addLineSeries("youngs", new Double[] { 323.0, 89.0 })
.addLineSeries("NewLine", new Double[] { 123.0, 59.0 }).create();
put("combChart", comb);
//ChartMultiSeriesRenderData的结构体
{
"chartTitle": "MyChart", // 图表标题
"categories": [ //种类
"中文", "English"
],
"seriesDatas": [ //所有系列
{
"name": "countries", //当前系列名称
"comboType": "BAR", //当前系列的图表类型comboType:柱形图BAR、折线图LINE、面积图 AREA
"values": [ //当前系列对应每个种类的值
15, 6
]
},
{
"name": "speakers",
"comboType": "LINE",
"values": [
223, 119
]
}
]
}