2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

Poi-tl Documentation(JAVA處理WORD)

 hncdman 2022-05-20 發(fā)布于湖南

poi-tl(poi template language)是Word模板引擎,使用Word模板和數(shù)據(jù)創(chuàng)建很棒的Word文檔。

在文檔的任何地方做任何事情(Do Anything Anywhere)是poi-tl的星辰大海。

1. License

Apache License 2.0

2. 源碼

GitHub

3. Why poi-tl方案移植性功能性易用性

Poi-tl

Java跨平臺

Word模板引擎,基于Apache POI,提供更友好的API

低代碼,準(zhǔn)備文檔模板和數(shù)據(jù)即可

Apache POI

Java跨平臺

Apache項目,封裝了常見的文檔操作,也可以操作底層XML結(jié)構(gòu)

文檔不全,這里有一個教程:Apache POI Word快速入門

Freemarker

XML跨平臺

僅支持文本,很大的局限性

不推薦,XML結(jié)構(gòu)的代碼幾乎無法維護

OpenOffice

部署OpenOffice,移植性較差

-

需要了解OpenOffice的API

HTML瀏覽器導(dǎo)出

依賴瀏覽器的實現(xiàn),移植性較差

HTML不能很好的兼容Word的格式,樣式糟糕

-

Jacob、winlib

Windows平臺

-

復(fù)雜,完全不推薦使用

poi-tl是一個基于Apache POI的Word模板引擎,也是一個免費開源的Java類庫,你可以非常方便的加入到你的項目中,并且擁有著讓人喜悅的特性。Word模板引擎功能描述

文本

將標(biāo)簽渲染為文本

圖片

將標(biāo)簽渲染為圖片

表格

將標(biāo)簽渲染為表格

列表

將標(biāo)簽渲染為列表

圖表

條形圖(3D條形圖)、柱形圖(3D柱形圖)、面積圖(3D面積圖)、折線圖(3D折線圖)、雷達圖、餅圖(3D餅圖)、散點圖等圖表渲染

If Condition判斷

根據(jù)條件隱藏或者顯示某些文檔內(nèi)容(包括文本、段落、圖片、表格、列表、圖表等)

Foreach Loop循環(huán)

根據(jù)集合循環(huán)某些文檔內(nèi)容(包括文本、段落、圖片、表格、列表、圖表等)

Loop表格行

循環(huán)復(fù)制渲染表格的某一行

Loop表格列

循環(huán)復(fù)制渲染表格的某一列

Loop有序列表

支持有序列表的循環(huán),同時支持多級列表

Highlight代碼高亮

word中代碼塊高亮展示,支持26種語言和上百種著色樣式

Markdown

將Markdown渲染為word文檔

Word批注

完整的批注功能,創(chuàng)建批注、修改批注等

Word附件

Word中插入附件

SDT內(nèi)容控件

內(nèi)容控件內(nèi)標(biāo)簽支持

Textbox文本框

文本框內(nèi)標(biāo)簽支持

圖片替換

將原有圖片替換成另一張圖片

書簽、錨點、超鏈接

支持設(shè)置書簽,文檔內(nèi)錨點和超鏈接功能

Expression Language

完全支持SpringEL表達式,可以擴展更多的表達式:OGNL, MVEL…

樣式

模板即樣式,同時代碼也可以設(shè)置樣式

模板嵌套

模板包含子模板,子模板再包含子模板

合并

Word合并Merge,也可以在指定位置進行合并

用戶自定義函數(shù)(插件)

插件化設(shè)計,在文檔任何位置執(zhí)行函數(shù)

4. 版本

Apache POI已經(jīng)進入5.0.0+時代,如果你仍希望使用低版本的Apache POI,請查閱歷史版本。

當(dāng)前版本 1.12.0 Documentation,Apache POI5.2.2+,JDK1.8+

1.11.x Documentation,Apache POI5.1.0+,JDK1.8+

1.10.x Documentation,Apache POI4.1.2,JDK1.8+

1.10.3 Documentation,Apache POI4.1.2,JDK1.8+

1.9.x Documentation,Apache POI4.1.2,JDK1.8+

1.8.x Documentation,Apache POI4.1.2,JDK1.8+

1.7.x Documentation,Apache POI4.0.0+,JDK1.8+

1.6.x Documentation,Apache POI4.0.0+,JDK1.8+

1.5.x Documentation,Apache POI3.16+,JDK1.6+

V1.12.0版本作了一個不兼容的改動,升級的時候需要注意:

重構(gòu)了PictureRenderData,改為抽象類,建議使用Pictures工廠方法來創(chuàng)建圖片數(shù)據(jù)

5. Getting Started

5.1. Maven  com.deepoove  poi-tl  1.12.0

5.2. Gradleimplementation 'com.deepoove:poi-tl:1.12.0'

5.3. 2分鐘快速入門

新建Word文檔template.docx,包含標(biāo)簽 {{title}}

template.docx

{{title}}

代碼示例XWPFTemplate template = XWPFTemplate.compile("template.docx").render(  new HashMap(){{     put("title", "Hi, poi-tl Word模板引擎"); }});  template.writeAndClose(new FileOutputStream("output.docx"));

compile 編譯模板

render 渲染數(shù)據(jù)

write 輸出到流

TDO模式:Template + data-model = output

output.docx

Hi, poi-tl Word模板引擎

5.4. Template:模板

模板是Docx格式的Word文檔,你可以使用Microsoft office、WPS Office、Pages等任何你喜歡的軟件制作模板,也可以使用Apache POI代碼來生成模板。

所有的標(biāo)簽都是以{{開頭,以}}結(jié)尾,標(biāo)簽可以出現(xiàn)在任何位置,包括頁眉,頁腳,表格內(nèi)部,文本框等,表格布局可以設(shè)計出很多優(yōu)秀專業(yè)的文檔,推薦使用表格布局。

poi-tl模板遵循“所見即所得”的設(shè)計,模板和標(biāo)簽的樣式會被完全保留。

5.5. Data-model:數(shù)據(jù)

數(shù)據(jù)類似于哈?;蛘咦值?,可以是Map結(jié)構(gòu)(key是標(biāo)簽名稱):Map data = new HashMap<>(); data.put("name", "Sayi"); data.put("start_time", "2019-08-04");

可以是對象(屬性名是標(biāo)簽名稱):public class Data {  private String name;  private String startTime;  private Author author; }

數(shù)據(jù)可以是樹結(jié)構(gòu),每級之間用點來分隔開,比如{{author.name}}標(biāo)簽對應(yīng)的數(shù)據(jù)是author對象的name屬性值。

FreeMarker、Velocity文本模板中可以通過三個標(biāo)簽設(shè)置圖片路徑、寬和高:

但是Word模板不是由簡單的文本表示,所以在渲染圖片、表格等元素時提供了數(shù)據(jù)模型,它們都實現(xiàn)了接口RenderData,比如圖片數(shù)據(jù)模型PictureRenderData包含圖片路徑、寬、高三個屬性。

5.6. Output:輸出

以流的方式進行輸出:template.write(OutputStream stream);

可以寫到任意輸出流中,比如文件流:template.write(new FileOutputStream("output.docx"));

