一、poi-tl简介
下面简介来自官方文档。
官方文档:http://deepoove.com/poi-tl/#_why_poi_tl
1、简介
poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档。
poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性。
V1.12.x版本作了一个不兼容的改动,升级的时候需要注意:
- 重构了PictureRenderData,改为抽象类,建议使用Pictures工厂方法来创建图片数据
2、poi-tl与poi区别
poi-tl与poi区别:

3、快速入门
poi-tl使用的通用步骤:
- 引入依赖
<dependency>
  <groupId>com.deepoove</groupId>
  <artifactId>poi-tl</artifactId>
  <version>1.12.1</version>
</dependency>
- 定义模板
模板是Docx格式的Word文档,你可以使用Microsoft office、WPS Office、Pages等任何你喜欢的软件制作模板,也可以使用Apache POI代码来生成模板。
模板即样式,同时代码也可以设置样式。
所有的标签都是以{{开头,以}}结尾,标签可以出现在任何位置,包括页眉,页脚,表格内部,文本框等,表格布局可以设计出很多优秀专业的文档,推荐使用表格布局。
标签由前后两个大括号组成,{{title}}是标签,{{?title}}也是标签,title是这个标签的名称,?问号标识了标签类型,比如表格,图片或者自定义标签等。
一般我们线下定义好模板格式。比如:新建Word文档 template.docx,文件内容如下:
 
- 填充数据
数据类似于哈希或者字典,可以是Map结构(key是标签名称),也可以是对象(属性名是标签名称)。
- 输出模板
输出模板的方式有很多种,比如:
- 以输出流|文件流等方式进行输出。最后不要忘记关闭这些流。
入门示例demo:
XWPFTemplate template = XWPFTemplate.compile("template.docx").render(
  new HashMap<String, Object>(){{
    put("title", "Hi, poi-tl Word模板引擎");
}});  
template.writeAndClose(new FileOutputStream("output.docx")); 
二、文本/表格和图片渲染
下面进行文本、表格和图片的渲染简介。
1、文本
文本标签:{{var}}
数据模型:
- String :文本
- TextRenderData :有样式的文本
- HyperlinkTextRenderData :超链接和锚点文本
- Object :调用 toString() 方法转化为文本
put("name", "Sayi");
put("author", new TextRenderData("000000", "Sayi"));
put("link", new HyperlinkTextRenderData("website", "http://deepoove.com"));
put("anchor", new HyperlinkTextRenderData("anchortxt", "anchor:appendix1"));
// 还提供了更加优雅的工厂 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());
POI-TL模板即样式,一般模板文档能设置好的样式,代码就不要处理啦。
2.表格
表格标签以#开始:{{#var}}
数据模型:
- TableRenderData
推荐使用工厂 Tables 、 Rows 和 Cells 构建表格模型。
// 第0行居中且背景为蓝色的表格
RowRenderData row0 = Rows.of("姓名", "学历").textColor("FFFFFF")
      .bgColor("4472C4").center().create();
RowRenderData row1 = Rows.create("李四", "博士");
put("table1", Tables.create(row0, row1));
3、图片
图片标签以@开始:{{@var}}
数据模型:
- String :图片url或者本地路径,默认使用图片自身尺寸
- PictureRenderData
- ByteArrayPictureRenderData
- FilePictureRenderData
- UrlPictureRenderData
推荐使用工厂 Pictures 构建图片模型。
// 指定图片路径
put("image", "logo.png");
// svg图片
put("svg", "https://img.shields.io/badge/jdk-1.6%2B-orange.svg");
// 设置图片宽高
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());
4、示例模板demo
示例demo,进行文本、表格和图片的渲染。
1)新建模板文档 template文档.docx

