Java Word模板引擎-Poi-tl

39 篇文章 1 订阅
6 篇文章 0 订阅

本文内容从Poi-tl官方文档摘录,poi-tl是一个基于Java POI的Word模板引擎,有着非常强大的功能

此处只摘录了一些我现在需要用到的功能







一、简单示例

1.准备一个模板文档 template.docx

在文档中写上{{title}}

2.写一个测试方法

public class PoiTlTest01 {
    @Test
    public void testStart() throws IOException {
        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"));

除了使用上面这这种new方法,还可以使用链式调用,使用更优雅的Text来构建文本模型

put("name", "Sayi");
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的结构体
{
  "text": "Sayi",
  "style": {
    "strike": false,  // 删除线
    "bold": true,  // 粗体
    "italic": false,  // 斜体
    "color": "00FF00",  // 颜色
    "underLine": false,  // 下划线
    "fontFamily": "微软雅黑",  // 字体样式
    "fontSize": 12,  // 字体大小
    "highlightColor": "green",  // 背景高亮色
    "vertAlign": "superscript",  // 上标或者下标
    "characterSpacing" : 20  // 间距
  }
}

文本之间换行使用\n


2.列表

列表标签以*开始:{{*var}}
数据模型:

  • NumberingReanderData
    推荐使用工厂Numberings构建编号模型

示例代码:

put("list", Numberings.create("Plug-in grammar",
                    "Supports word text, pictures, table...",
                    "Not just templates"));

编号样式支持罗马字符、有序无序等,可以通过Numberings.os(NumberingFormat)来指定

DECIMAL //1. 2. 3.
DECIMAL_PARENTHESES //1) 2) 3)
BULLET //● ● ●
LOWER_LETTER //a. b. c.
LOWER_ROMAN //i ⅱ ⅲ
UPPER_LETTER //A. B. C.

3.区块对

区块对由前后两个标签组成,开始标签以?标识,结束标签以/标识,如:

{{?sections}}{{/sections}} 

区块对应用范围

区块对开始和结束标签中间可以包含以下内容:

  • 多个图片
  • 表格
  • 段落
  • 列表
  • 图表
  • 等…

其中开始和结束标签可以跨多个段落,也可以在同一个段落,但是如果在表格中使用区块对,开始和结束标签必须在同一个单元格内,因为跨多个单元格的渲染行为是未知的
区块对在处理一些列文档元素的时候非常有用,位于区块对中的文档元素可以被渲染零次,一次或N次,这取决于区块对的取值。

False或空集合

隐藏区块中的所有文档元素
如果区块对的值是null、false或者空的集合,位于区块中的所有文档元素将不会显示,等同于if语句的条件为false
如下:


data-model

{
  "announce": false
}

------

template.docx

Made it,Ma!{{?announce}}Top of the world!{{/announce}}

Made it,Ma!

{{?announce}}

Top of the world!🎋

{{/announce}}

----

output.docx

Made it,Ma!

Made it,Ma!


非False且不是集合

显示区块中的文档元素 渲染一次
如果区块对的值不为null、false,且不是集合,位于区块中的所有文档元素会被渲染一次,等同于if语句的条件为true


data-model

{
  "person": { "name": "Sayi" }
}

-----

template.docx

{{?person}}

Hi {{name}}!

{{/person}}

-----

output.docx

Hi Sayi!

区块对中标签的作用域会被限定在当前区块对内,当且仅当区块对的值是 boolean 类型且为 true 时,这些标签作用域才不会改变。


非空集合

根据集合的大小,循环渲染区块中的文档元素
如果区块对的值是一个非空集合,区块中的文档元素会被迭代渲染一次或者N次,这取决于集合的大小,类似foreach语句


data-model

{
  "songs": [
    { "name": "Memories" },
    { "name": "Sugar" },
    { "name": "Last Dance" }
  ]
}

----

template.docx

{{?songs}}

{{name}}

{{/songs}}

----

output.docx

Memories

Sugar

Last Dance


上述的集合是根据值的类型是否实现了Iterable迭代器接口来判断


循环内置变量

在循环中提供了一些内置banliang,这些内置变量只能用于区块对中

变量类型说明
_indexint返回当前迭代从0开始的索引
_is_firstboolean判别循环项是否是当前迭代的第一项
_is_lastboolean判别循环项是否是当前迭代的最后一项
_has_nextboolean判别循环项是否是有下一项
_is_even_itemboolean判别循环项是否是当前迭代间隔1的奇数项
_is_odd_itemboolean判别循环项是否是当前迭代间隔1的偶数项
#thisobject引用当前对象,由于#和已有表格标标识的冲突,所以在文本标签中需要使用=

示例数据:

{
  "produces": [
    "application/json",
    "application/xml"
  ]
}

-----

template.docx:

{{?produces}}
{{_index}}. {{=#this}}
{{/produces}}

----

output.docx:

0. application/json
1. application/xml

4.嵌套

嵌套又称为导入、包含或者合并,以+标识:{{+var}}
数据模型:

  • DocxRenderData
    推荐使用工厂Includes构建嵌套模型
List<SegmentData> subData = new ArrayList<SegmentData>();
SegmentData s1 = new SegmentData();
s1.setTitle("Monday");
s1.setContent("Two parallel lines will intersect one day.");
subData.add(s1);

SegmentData s2 = new SegmentData();
s2.setTitle("Friday");
s2.setContent("Confidence is not necessarily successful.");
subData.add(s2);

//主模板包含嵌套标签{{+docx_word}}
//segment.docx是一个包含了{{title}}和{{content}}的子模板,使用subData集合渲染后合并到主模板
put("docx_word", Includes.ofLocal("segment.docx").setRenderModel(subData).create());  


三、配置

poi-tl提供了配置类Configure来存储常用的设置,配置的使用方式如下:

ConfigureBuilder builder = Configure.builder();
XWPFTemplate.compile("template.docx", builder.buid());

1.前后缀

可以使用builder.buildGramer()方法来修改标签的前后缀


2.标签类型

默认的图片标签是以@开始,也可以使用%开始作为图片标签

builder.addPlugin('%', new PictureRenderPolicy());

也可以根据自己的需求 对我标签标识类型进行更改

builder.addPlugin('@', new TableRenderPolicy());
builder.addPlugin('#', new PictureRenderPolicy());

这样{{@var}}就ibanchengle表格标签,{{#var}}就变成了图片标签,虽然不建议对默认标签标识进行修改,但是从中可以看到poi-tl插件的灵活度


3.标签正则

标签默认支持中文、字母、数字、下划线的组合,可以通过正则表达式来配置标签的规则,比如不允许中:

builder.buildGrammerRegex("[\\w]+(\\.[\\w]+)*");

比如允许除了标签前后缀以外的任意字符:

builder.buildGrammerRegex(RegexUtils.createGeneral("{{", "}}"));

4.计算标签值

计算标签值是指如何在数据中索引标签的值,可以完全自定义计算的方式:

builder.setRenderDataComputeFactory(new RenderDataComputeFactory());

RenderDataComputeFactory是一个抽象工厂,你可以定义自己的工厂提供标签表达式计算接口 RenderDataCompute 的实现。


5.Spring表达式

Spring Expression Language 是一个强大的表达式语言,支持在运行时查询和操作对象图。在使用前需要引入相应的依赖:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-expression</artifactId>
  <version>4.3.6.RELEASE</version>
</dependency>

为了在模板标签中使用SpringEL表达式,需要将标签配置为SpringEL模式:

builder.useSpringEL();

6.SpringEL作为区块对的条件

Spring表达式与区块对结合可以实现更强大的功能


data-model

{
  "desc": "",
  "summary": "Find A Pet",
  "produces": [
    "application/xml"
  ]
}

----

template.docx

{{?desc == null or desc == ''}}{{summary}}{{/}}

{{?produces == null or produces.size() == 0}}{{/}}

----

output.docx

Find A Pet

使用SpringEL时区块对的结束标签可以是:{{/}}


7.错误处理

poi-tl支持在发生错误的时候定制引擎的行为

标签无法被计算

标签无法被计算的场景有几种,比如模板中引用了一个不存在的变量,或者级联的前置结果不是一个哈希,如 {{author.name}} 中author的值为null,此时就无法计算name的值。

poi-tl可以在发生这种错误时对计算结果进行配置,默认会认为标签值为 null 。当我们需要严格校验模板是否有人为失误时,可以抛出异常:

builder.useDefaultEL(true);

注意的是,如果使用SpringEL表达式,可以通过参数来配置异常处理的方式:

builder.useSpringEL(true);

标签数据类型不合法

我们知道渲染图片、表格等标签时对数据模型是有要求的,如果数据不合法(为空或者是一个错误的数据类型),可以配置模板标签的渲染行为。

poi-tl默认的行为会清空标签,如果希望保留标签:

builder.setValidErrorHandler(new DiscardHandler());

如果希望执行严格的校验,直接抛出异常:

builder.setValidErrorHandler(new AbortHandler());

8.模板生成模板

模板引擎不仅仅可以生成文档,也可以生成新的模板,比如我们把原先的一个模板标签分成两个模板标签:

put("title", "{{title}}\n{{subtitle}}");
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值