比如網(wǎng)絡(luò)流:response.setContentType("application/octet-stream"); response.setHeader("Content-disposition","attachment;filename=\""+"out_template.docx"+"\"");// HttpServletResponse responseOutputStream out = response.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(out); template.write(bos); bos.flush(); out.flush(); PoitlIOUtils.closeQuietlyMulti(template, bos, out);

最后不要忘記關(guān)閉這些流。

6. 標(biāo)簽

poi-tl是一種無邏輯「logic-less」的模板引擎,沒有復(fù)雜的控制結(jié)構(gòu)和變量賦值,只有標(biāo)簽。標(biāo)簽由前后兩個大括號組成,{{title}}是標(biāo)簽,{{?title}}也是標(biāo)簽,title是這個標(biāo)簽的名稱,問號標(biāo)識了標(biāo)簽類型,接下來我們來看看有哪些默認標(biāo)簽類型(用戶可以創(chuàng)建新的標(biāo)簽類型,這屬于更高級的話題)。

6.1. 文本

{{var}}

數(shù)據(jù)模型:

String :文本

TextRenderData :有樣式的文本

HyperlinkTextRenderData :超鏈接和錨點文本

Object :調(diào)用 toString() 方法轉(zhuǎn)化為文本

代碼示例put("name", "Sayi"); put("author", new TextRenderData("000000", "Sayi")); put("link", new HyperlinkTextRenderData("website", "http://")); put("anchor", new HyperlinkTextRenderData("anchortxt", "anchor:appendix1"));

除了new操作符,還提供了更加優(yōu)雅的工廠 Texts 和鏈?zhǔn)秸{(diào)用的方式輕松構(gòu)建文本模型。

鏈?zhǔn)酱a示例put("author", Texts.of("Sayi").color("000000").create()); put("link", Texts.of("website").link("http://").create()); put("anchor", Texts.of("anchortxt").anchor("appendix1").create());

所見即所得,標(biāo)簽的樣式會應(yīng)用到替換后的文本上,也可以通過代碼設(shè)定文本的樣式。

TextRenderData的結(jié)構(gòu)體{  "text": "Sayi",  "style": {    "strike": false,      "bold": true,      "italic": false,      "color": "00FF00",      "underLine": false,      "fontFamily": "微軟雅黑",      "fontSize": 12,      "highlightColor": "green",      "vertAlign": "superscript",      "characterSpacing" : 20    } }

刪除線

粗體

斜體

顏色

下劃線

字體

字號

背景高亮色

上標(biāo)或者下標(biāo)

間距

文本換行使用 \n 字符。

6.2. 圖片

圖片標(biāo)簽以@開始:{{@var}}

數(shù)據(jù)模型:

String :圖片url或者本地路徑,默認使用圖片自身尺寸

PictureRenderData

ByteArrayPictureRenderData

FilePictureRenderData

UrlPictureRenderData

推薦使用工廠 Pictures 構(gòu)建圖片模型。

代碼示例// 指定圖片路徑put("image", "logo.png");// svg圖片put("svg", "https://img./badge/jdk-1.6%2B-orange.svg");// 設(shè)置圖片寬高put("image1", Pictures.ofLocal("logo.png").size(120, 120).create());// 圖片流put("streamImg", Pictures.ofStream(new FileInputStream("logo.jpeg"), PictureType.JPEG)   .size(100, 120).create());// 網(wǎng)絡(luò)圖片(注意網(wǎng)絡(luò)耗時對系統(tǒng)可能的性能影響)put("urlImg", Pictures.ofUrl("http:///images/icecream.png")   .size(100, 100).create());// java圖片put("buffered", Pictures.ofBufferedImage(bufferImage, PictureType.PNG)   .size(100, 100).create());

圖片支持BufferedImage,這意味著我們可以利用Java生成圖表插入到word文檔中。

FilePictureRenderData的結(jié)構(gòu)體{  "pictureType" : "PNG",    "path": "logo.png",    "pictureStyle": {    "width": 100,      "height": 100    },  "altMeta": "圖片不存在" }

圖片類型

圖片路徑

寬度,單位是像素

高度,單位是像素

當(dāng)無法獲取圖片時展示的文字

6.3. 表格

表格標(biāo)簽以#開始:{{#var}}

數(shù)據(jù)模型:

TableRenderData

推薦使用工廠 Tables 、 Rows 和 Cells 構(gòu)建表格模型。

Example 1. 基礎(chǔ)表格示例// 一個2行2列的表格put("table0", Tables.of(new String[][] {                new String[] { "00", "01" },                new String[] { "10", "11" }             }).border(BorderStyle.DEFAULT).create());

table simple

Example 2. 表格樣式示例// 第0行居中且背景為藍色的表格RowRenderData row0 = Rows.of("姓名", "學(xué)歷").textColor("FFFFFF")       .bgColor("4472C4").center().create(); RowRenderData row1 = Rows.create("李四", "博士"); put("table1", Tables.create(row0, row1));

table header

Example 3. 表格合并示例// 合并第1行所有單元格的表格RowRenderData row0 = Rows.of("列0", "列1", "列2").center().bgColor("4472C4").create(); RowRenderData row1 = Rows.create("沒有數(shù)據(jù)", 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());

table merge

TableRenderData表格模型在單元格內(nèi)可以展示文本和圖片,同時也可以指定表格樣式、行樣式和單元格樣式,而且在N行N列渲染完成后可以應(yīng)用單元格合并規(guī)則 MergeCellRule ,從而實現(xiàn)更復(fù)雜的表格。

TableRenderData的結(jié)構(gòu)體{  "rows": [      {      "cells": [          {          "paragraphs": [              {              "contents": [                 {                   [TextRenderData]                  },                 {                   [PictureRenderData]                  }               ],              "paragraphStyle": null              }           ],          "cellStyle": {              "backgroundColor": "00000",            "vertAlign": "CENTER"           }         }       ],      "rowStyle": {          "height": 2.0f       }     }   ],  "tableStyle": {      "width": 14.63f,      "colWidths": null   },  "mergeRule": {      "mapping": {      "0-0": "1-2"     }   } }

行數(shù)據(jù)

單元格數(shù)據(jù)

單元格內(nèi)段落

單元格內(nèi)文本

單元格內(nèi)圖片

單元格內(nèi)段落文本的樣式:對齊

單元格樣式:垂直對齊方式,背景色

行樣式:行高(單位cm)

表格樣式:表格對齊、邊框樣式

表格寬度(單位cm),表格的最大寬度 = 頁面寬度 - 頁邊距寬度 * 2,頁面寬度為A4(20.99 * 29.6,頁邊距為3.18 * 2.54)的文檔最大表格寬度14.63cm。

單元格合并規(guī)則,比如第0行第0列至第1行第2列單元格合并

產(chǎn)品需求中表格的布局和樣式可能很復(fù)雜,可以嘗試一些已有表格插件來解決,參見更多插件列表。

我們也可以編寫插件,完全由自己生成整個表格,前提是需要熟悉Apache POI XWPFTable相關(guān)API,但是自由度最高:參見 開發(fā)一個插件。

6.4. 列表

列表標(biāo)簽以*開始:{{*var}}

數(shù)據(jù)模型:

List

NumberingRenderData

推薦使用工廠 Numberings 構(gòu)建列表模型。