2)完整代码如下:
public class PoiWordTest1 {
    private static void createTemplateData() throws IOException {
        String dirName = "D:\\TempFiles\\poitl";
        String templateFileName = "template文档.docx";
        String outFileName = "output文档.docx";
        // 模板数据
        Map<String, Object> templateData = new HashMap<>();
        // 1.文本
        templateData.put("txt1", "测试文本1");
        templateData.put("txt2", "测试文本2");
        templateData.put("table1Name", "测试table1Name");
        templateData.put("img1Name", "测试img1Name");
        // 2.表格
        List<TableInfo> tableInfoList = new ArrayList<>();
        tableInfoList.add(new TableInfo("类型1", 3001, new BigDecimal("19.484")));
        tableInfoList.add(new TableInfo("类型2", 180, new BigDecimal("1.10")));
        tableInfoList.add(new TableInfo("类型3", 2000, new BigDecimal("19.485")));
        tableInfoList.add(new TableInfo("类型4", 180, new BigDecimal("1.100")));
        tableInfoList = tableInfoList.stream().sorted(Comparator.comparingInt(TableInfo::getInfoCount).reversed()).collect(Collectors.toList());
        String[] tableHeader = new String[]{"序号", "类型", "数量", "百分比"};
        createTable(templateData, tableHeader, tableInfoList);
        // 3.图片
        String fileName = "b1.jpg";
        FileInputStream inputStream = new FileInputStream(dirName + File.separator + fileName);
        templateData.put("img1", Pictures.ofStream(inputStream, PictureType.PNG)
                .size(200, 220)
                .create());
        // 4. 创建模板,输出模板
        XWPFTemplate template = XWPFTemplate.compile(dirName + File.separator + templateFileName)
                .render(templateData);
        template.writeAndClose(new FileOutputStream(dirName + File.separator + outFileName));
    }
    private static void createTable(Map<String, Object> templateData, String[] tableHeader, List<TableInfo> tableInfoList) {
        // 表格
        RowRenderData tableHeaderRow = Rows.of(tableHeader).bgColor("BDDCE6").center().create();
        RowRenderData[] rowRenderData = new RowRenderData[tableInfoList.size() + 1];
        rowRenderData[0] = tableHeaderRow;
        for (int i = 0; i < tableInfoList.size(); i++) {
            TableInfo tableInfo = tableInfoList.get(i);
            String type = tableInfo.getType();
            Integer infoCount = tableInfo.getInfoCount();
            BigDecimal ratio = tableInfo.getRatio();
            String infoCountStr = infoCount == null ? "" : String.valueOf(infoCount);
            // 保留两位小数
            String ratioStr = bigDecimal2Str(ratio, 2);
            if (StringUtils.isNotBlank(ratioStr)) {
                ratioStr = ratioStr + "%";
            }
            RowRenderData rowData = Rows.create(String.valueOf(i + 1), type, infoCountStr, ratioStr);
            rowRenderData[i + 1] = rowData;
        }
        // 一个几行4列的表格
        templateData.put("table1Info", Tables.create(rowRenderData));
    }
    /**
     * 转string,四舍五入
     *
     * @param value
     * @param newScale - 保留几位小数,默认2
     * @return
     */
    private static String bigDecimal2Str(BigDecimal value, Integer newScale) {
        if (value == null) {
            return "";
        }
        newScale = newScale == null ? 2 : newScale;
        BigDecimal bigDecimal = value.setScale(newScale, BigDecimal.ROUND_HALF_UP);
        return bigDecimal.toString();
    }
    public static void main(String[] args) throws IOException {
        createTemplateData();
    }
}
3)输出文档:

注意:
- 图片默认是嵌入型的,如果你想使用浮于文字之上,目前博主还没找到方法。

上面文件都是本地的。下面写一个常用的方法。模板流,输出生成模板流,保存到文件系统中。
        // 4. 创建模板,输出模板
        InputStream templateInput = getTemplateInputStream("文件ID"); //通过文件系统获取定义好的文件模板流
        XWPFTemplate template = XWPFTemplate.compile(templateInput).render(templateData);
        // 输出生成的模板流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        template.writeAndClose(byteArrayOutputStream);
        // 保存生成的模板流文件到文件系统
        byte[] buffer = byteArrayOutputStream.toByteArray();
        InputStream saveInputStream = new ByteArrayInputStream(buffer);
        String outFileName = "output文档.docx";
        saveGenerateTemplateFile(saveInputStream, outFileName);
更多使用参见官方文档。
– 求知若饥,虚心若愚。



