代碼示例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.

NumberingRenderData可以創(chuàng)建多級列表,但是推薦使用區(qū)塊對:區(qū)塊對的循環(huán)功能可以很好的循環(huán)列表,并且保持有序列表編號有序。

6.5. 區(qū)塊對

區(qū)塊對由前后兩個標(biāo)簽組成,開始標(biāo)簽以?標(biāo)識,結(jié)束標(biāo)簽以/標(biāo)識:{{?sections}}{{/sections}}

區(qū)塊對開始和結(jié)束標(biāo)簽中間可以包含多個圖片、表格、段落、列表、圖表等,開始和結(jié)束標(biāo)簽可以跨多個段落,也可以在同一個段落,但是如果在表格中使用區(qū)塊對,開始和結(jié)束標(biāo)簽必須在同一個單元格內(nèi),因為跨多個單元格的渲染行為是未知的。

區(qū)塊對在處理一系列文檔元素的時候非常有用,位于區(qū)塊對中的文檔元素可以被渲染零次,一次或N次,這取決于區(qū)塊對的取值。

False或空集合

隱西藏塊中的所有文檔元素

非False且不是集合

顯示區(qū)塊中的文檔元素,渲染一次

非空集合

根據(jù)集合的大小,循環(huán)渲染區(qū)塊中的文檔元素

集合是根據(jù)值的類型是否實現(xiàn)了 Iterable 接口來判斷。

6.5.1. False或空集合

如果區(qū)塊對的值是 null 、false 或者空的集合,位于區(qū)塊中的所有文檔元素將不會顯示,這就等同于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!

6.5.2. 非False且不是集合

如果區(qū)塊對的值不為 null 、 false ,且不是集合,位于區(qū)塊中的所有文檔元素會被渲染一次,這就等同于if語句的條件為 true。

data-model{  "person": { "name": "Sayi" } }

template.docx

{{?person}}

Hi {{name}}!

{{/person}}

output.docx

Hi Sayi!

區(qū)塊對中標(biāo)簽的作用域會被限定在當(dāng)前區(qū)塊對內(nèi),當(dāng)且僅當(dāng)區(qū)塊對的值是boolean類型且為true時,這些標(biāo)簽作用域才不會改變。

6.5.3. 非空集合

如果區(qū)塊對的值是一個非空集合,區(qū)塊中的文檔元素會被迭代渲染一次或者N次,這取決于集合的大小,類似于foreach語法。

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

template.docx

{{?songs}}

{{name}}

{{/songs}}

output.docx

Memories

Sugar

Last Dance

循環(huán)內(nèi)置變量

在循環(huán)中提供了一些內(nèi)置變量,這些內(nèi)置變量只能用于區(qū)塊對中。變量類型說明

_index

int

返回當(dāng)前迭代從0開始的索引

_is_first

boolean

辨別循環(huán)項是否是當(dāng)前迭代的第一項。

_is_last

boolean

辨別循環(huán)項是否是當(dāng)前迭代的最后一項。

_has_next

boolean

辨別循環(huán)項是否是有下一項。

_is_even_item

boolean

辨別循環(huán)項是否是當(dāng)前迭代間隔1的奇數(shù)項。

_is_odd_item

boolean

辨別循環(huán)項是否是當(dāng)前迭代間隔1的偶數(shù)項。

#this

object

引用當(dāng)前對象,由于#和已有表格標(biāo)簽標(biāo)識沖突,所以在文本標(biāo)簽中需要使用=號標(biāo)識來輸出文本。

示例數(shù)據(jù):{  "produces": [    "application/json",    "application/xml"   ] }

template.docx(注意:如果標(biāo)簽內(nèi)要使用運算符,需要開啟Spring表達式):{{?produces}} {{_index + 1}}. {{=#this}} {{/produces}}

output.docx:1. application/json 2. application/xml

6.6. 嵌套

嵌套又稱為導(dǎo)入、包含或者合并,以+標(biāo)識:{{+var}}

數(shù)據(jù)模型:

DocxRenderData

推薦使用工廠 Includes 構(gòu)建嵌套模型。

代碼示例class AddrModel {  private String addr;  public AddrModel(String addr) {    this.addr = addr;   }  // Getter/Setter} List subData = new ArrayList<>(); subData.add(new AddrModel("Hangzhou,China")); subData.add(new AddrModel("Shanghai,China")); put("nested", Includes.ofLocal("sub.docx").setRenderModel(subData).create());

主模板包含嵌套標(biāo)簽{{+nested}}

sub.docx是一個包含了{{addr}}的子模板,使用subData集合渲染后合并到主模板

7. 引用標(biāo)簽

引用標(biāo)簽是一種特殊位置的特殊標(biāo)簽,提供了直接引用文檔中的元素句柄的能力,這個重要的特性在我們只想改變文檔中某個元素極小一部分樣式和屬性的時候特別有用,因為其余樣式和屬性都可以在模板中預(yù)置好,真正的所見即所得。

7.1. 圖片

引用圖片標(biāo)簽是一個文本:{{var}},標(biāo)簽位置在:設(shè)置圖片格式—可選文字—標(biāo)題或者說明(新版本Microsoft Office標(biāo)簽位置在:編輯替換文字-替換文字)。

ref2

引用圖片標(biāo)簽只會替換圖片而不會改變圖片尺寸和布局,數(shù)據(jù)模型和圖片標(biāo)簽一致:PictureRenderData 。

代碼示例put("img", Pictures.ofLocal("sayi.png").create());

7.2. 多系列圖表

多系列圖表指的是條形圖(3D條形圖)、柱形圖(3D柱形圖)、面積圖(3D面積圖)、折線圖(3D折線圖)、雷達圖、散點圖等。

多系列圖表的標(biāo)簽是一個文本:{{var}},標(biāo)簽位置在:圖表區(qū)格式—可選文字—標(biāo)題(新版本Microsoft Office標(biāo)簽位置在:編輯替換文字-替換文字)。

chartref

數(shù)據(jù)模型:

ChartMultiSeriesRenderData

推薦使用工廠 Charts 構(gòu)建圖表模型。

代碼示例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);

新的圖表系列數(shù)據(jù)會完全替換原有圖表數(shù)據(jù),而原有圖表的樣式都會被保留。

ChartMultiSeriesRenderData的結(jié)構(gòu)體{  "chartTitle": "ChartTitle",    "categories": [      "中文", "English"   ],  "seriesDatas": [      {      "name": "countries",        "values": [          15, 6       ]     },     {      "name": "speakers",      "values": [        223, 119       ]     }   ] }

圖表標(biāo)題

種類

所有系列

當(dāng)前系列名稱

當(dāng)前系列對應(yīng)每個種類的值

7.3. 單系列圖表

單系列圖表指的是餅圖(3D餅圖)、圓環(huán)圖等。

單系列圖表的標(biāo)簽是一個文本:{{var}},標(biāo)簽位置在:圖表區(qū)格式—可選文字—標(biāo)題(新版本Microsoft Office標(biāo)簽位置在:編輯替換文字-替換文字)。

piechartref

數(shù)據(jù)模型:

ChartSingleSeriesRenderData

推薦使用工廠 Charts 構(gòu)建圖表模型。

代碼示例ChartSingleSeriesRenderData pie = Charts                 .ofSingleSeries("ChartTitle", new String[] { "美國", "中國" })                 .series("countries", new Integer[] { 9826675, 9596961 })                 .create(); put("pieChart", pie);

ChartSingleSeriesRenderData的結(jié)構(gòu)體{  "chartTitle": "ChartTitle",    "categories": [      "美國",    "中國"   ],  "seriesData": {      "name": "countries",      "values": [        9826675,      9596961     ]   } }

圖表標(biāo)題

種類

單系列

單系列名稱

單系列對應(yīng)每個種類的值

7.4. 組合圖表

組合圖表指的是由多系列圖表(柱形圖、折線圖、面積圖)組合而成的圖表。

組合圖表的標(biāo)簽是一個文本:{{var}},標(biāo)簽位置在:圖表區(qū)格式—可選文字—標(biāo)題(新版本Microsoft Office標(biāo)簽位置在:編輯替換文字-替換文字)。

chart combo

同多系列圖表 ChartMultiSeriesRenderData 數(shù)據(jù)模型。

代碼示例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的結(jié)構(gòu)體{  "chartTitle": "MyChart",    "categories": [      "中文", "English"   ],  "seriesDatas": [      {      "name": "countries",        "comboType": "BAR",        "values": [          15, 6       ]     },     {      "name": "speakers",      "comboType": "LINE",      "values": [        223, 119       ]     }   ] }

圖表標(biāo)題

種類

所有系列

當(dāng)前系列名稱

當(dāng)前系列的圖表類型comboType:柱形圖BAR、折線圖LINE、面積圖AREA

當(dāng)前系列對應(yīng)每個種類的值

8. 配置

poi-tl提供了類 Configure 來配置常用的設(shè)置,使用方式如下:ConfigureBuilder builder = Configure.builder(); XWPFTemplate.compile("template.docx", builder.buid());

8.1. 前后綴

我一直使用 {{}} 的方式來致敬Google CTemplate,如果你更偏愛freemarker ${} 的方式:builder.buildGramer("${", "}");

8.2. 標(biāo)簽類型

默認的圖片標(biāo)簽是以@開始,如果你希望使用%開始作為圖片標(biāo)簽:builder.addPlugin('%', new PictureRenderPolicy());

如果你不是很喜歡默認的標(biāo)簽標(biāo)識類型,你也可以自由更改:builder.addPlugin('@', new TableRenderPolicy()); builder.addPlugin('#', new PictureRenderPolicy());

這樣{{@var}}就變成了表格標(biāo)簽,{{#var}}變成了圖片標(biāo)簽,雖然不建議改變默認標(biāo)簽標(biāo)識,但是從中可以看到poi-tl插件的靈活度,在插件章節(jié)中我們將會看到如何自定義自己的標(biāo)簽。

8.3. 標(biāo)簽正則

標(biāo)簽?zāi)J支持中文、字母、數(shù)字、下劃線的組合,我們可以通過正則表達式來配置標(biāo)簽的規(guī)則,比如不允許中文:builder.buildGrammerRegex("[\\w]+(\\.[\\w]+)*");

比如允許除了標(biāo)簽前后綴外的任意字符:builder.buildGrammerRegex(RegexUtils.createGeneral("{{", "}}"));

8.4. 計算標(biāo)簽值

計算標(biāo)簽值是指如何在數(shù)據(jù)模型中索引標(biāo)簽Key的值,可以完全自定義獲取標(biāo)簽值的方式。builder.setRenderDataComputeFactory(new RenderDataComputeFactory());

RenderDataComputeFactory是一個抽象工廠,你可以定義自己的工廠提供標(biāo)簽表達式計算接口 RenderDataCompute 的實現(xiàn)。

我們可以通過此方式支持任何的表達式引擎,Spring表達式正是通過 SpELRenderDataCompute 實現(xiàn)。

8.5. Spring表達式

Spring Expression Language 是一個強大的表達式語言,支持在運行時查詢和操作對象圖,可作為獨立組件使用,需要引入相應(yīng)的依賴:  org.springframework  spring-expression  5.3.18

為了在模板標(biāo)簽中使用SpringEL表達式,需要將標(biāo)簽配置為SpringEL模式:builder.useSpringEL();

8.5.1. 基本使用

關(guān)于SpringEL的寫法可以參見官方文檔,下面給出一些典型的示例。{{name}} {{name.toUpperCase()}} {{name == 'poi-tl'}} {{empty?:'這個字段為空'}} {{sex ? '男' : '女'}} {{new java.text.SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(time)}} {{price/10000 + '萬元'}} {{dogs[0].name}} {{localDate.format(T(java.time.format.DateTimeFormatter).ofPattern('yyyy年MM月dd日'))}}

類方法調(diào)用,轉(zhuǎn)大寫

判斷條件

三目運算符

類方法調(diào)用,時間格式化

運算符

數(shù)組列表使用下標(biāo)訪問

使用靜態(tài)類方法

8.5.2. SpringEL作為區(qū)塊對的條件

Spring表達式與區(qū)塊對結(jié)合可以實現(xiàn)更強大的功能,示例如下:

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時區(qū)塊對的結(jié)束標(biāo)簽可以是:{{/}}。

8.6. 數(shù)據(jù)模型序列化

數(shù)據(jù)模型支持JSON字符串序列化,可以方便的構(gòu)造遠程HTTP或者RPC服務(wù),需要引入相應(yīng)依賴: com.deepoove poi-tl-jsonmodel-support 1.0.0

然后配置數(shù)據(jù)模型前置轉(zhuǎn)化器即可:builder.addPreRenderDataCastor(new GsonPreRenderDataCastor());

8.7. 錯誤處理

poi-tl支持在發(fā)生錯誤的時候定制引擎的行為。

8.7.1. 標(biāo)簽無法被計算

標(biāo)簽無法被計算的場景有幾種,比如模板中引用了一個不存在的變量,或者級聯(lián)的前置結(jié)果不是一個哈希,如 {{author.name}} 中author的值為null,此時就無法計算name的值。

poi-tl可以在發(fā)生這種錯誤時對計算結(jié)果進行配置,默認會認為標(biāo)簽值為null。當(dāng)我們需要嚴格校驗?zāi)0迨欠裼腥藶槭д`時,可以拋出異常:builder.useDefaultEL(true);

注意的是,如果使用SpringEL表達式,可以通過參數(shù)來配置是否拋出異常:builder.useSpringEL(true);

8.7.2. 標(biāo)簽數(shù)據(jù)類型不合法

我們知道渲染圖片、表格等標(biāo)簽時對數(shù)據(jù)模型是有要求的,如果數(shù)據(jù)不合法(為NULL或者是一個錯誤的數(shù)據(jù)類型),可以配置模板標(biāo)簽的渲染行為。

poi-tl默認的行為會清空標(biāo)簽,如果希望對標(biāo)簽不作任何處理:builder.setValidErrorHandler(new DiscardHandler());

如果希望執(zhí)行嚴格的校驗,直接拋出異常:builder.setValidErrorHandler(new AbortHandler());

8.8. 模板生成模板

模板引擎不僅僅可以生成文檔,也可以生成新的模板,比如我們把原先的一個文本標(biāo)簽分成一個文本標(biāo)簽和一個表格標(biāo)簽:Configure config = Configure.builder().bind("title", new DocumentRenderPolicy()).build(); Map data = new HashMap<>(); DocumentRenderData document = Documents.of()         .addParagraph(Paragraphs.of("{{title}}").create())         .addParagraph(Paragraphs.of("{{#table}}").create())         .create(); data.put("title", document);

8.9. 無模板創(chuàng)建文檔

使用 XWPFTemplate.create 在無需模板的情況下創(chuàng)建文檔,可以充分利用poi-tl友好的API來生成文檔元素。String text = "this a paragraph"; DocumentRenderData data = Documents.of().addParagraph(Paragraphs.of(text).create()).create(); XWPFTemplate template = XWPFTemplate.create(data);

8.10. 日志

poi-tl使用slf4j作為日志門面,你可以自由選擇日志實現(xiàn),比如logback、log4j等。我們以logback為例:

首先在項目中添加logback依賴:  ch.qos.logback  logback-core  1.2.3  ch.qos.logback  logback-classic  1.2.3

然后配置logback.xml文件,可以配置日志級別和格式:            %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n                        

debug級別的日志會打印解析渲染過程中的信息,有利于程序調(diào)試,另外在模板引擎執(zhí)行結(jié)束后會打印耗時信息:

Successfully Render the template file in 13 millis

9. 插件

插件,又稱為自定義函數(shù),它允許用戶在模板標(biāo)簽位置處執(zhí)行預(yù)先定義好的函數(shù)。由于插件機制的存在,我們幾乎可以在模板的任何位置執(zhí)行任何操作。

插件是poi-tl的核心,默認的標(biāo)簽和引用標(biāo)簽都是通過插件加載。

9.1. 默認插件

poi-tl默認提供了八個策略插件,用來處理文本、圖片、列表、表格、文檔嵌套、引用圖片、引用多系列圖表、引用單系列圖表等:

TextRenderPolicy

PictureRenderPolicy

NumberingRenderPolicy

TableRenderPolicy

DocxRenderPolicy

MultiSeriesChartTemplateRenderPolicy

SingleSeriesChartTemplateRenderPolicy

DefaultPictureTemplateRenderPolicy

由于這八個插件如此通用,因此將這些插件注冊為不同的標(biāo)簽類型,從而搭建了poi-tl的標(biāo)簽體系,也構(gòu)筑了poi-tl高度自由的插件機制。

9.2. 開發(fā)一個插件

實現(xiàn)一個插件就是要告訴我們在模板的某個地方用某些數(shù)據(jù)做某些事情,我們可以通過實現(xiàn)RenderPolicy接口開發(fā)自己的插件:public interface RenderPolicy {  void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template);   }

ElementTemplate是當(dāng)前標(biāo)簽位置

data是數(shù)據(jù)模型

XWPFTemplate代表整個模板

接下來我們寫一個將標(biāo)簽替換為Hello, world的插件:public class HelloWorldRenderPolicy implements RenderPolicy {  @Override   public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {     XWPFRun run = ((RunTemplate) eleTemplate).getRun();      // String thing = String.valueOf(data);     String thing = "Hello, world";     run.setText(thing, 0);    } }

XWPFRun是Apache POI的類,表示當(dāng)前位置

渲染文本hello, world

poi-tl提供了抽象模板類 AbstractRenderPolicy ,它定義了一些骨架步驟并且將數(shù)據(jù)模型的校驗和渲染邏輯分開,使用泛型約束數(shù)據(jù)類型,讓插件開發(fā)起來更簡單,接下來我們再寫一個更復(fù)雜的插件,在模板標(biāo)簽位置完完全全使用代碼創(chuàng)建一個表格,這樣我們就可以隨心所欲的操作表格:public class CustomTableRenderPolicy extends AbstractRenderPolicy

{  @Override   protected void afterRender(RenderContext

context) {    // 清空標(biāo)簽     clearPlaceholder(context, true);   }  @Override   public void doRender(RenderContext

context) throws Exception {     XWPFRun run = context.getRun();     BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);    // 定義行列     int row = 10, col = 8;    // 插入表格     XWPFTable table = bodyContainer.insertNewTable(run, row, col);    // 表格寬度     TableTools.setWidth(table, UnitUtils.cm2Twips(14.63f) + "", null);    // 邊框和樣式     TableTools.borderTable(table, BorderStyle.DEFAULT);    // 1) 調(diào)用XWPFTable API操作表格     // 2) 調(diào)用TableRenderPolicy.Helper.renderRow方法快速方便的渲染一行數(shù)據(jù)     // 3) 調(diào)用TableTools類方法操作表格,比如合并單元格     // ......     TableTools.mergeCellsHorizonal(table, 0, 0, 7);     TableTools.mergeCellsVertically(table, 0, 1, 9);   } }

通過 bodyContainer.insertNewTable 在當(dāng)前標(biāo)簽位置插入表格,使用XWPFTable API來操作表格。

隨心所欲的意思是原則上Apache POI支持的操作,都可以在當(dāng)前標(biāo)簽位置進行渲染,Apache POI不支持的操作也可以通過直接操縱底層XML來實現(xiàn)。

9.3. 使用插件

插件開發(fā)好后,為了讓插件在某個標(biāo)簽處執(zhí)行,我們需要將插件與標(biāo)簽綁定。

9.3.1. 將插件應(yīng)用到標(biāo)簽

當(dāng)我們有個模板標(biāo)簽為 {{report}},默認是文本標(biāo)簽,如果希望在這個位置做些不一樣或者更復(fù)雜的事情,我們可以將插件應(yīng)用到這個模板標(biāo)簽:ConfigureBuilder builder = Configure.builder(); builder.bind("report", new CustomTableRenderPolicy());

此時,{{report}} 將不再是一個文本標(biāo)簽,而是一個自定義標(biāo)簽。

ConfigureBuilder采用了鏈?zhǔn)秸{(diào)用的方式,可以一次性設(shè)置多個標(biāo)簽的插件:builder.bind("report", new CustomTableRenderPolicy()).bind("name", new MyRenderPolicy());

9.3.2. 將插件注冊為新標(biāo)簽類型

當(dāng)開發(fā)的插件具有一定的通用能力就可以將其注冊為新的標(biāo)簽類型。比如增加%標(biāo)識:{{%var}},對應(yīng)自定義的渲染策略 HelloWorldRenderPolicy:builder.addPlugin('%', new HelloWorldRenderPolicy());

此時,{{%var}} 將成為一種新的標(biāo)簽類型,它的執(zhí)行函數(shù)是 HelloWorldRenderPolicy。

9.4. Plugin Example

接下來用一個完整的代碼示例向你展示 Do Anything Anywhere 的想法,它不使用任何poi-tl的默認插件,完全使用自定義函數(shù)完成。

插件是一個函數(shù),它的入?yún)⑹莂nywhere和anything,函數(shù)體就是do something。// where綁定policyConfigure config = Configure.builder().bind("sea", new AbstractRenderPolicy() {  @Override   public void doRender(RenderContext context) throws Exception {        // anywhere       XWPFRun where = context.getWhere();      // anything       String thing = context.getThing();      // do 文本       where.setText(thing, 0);   } }).bind("sea_img", new AbstractRenderPolicy() {  @Override   public void doRender(RenderContext context) throws Exception {        // anywhere delegate       WhereDelegate where = context.getWhereDelegate();      // any thing       String thing = context.getThing();      // do 圖片       FileInputStream stream = null;      try {           stream = new FileInputStream(thing);           where.addPicture(stream, XWPFDocument.PICTURE_TYPE_JPEG, 400, 450);       } finally {           IOUtils.closeQuietly(stream);       }      // clear       clearPlaceholder(context, false);   } }).bind("sea_feature", new AbstractRenderPolicy() {  @Override   public void doRender(RenderContext context) throws Exception {        // anywhere delegate       WhereDelegate where = context.getWhereDelegate();      // anything       List thing = context.getThing();      // do 列表       where.renderNumbering(Numberings.of(thing.toArray(new String[] {})).create());      // clear       clearPlaceholder(context, true);   } }).build();// 初始化where的數(shù)據(jù)HashMap args = new HashMap(); args.put("sea", "Hello, world!"); args.put("sea_img", "sea.jpg"); args.put("sea_feature", Arrays.asList("面朝大海春暖花開", "今朝有酒今朝醉")); args.put("sea_location", Arrays.asList("日落:日落山花紅四海", "花海:你想要的都在這里"));// 一行代碼XWPFTemplate.compile("sea.docx", config).render(args).writeToFile("out_sea.docx");

自定義文本插件

自定義圖片插件

自定義列表插件

10. 更多插件

10.1. 插件列表

除了八個通用的策略插件外,還內(nèi)置了一些非常有用的插件。

ParagraphRenderPolicy

渲染一個段落,可以包含不同樣式文本,圖片等

DocumentRenderPolicy

渲染整個word文檔

CommentRenderPolicy

完整的批注功能

示例-批注

AttachmentRenderPolicy

插入附件功能

示例-插入附件

LoopRowTableRenderPolicy

循環(huán)表格行,下文會詳細介紹

示例-表格行循環(huán)

LoopColumnTableRenderPolicy

循環(huán)表格列

示例-表格列循環(huán)

DynamicTableRenderPolicy

動態(tài)表格插件,允許直接操作表格對象

示例-動態(tài)表格

BookmarkRenderPolicy

書簽和錨點

示例-Swagger文檔

AbstractChartTemplateRenderPolicy

引用圖表插件,允許直接操作圖表對象

TOCRenderPolicy

Beta實驗功能:目錄,打開文檔時會提示更新域

同時有更多的獨立插件可以使用(需要引入對應(yīng)Maven依賴):

HighlightRenderPolicy

Word支持代碼高亮

示例-代碼高亮

MarkdownRenderPolicy

使用Markdown來渲染word

示例-Markdown

如果你寫了一個不錯的插件,歡迎分享。

10.2. 表格行循環(huán)

LoopRowTableRenderPolicy 是一個特定場景的插件,根據(jù)集合數(shù)據(jù)循環(huán)表格行。

template.docx

貨物明細和人工費在同一個表格中,貨物明細需要展示所有貨物,人工費需要展示所有費用。{{goods}} 是個標(biāo)準(zhǔn)的標(biāo)簽,將 {{goods}} 置于循環(huán)行的上一行,循環(huán)行設(shè)置要循環(huán)的標(biāo)簽和內(nèi)容,注意此時的標(biāo)簽應(yīng)該使用 [] ,以此來區(qū)別poi-tl的默認標(biāo)簽語法。同理,{{labors}} 也置于循環(huán)行的上一行。

example looptable template

代碼示例

{{goods}} 和 {{labors}} 標(biāo)簽對應(yīng)的數(shù)據(jù)分別是貨物集合和人工費集合,如果集合為空則會刪除循環(huán)行。class Goods {  private int count;  private String name;  private String desc;  private int discount;  private int tax;  private int price;  private int totalPrice;  // getter setter}class Labor {  private String category;  private int people;  private int price;  private int totalPrice;  // getter setter} List goods = new ArrayList<>(); List labors = new ArrayList<>();

接下來我們將插件應(yīng)用到這兩個標(biāo)簽。LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); Configure config = Configure.builder()         .bind("goods", policy).bind("labors", policy).build(); XWPFTemplate template = XWPFTemplate.compile(resource, config).render(  new HashMap() {{       put("goods", goods);       put("labors", labors);     }} );

綁定插件

output.docx

最終生成的文檔列出了所有貨物和人工費。

example looptable output

源碼參見 JUnit LoopRowTableRenderPolicyTest,如果希望模板標(biāo)簽和循環(huán)行在同一行而不是在上一行,可以使用 new LoopRowTableRenderPolicy(true) 來構(gòu)造插件。

10.3. 表格列循環(huán)

LoopColumnTableRenderPolicy 是一個特定場景的插件,根據(jù)集合數(shù)據(jù)循環(huán)表格列。要注意的是,由于文檔寬度有限,因此模板列必須設(shè)置寬度,所有循環(huán)列將平分模板列的寬度。

template.docx

LoopColumnTableRenderPolicy 循環(huán)列的使用方式和插件 LoopRowTableRenderPolicy 是一樣的,需要將占位標(biāo)簽放在循環(huán)列的前一列。

example loopcol template

代碼示例LoopColumnTableRenderPolicy policy = new LoopColumnTableRenderPolicy(); Configure config = Configure.builder().bind("goods", policy).build(); XWPFTemplate template = XWPFTemplate.compile(resource, config).render(  new HashMap() {{       put("goods", goods);     }} );

output.docx

最終生成的文檔列出了所有貨物和人工費。

example loopcol output

源碼參見 JUnit LoopColumnTableRenderPolicyTest

10.4. 動態(tài)表格

當(dāng)需求中的表格更加復(fù)雜的時候,我們完全可以設(shè)計好那些固定的部分,將需要動態(tài)渲染的部分單元格交給自定義模板渲染策略。poi-tl提供了抽象表格策略 DynamicTableRenderPolicy 來實現(xiàn)這樣的功能。public abstract class DynamicTableRenderPolicy implements RenderPolicy {  public abstract void render(XWPFTable table, Object data); }

template.docx

{{detail_table}}標(biāo)簽可以在表格內(nèi)的任意單元格內(nèi),DynamicTableRenderPolicy會獲取XWPFTable對象進而獲得操作整個表格的能力。

dynamic

代碼示例

首先新建渲染策略DetailTablePolicy,繼承于抽象表格策略。public class DetailTablePolicy extends DynamicTableRenderPolicy {  // 貨品填充數(shù)據(jù)所在行數(shù)   int goodsStartRow = 2;  // 人工費填充數(shù)據(jù)所在行數(shù)   int laborsStartRow = 5;  @Override   public void render(XWPFTable table, Object data) throws Exception {    if (null == data) return;     DetailData detailData = (DetailData) data;    // 人工費     List labors = detailData.getLabors();    if (null != labors) {       table.removeRow(laborsStartRow);      // 循環(huán)插入行       for (int i = 0; i < labors.size(); i++) {         XWPFTableRow insertNewTableRow = table.insertNewTableRow(laborsStartRow);        for (int j = 0; j < 7; j++) insertNewTableRow.createCell();        // 合并單元格         TableTools.mergeCellsHorizonal(table, laborsStartRow, 0, 3);        // 單行渲染         TableRenderPolicy.Helper.renderRow(table.getRow(laborsStartRow), labors.get(i));       }     }    // 貨物     List goods = detailData.getGoods();    if (null != goods) {       table.removeRow(goodsStartRow);      for (int i = 0; i < goods.size(); i++) {         XWPFTableRow insertNewTableRow = table.insertNewTableRow(goodsStartRow);        for (int j = 0; j < 7; j++) insertNewTableRow.createCell();         TableRenderPolicy.Helper.renderRow(table.getRow(goodsStartRow), goods.get(i));       }     }   } }

然后將模板標(biāo)簽{{detail_table}}設(shè)置成此策略。Configure config = Configure.builder().bind("detail_table", new DetailTablePolicy()).build();

output.docx

最終生成的文檔列出了所有貨物和人工費。

dynamic output

源碼參見 JUnit PaymentExample

10.5. 批注

CommentRenderPolicy 是內(nèi)置插件,提供了對批注完整功能的支持。

數(shù)據(jù)模型:

CommentRenderData

代碼示例CommentRenderData comment = Comments.of("鵝")                 .signature("Sayi", "s", LocaleUtil.getLocaleCalendar())                 .comment("鵝,是一種動物")                 .create(); Map data = new HashMap<>(); data.put("comment", comment); Configure config = Configure.builder().bind("comment", new CommentRenderPolicy()).build(); XWPFTemplate.compile("comment_template.docx", config).render(data);

批注內(nèi)容

將批注插件和comment標(biāo)簽綁定

10.5.1. 示例

output.docx

批注中支持添加文字、圖片等文檔內(nèi)容。

example comment output

源碼參見 JUnit CommentRenderPolicyTest。

10.6. 插入附件

AttachmentRenderPolicy 是內(nèi)置插件,提供了插入附件功能的支持。

數(shù)據(jù)模型:

AttachmentRenderData

代碼示例AttachmentRenderData attach = Attachments.ofLocal("attachment.xlsx", AttachmentType.XLSX).create(); Map data = new HashMap<>(); data.put("attachment", attach); Configure config = Configure.builder().bind("attachment", new AttachmentRenderPolicy()).build(); XWPFTemplate.compile("attachment_template.docx", config).render(data);

附件文檔,Word或者Excel

綁定標(biāo)簽和附件插件

10.6.1. 示例

output.docx

文檔中插入Excel,雙擊圖標(biāo)打開附件。

example attach output

源碼參見 JUnit AttachmentRenderPolicyTest。

10.7. 代碼高亮

HighlightRenderPolicy 插件對Word代碼塊進行高亮展示。

10.7.1. 引入依賴:  com.deepoove  poi-tl-plugin-highlight  1.0.0

10.7.2. 快速開始

數(shù)據(jù)模型:

HighlightRenderData

代碼示例HighlightRenderData code = new HighlightRenderData(); code.setCode("/**\n"         + " * @author John Smith \n"         + "*/\n"         + "package l2f.gameserver.model;\n"         + "\n"         + "public abstract strictfp class L2Char extends L2Object {\n"         + "  public static final Short ERROR = 0x0001;\n"         + "\n"         + "  public void moveTo(int x, int y, int z) {\n"         + "    _ai = null;\n"         + "    log(\"Should not be called\");\n"         + "    if (1 > 5) { // wtf!?\n"         + "      return;\n"         + "    }\n"         + "  }\n"         + "}"); code.setLanguage("java"); code.setStyle(HighlightStyle.builder().withShowLine(true).withTheme("zenburn").build()); Map data = new HashMap<>(); data.put("code", code); Configure config = Configure.builder().bind("code", new HighlightRenderPolicy()).build(); XWPFTemplate.compile("highlight_template.docx", config).render(data);

代碼語言

設(shè)置主題樣式

將代碼高亮插件和code標(biāo)簽綁定

10.7.3. 示例

output.docx

示例展示了代碼高亮插件支持20多種編程語言和幾十種主題樣式。

highlight

源碼參見 JUnit HighlightRenderPolicyTest。

10.7.4. 常用語言支持

apache

bash

cpp

cs

css

diff

go

groovy

http

ini

java

javascript

json

makefile

markdown

objectivec

perl

php

python

ruby

scala

shell

sql

xml

yaml

10.7.5. 常用主題樣式

github

idea

zenburn

androidstudio

solarized- light

solarized- dark

xcode

vs

agate

darcula

dark

dracula

foundation

googlecode

monokai

mono- blue

far

gml

10.8. Markdown

MarkdownRenderPolicy 插件支持通過Markdown生成word文檔。

10.8.1. 引入依賴:  com.deepoove  poi-tl-plugin-markdown  1.0.3

10.8.2. 快速開始

數(shù)據(jù)模型:

MarkdownRenderData

代碼示例MarkdownRenderData code = new MarkdownRenderData(); code.setMarkdown(new String(Files.readAllBytes(Paths.get("README.md")))); code.setStyle(MarkdownStyle.newStyle()); Map data = new HashMap<>(); data.put("md", code); Configure config = Configure.builder().bind("md", new MarkdownRenderPolicy()).build(); XWPFTemplate.compile("markdown_template.docx", config).render(data);

定制markdown轉(zhuǎn)為word的樣式

將Markdown插件和md標(biāo)簽綁定

10.8.3. 示例

output.docx

通過Markdown插件將poi-tl根目錄下的README.md內(nèi)容轉(zhuǎn)為word文檔的結(jié)果示例:markdown.docx

example markdown output

源碼參見 JUnit MarkdownRenderPolicyTest。

11. 示例

接下來的示例采取三段式output+template+data-model來說明,首先直接展示生成后的文檔,然后一覽模板的樣子,最后我們對數(shù)據(jù)模型作個介紹。

11.1. 軟件說明文檔

output.docx

需要生成這樣的一份軟件說明書:擁有封面和頁眉,正文含有不同樣式的文本,還有表格,列表和圖片。poi_tl.docx

example poitl output1

template.docx

使用poi-tl標(biāo)簽制作模板,可以看到標(biāo)簽可以擁有樣式。

example poitl template1

這個示例向我們展示了poi-tl最基本的能力,它在模板標(biāo)簽位置,插入基本的數(shù)據(jù)模型,所見即所得。

源碼參見 JUnit XWPFTemplateTest

11.2. 付款通知書

output.docx

需要生成這樣的一份流行的通知書:大部分數(shù)據(jù)是由表格構(gòu)成的,需要創(chuàng)建一個訂單的表格(圖中第一個表格),還需要在一個已有表格中,填充貨物明細和人工費數(shù)據(jù)(圖中第二個表格)。下載最終生成的文件payment.docx

example payment output

template.docx

使用{{#order}}生成poi-tl提供的默認樣式的表格,設(shè)置{{detail_table}}為自定義模板渲染策略(繼承抽象表格策略DynamicTableRenderPolicy),自定義已有表格中部分單元格的渲染。

example payment template

這個示例向我們展示了poi-tl在表格操作上的一些思考。示例中貨物明細和人工費的表格就是一個相當(dāng)復(fù)雜的表格,貨物明細是由7列組成,行數(shù)不定,人工費是由4列組成,行數(shù)不定。

這個示例主要用來展示DynamicTableRenderPolicy的用法,貨物明細和人工費僅僅是循環(huán)渲染表格行,使用LoopRowTableRenderPolicy 插件會更方便。

源碼參見 JUnit PaymentExample

11.3. 目標(biāo)制定

output.docx

需要制定一份OKR目標(biāo)計劃,業(yè)務(wù)目標(biāo)和管理目標(biāo)使用表格呈現(xiàn),數(shù)量不等。下載最終生成的文件okr.docx

example okr output

template.docx

將表格放到區(qū)塊對中,當(dāng)區(qū)塊對取值為空集合或者null則不會展示目標(biāo)表格,當(dāng)區(qū)塊對是一個非空集合則循環(huán)展示表格。

example okr template

這個示例展示了區(qū)塊對的功能,它可以對文檔內(nèi)容進行循環(huán)渲染。

源碼參見 JUnit OKRExample

11.4. 野生動物現(xiàn)狀

output.docx

針對野生動物出具一份現(xiàn)狀的調(diào)查報告,野生動物種類不確定,調(diào)查報告包含圖片、文字和圖表。下載最終生成的文件animal.docx

example animal output

template.docx

不確定動物種類使用區(qū)塊對{{?animals}}的循環(huán)功能實現(xiàn),圖片和圖表如模板所示,使用引用標(biāo)簽,在可選文字標(biāo)題位置輸入標(biāo)簽。

example animal template

這個示例展示了區(qū)塊對的循環(huán)功能,以及如何在循環(huán)中使用引用圖片和引用圖表的功能。

源碼參見 JUnit AnimalExample

11.5. 證書獎狀

output.docx

頒發(fā)一張由特殊樣式圖片、姓名、日期構(gòu)成的證書獎狀。下載最終生成的文件certificate.docx

example certificate output

template.docx

圖片格式和布局由模板指定,圖片使用引用標(biāo)簽替換即可。

example certificate template

這個示例展示了引用圖片和文本框的功能。

源碼參見 JUnit CertificateExample

11.6. 個人簡歷

output.docx

需要生成這樣的一份個人簡歷:左側(cè)是個人的基本信息,技術(shù)棧是個典型的列表,右側(cè)是個人的工作經(jīng)歷,數(shù)量不定。下載最終生成的文件resume.docx

example resume output

11.6.1. 方案一:使用區(qū)塊對標(biāo)簽

template.docx

工作經(jīng)歷是一個循環(huán)顯示的內(nèi)容,我們使用區(qū)塊對標(biāo)簽{{?experiences}}{{/experiences}}。

example iterable resume template

源碼參見 JUnit Iterable ResumeExample

11.6.2. 方案二:使用嵌套標(biāo)簽

template.docx

工作經(jīng)歷可以使用嵌套標(biāo)簽,我們制作兩個模板,一套主模板簡歷.docx(下圖左側(cè)),一套為文檔模板segment.docx(下圖右側(cè))。

example resume template

看起來很復(fù)雜的簡歷,其實對于模版引擎來說,和普通的Word文檔沒有什么區(qū)別,我們只需要制作好一份簡歷,將需要替換的內(nèi)容用模版標(biāo)簽代替。

因為模版即樣式,模版引擎無需考慮樣式,只關(guān)心數(shù)據(jù),我們甚至可以制作10種不同樣式的簡歷模板,用同一份數(shù)據(jù)去渲染。

源碼參見 JUnit ResumeExample

11.7. Swagger文檔

output.docx

這是一份非常專業(yè)的Swagger Word文檔,樣式優(yōu)雅且有著清晰完整的文檔結(jié)構(gòu),API列表需要循環(huán)展示,接口的請求參數(shù)需要循環(huán)展示,接口的返回值需要循環(huán)展示,數(shù)據(jù)類型支持錨點到具體的模型,模型支持代碼塊高亮展示。下載最終生成的文件swagger.docx

example swagger output

example swagger output2

template.docx

使用區(qū)塊對標(biāo)簽完成所有循環(huán)功能,可以完美的支持有序和多級列表;表格使用 LoopRowTableRenderPolicy 插件的約定,可以非常方便的完成參數(shù)、返回值等表格的渲染;使用Spring表達式來支持豐富的條件判斷;代碼塊高亮使用 HighlightRenderPolicy 插件。

example swagger template1

example swagger template2

代碼示例SwaggerParser swaggerParser = new SwaggerParser(); Swagger swagger = swaggerParser.read("https://petstore./v2/swagger.json"); SwaggerView viewData = convert(swagger); LoopRowTableRenderPolicy LoopRowTableRenderPolicy = new LoopRowTableRenderPolicy(); Configure config = Configure.builder()         .bind("parameters", hackLoopTableRenderPolicy)         .bind("responses", hackLoopTableRenderPolicy)         .bind("properties", hackLoopTableRenderPolicy)         .bind("definitionCode", new HighlightRenderPolicy())         .useSpringEL()         .build(); XWPFTemplate template = XWPFTemplate.compile("swagger.docx", config).render(viewData); template.writeToFile("out_example_swagger.docx");

解析Swagger.json

配置模板引擎

Swagger導(dǎo)出Word

沒錯,一切都是如此簡潔:簡潔的導(dǎo)出代碼 ,簡潔的Word模板,甚至生成的Swagger文檔都看起來那么簡潔,愿一切如你所愿。

源碼參見 JUnit SwaggerToWordExample

12. 打賞個小費

poi-tl開源的初衷是希望讓所有有需要的人享受Word模板引擎的功能,而且它可能是Java中最好的Word模板引擎。

如果你覺得它節(jié)省了你的時間,給你帶來了方便和靈感,或者認同這個開源項目,可以為我的付出打賞點小費哦(在備注留言中附上你的微信號,讓我可以加個好友,說句感謝??)。

poi-tl是給你的禮物!

— Sayi

13. 常見問題

出現(xiàn)NoSuchMethodError 、ClassNotFoundException 、NoClassDefFoundError異常?

poi-tl依賴的apache-poi版本是5.2.2+,如果你的項目引用了低版本,請升級或刪除。

是否支持Android客戶端使用?

參考issue227。

有沒有HTML轉(zhuǎn)Word的插件?

參考issue219。

有沒有公式的插件?

參考issue27。

如何通過標(biāo)簽指定格式化函數(shù)?

Spring表達式,應(yīng)有盡有。

如何在一行中顯示不同樣式的文本?

可能你需要多個標(biāo)簽;或者使用區(qū)塊對,區(qū)塊對的集合數(shù)據(jù)是擁有不同樣式的TextRenderData,還可以考慮使用ParagraphRenderPolicy插件。

我不是很熟悉Apache POI,我該怎么編寫插件?

編寫插件還是需要熟悉下POI,你可以參考現(xiàn)有插件的源碼,或者Google下Apache POI的用法,這里有一個入門教程:Apache POI Word快速入門

Apache POI不支持的功能,我該怎么編寫插件?

Apache POI底層的組件也是直接操作XML的,你可以使用POI背后的組件。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多