Java poi-tl根據(jù)模版生成word文件并插入文字、圖片、表格、圖表
前言
本篇文章主要通過(guò)代碼案例的方式,展示 poi-tl 生成 docx 文件的一些常用操作,主要涵蓋以下內(nèi)容 :
- 插入文本字符(含樣式、超鏈接)
- 插入圖片
- 插入表格
- 引入標(biāo)簽(通過(guò)可選文字的方式,這種方式也可以實(shí)現(xiàn)插入圖片和插入表格)
當(dāng)然 poi-tl 官方也有很詳細(xì)的介紹,官網(wǎng)文檔地址:https://deepoove.com/poi-tl/
項(xiàng)目初始化【必讀】
項(xiàng)目創(chuàng)建好之后第一件事當(dāng)然是引入依賴(lài)?yán)病?/p>
下面是 maven 引入的依賴(lài),如果使用 Gradle 自行轉(zhuǎn)成 Gradle 依賴(lài)。
<!-- poi 依賴(lài) --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.5</version> </dependency> <!-- poi-tl --> <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.12.2</version> </dependency>
在 poi-tl 生成 docx 文件時(shí),先搞清楚三個(gè)問(wèn)題:
- 定義 docx 模板文件:要生成怎么樣的文件,自行創(chuàng)建一個(gè) docx 的模板文件
- 定義模板文件的數(shù)據(jù):向模板文件中,添加數(shù)據(jù)
- 生成文件位置:實(shí)際開(kāi)發(fā)中大多會(huì)通過(guò)網(wǎng)絡(luò)的方式傳遞,這里只展示生成在本地文件
本篇文章展示一些關(guān)鍵代碼,為了減少冗余,我們可以定義一個(gè)生成 docx 的工具類(lèi) PoitlUtils:
import com.deepoove.poi.XWPFTemplate;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/**
* @author 17279
*/
public class PoitlUtils {
/**
* @param templateData 生成模板文件所需的所有數(shù)據(jù)
* @param templateFilePath 模板文件路徑(這里讀取的是 resources 下的文件)
* @param outputFilePath 模板文件輸入的地址
*/
public static void generateWordFile(Map<String, Object> templateData, String templateFilePath, String outputFilePath) {
// 讀取模板文件
try (InputStream templateIn = PoitlUtils.class.getResourceAsStream(templateFilePath)) {
// 生成模板文件
XWPFTemplate template = XWPFTemplate.compile(templateIn).render(templateData);
template.writeAndClose(new FileOutputStream(outputFilePath));
// 這個(gè)目的是:生成文件之后調(diào)用 cmd 打開(kāi)本地文件,實(shí)際生產(chǎn)不需要該操作
// Runtime.getRuntime().exec(String.format("cmd /c %s", outputFilePath));
} catch (IOException e) {
e.printStackTrace();
}
}
}
這里使用的所有 docs 模板文件,我都存放在 resources 的目錄下。

插入文本
str_demo.docx 文件,文本使用 {{xxx}} 設(shè)置占位符:
{{str1}}
{{str2}}
{{str3}}
{{str4}}
{{?strArr1}}{{=#this}} {{/strArr1}}
案例代碼:
// 模板文件
String templateFilePath = "/word_template/str_demo.docx";
// 輸出文件
String outputFilePath = "D:/output.docx";
// 插入文本數(shù)據(jù)
Map<String, Object> templateData = new HashMap<String, Object>() {{
// 直接插入 String
put("str1", "直接插入 String");
// 插入含有樣式的文本
put("str2", Texts.of("插入含有樣式的文").color("ff0000").create());
// 插入含超鏈接的文本
put("str3", Texts.of("插入含有樣式的文").link("http://www.shijialeya.top/").create());
// 傳入一個(gè)對(duì)象
put("str4", Arrays.asList("鍵盤(pán)敲破", "工資過(guò)萬(wàn)"));
// 遍歷文本
put("strArr1", Arrays.asList("派大星", "瘸老板", "海綿寶寶", "章魚(yú)哥", "蟹老板"));
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);
文檔效果:

要注意 docx 文件上的 {{xxx}} xxx 的前后不要有空格,如果將外面的文字復(fù)制到 word 可能會(huì)自動(dòng)加空格。
插入圖片
img_demo.docx 文件,圖片通過(guò) {{@xxx}} 設(shè)置占位符:
{{@img1}}
{{@img2}}
{{@img3}}
{{@img4}}
{{?imgArr1}}{{@#this}} {{/imgArr1}}
案例代碼:
// 模板文件
String templateFilePath = "/word_template/img_demo.docx";
// 輸出文件
String outputFilePath = "D:/output.docx";
// 插入文本數(shù)據(jù)
Map<String, Object> templateData = new HashMap<String, Object>() {{
// 直接插入本地圖片(默認(rèn)圖片的寬度與文檔的寬度一致)
// put("img1", "C:/Users/17279/Pictures/head.jpg");
// 插入本地圖片,并設(shè)置圖片大小
put("img1", Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
// 通過(guò)流的形式寫(xiě)入圖片
put("img2", Pictures.ofStream(new FileInputStream("C:/Users/17279/Pictures/head.jpg"), PictureType.JPEG).size(150, 150).create());
// 寫(xiě)入網(wǎng)絡(luò)圖片
put("img3", Pictures.ofUrl("http://file.shijialeya.top/head.jpg", PictureType.JPEG).size(170, 170).create());
// 寫(xiě)入通過(guò) Java 生成的圖片
put("img4", Pictures.ofBufferedImage(new BufferedImage(190, 190, BufferedImage.TYPE_BYTE_GRAY), PictureType.PNG).size(190, 190).create());
// 遍歷圖片
put("imgArr1", new ArrayList<Object>() {{
add(Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
add(Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
add(Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
}});
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);
文檔效果:

插入表格
tab_demo.docx 文件,圖片通過(guò) {{#xxx}} 設(shè)置占位符:
{{#tab1}}
{{#tab2}}
{{#tab3}}
合同名稱(chēng) {{tab4.contractName}}
合同時(shí)間 {{tab4.contractDate}} 合同金額 {{tab4.money}}
合同公司 {{tab4.company}}

案例代碼:
// 模板文件
String templateFilePath = "/word_template/tab_demo.docx";
// 輸出文件
String outputFilePath = "D:/output.docx";
// 插入文本數(shù)據(jù)
Map<String, Object> templateData = new HashMap<String, Object>() {{
// 插入一個(gè)基礎(chǔ)表格
String[][] tabData1 = {
new String[]{"姓名", "性別", "年齡"},
new String[]{"派大星", "16", "男"},
new String[]{"章魚(yú)哥", "35", "男"}
};
put("tab1", Tables.of(tabData1).create());
// 插入一個(gè)含有樣式的表格
Tables.TableBuilder tabData2 = Tables
// 創(chuàng)建一個(gè)指定寬度的表格(docx 文檔的 80% 寬度)
.ofPercentWidth("80%")
// 表格設(shè)為水平居中
.center()
// 設(shè)置表格邊框
.border(BorderStyle.builder()
// 邊框樣式
.withType(XWPFTable.XWPFBorderType.DOUBLE)
// 邊框顏色
.withColor("ff0000")
// 邊框粗細(xì)(邊框?yàn)榫€條類(lèi)型才會(huì)有效)
.withSize(12)
.build()
);
tabData2.addRow(Rows.of("姓名", "性別", "年齡")
// 設(shè)置文字顏色
.textColor("FFFFFF")
// 設(shè)置對(duì)應(yīng)表格的背景顏色
.bgColor("4472C4")
// 文字居中
.center()
.create()
);
tabData2.addRow(Rows.of("派大星", "16", "男").create());
put("tab2", tabData2.create());
// 合并單元格
String[][] tabData3 = {
new String[]{"姓名", "性別", "年齡"},
new String[]{"派大星", "16", "男"},
new String[]{"章魚(yú)哥", "35", "男"},
new String[]{"共2人", null, null},
};
put("tab3", Tables.of(tabData3)
// 添加單元格合并規(guī)則
.mergeRule(MergeCellRule
.builder()
// [縱坐標(biāo), 橫坐標(biāo)] 索引從零開(kāi)始,合并 [3, 0] 到 [3, 2] 位置的表格
.map(MergeCellRule.Grid.of(3, 0), MergeCellRule.Grid.of(3, 2))
.build()
)
.create()
);
// 對(duì)應(yīng)格式一定的表格,直接采用字符串替換即可
put("tab4", new HashMap<String, Object>() {{
put("contractName", "第一季度財(cái)務(wù)報(bào)告");
put("contractDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
put("company", "xxx有限責(zé)任公司");
put("money", 10089.33);
}});
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);
文檔效果:

引入標(biāo)簽
插入圖片
上面也有插入圖片的方式,但是通過(guò)引入標(biāo)簽的方式插入圖片時(shí),可以先在 word 模板文件中提前編輯好圖片的樣式,通過(guò)替換圖片的方式,會(huì)保留原本設(shè)置好的樣式。
在 docx 模板文件中先插入一張圖片,并且調(diào)整好圖片的樣式,之后右鍵圖片選擇【查看可選文字】,在可選文字中通過(guò) {{xxx}} 的方式填寫(xiě)屬性名稱(chēng)。
【特別提醒】貌似 WPS 沒(méi)有可選文字的功能,不確定是不是 WPS 版本的原因,反正我沒(méi)找到可選文字。
因此我特地把 WPS 卸載之后換成了 Office 工具。

案例代碼:
// 模板文件
String templateFilePath = "/word_template/quote_demo01.docx";
// 輸出文件
String outputFilePath = "D:/output.docx";
// 插入文本數(shù)據(jù)
Map<String, Object> templateData = new HashMap<String, Object>() {{
// 直接插入本地圖片,這里會(huì)保留模板文件的圖片樣式
put("label1", Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);
文檔效果:

插入單系列圖表
單系列圖表指的是餅圖(3D餅圖)、圓環(huán)圖等。
同引入標(biāo)簽插入圖片一樣,在插入圖表的時(shí)候,需要在 docx 模板中創(chuàng)建一個(gè)單系列的圖表,設(shè)置好樣式,之后右鍵圖表選擇【查看可選文字】,在可選文字中通過(guò) {{xxx}} 的方式填寫(xiě)屬性名稱(chēng)。

案例代碼:
// 模板文件
String templateFilePath = "/word_template/quote_demo02.docx";
// 輸出文件
String outputFilePath = "D:/output.docx";
// 插入文本數(shù)據(jù)
Map<String, Object> templateData = new HashMap<String, Object>() {{
// 添加單系列圖表的表格數(shù)據(jù)
put("label2", Charts
.ofSingleSeries("商品類(lèi)型", new String[]{"電器類(lèi)", "數(shù)碼類(lèi)", "生活用品類(lèi)", "食品類(lèi)", "其他"})
.series("數(shù)量", new Integer[]{30, 8, 25, 11, 3})
.create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);
文檔效果:

插入多系列圖表
多系列圖表指的是條形圖(3D條形圖)、柱形圖(3D柱形圖)、面積圖(3D面積圖)、折線圖(3D折線圖)、雷達(dá)圖、散點(diǎn)圖等。
模板文件如下:

案例代碼:
// 模板文件
String templateFilePath = "/word_template/quote_demo03.docx";
// 輸出文件
String outputFilePath = "D:/output.docx";
// 插入文本數(shù)據(jù)
Map<String, Object> templateData = new HashMap<String, Object>() {{
// 添加單系列圖表的表格數(shù)據(jù)
put("label3", Charts
.ofMultiSeries("銷(xiāo)售額", new String[]{"第一季度", "第二季度", "第三季度", "第四季度"})
.addSeries("電器類(lèi)", new Integer[]{22, 25, 28, 25})
.addSeries("數(shù)碼類(lèi)", new Integer[]{5, 10, 8, 4})
.addSeries("其他", new Integer[]{30, 42, 22, 33})
.create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);
文檔效果:
插入組合圖表
組合圖表指的是由多系列圖表(柱形圖、折線圖、面積圖)組合而成的圖表。
模板文件如下:

案例代碼:
// 模板文件
String templateFilePath = "/word_template/quote_demo04.docx";
// 輸出文件
String outputFilePath = "D:/output.docx";
// 插入文本數(shù)據(jù)
Map<String, Object> templateData = new HashMap<String, Object>() {{
// 添加單系列圖表的表格數(shù)據(jù)
put("label4", Charts
.ofComboSeries("汽車(chē)銷(xiāo)售額", new String[]{"第一季度", "第二季度", "第三季度", "第四季度"})
// 添加柱狀圖數(shù)據(jù)
.addBarSeries("比亞迪", new Double[]{12.3, 11.5, 9.7, 12.0})
.addBarSeries("廣汽", new Double[]{6.2, 5.8, 5.7, 6.6})
.addBarSeries("小米", new Double[]{0.0, 0.0, 10.2, 11.2})
// 添加折線圖數(shù)據(jù)
.addLineSeries("國(guó)內(nèi)均值", new Double[]{10.0, 12.2, 11.2, 9.8})
.addLineSeries("全球均值", new Double[]{8.3, 10.2, 10.0, 8.8})
.create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);
文檔效果:

以上就是Java poi-tl根據(jù)模版生成word文件并插入文字、圖片、表格、圖表的詳細(xì)內(nèi)容,更多關(guān)于Java poi-tl生成word的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于 Java 的數(shù)據(jù)結(jié)構(gòu)鏈表
這篇文章主要介紹了關(guān)于 Java 的數(shù)據(jù)結(jié)構(gòu)鏈表的相關(guān)資料,需要的朋友可以參考下面文章內(nèi)容2021-09-09
通過(guò)Java實(shí)現(xiàn)對(duì)PDF頁(yè)面的詳細(xì)設(shè)置
這篇文章主要介紹了通過(guò)Java實(shí)現(xiàn)對(duì)PDF頁(yè)面的詳細(xì)設(shè)置,下面的示例將介紹通過(guò)Java編程來(lái)對(duì)PDF頁(yè)面進(jìn)行個(gè)性化設(shè)置的方法,包括設(shè)置頁(yè)面大小、頁(yè)邊距、紙張方向、頁(yè)面旋轉(zhuǎn)等,需要的朋友可以參考下2019-07-07
關(guān)于JDK+Tomcat+eclipse+MyEclipse的配置方法,看這篇夠了
關(guān)于JDK+Tomcat+eclipse+MyEclipse的配置問(wèn)題,很多朋友都搞不太明白,網(wǎng)上一搜配置方法多種哪種最精簡(jiǎn)呢,今天小編給大家分享一篇文章幫助大家快速掌握J(rèn)DK Tomcat eclipse MyEclipse配置技巧,需要的朋友參考下吧2021-06-06
Java自動(dòng)添加重寫(xiě)的toString方法詳解
在本篇文章里小編給大家整理了關(guān)于Java自動(dòng)添加重寫(xiě)的toString方法總結(jié),需要的朋友們學(xué)習(xí)下。2019-07-07
Spring MVC實(shí)現(xiàn)文件上傳及優(yōu)化案例解析
本文介紹如何在SpringMVC框架中實(shí)現(xiàn)文件上傳和異步登錄功能,通過(guò)添加必要的依賴(lài)和配置,創(chuàng)建文件上傳頁(yè)面和控制器,實(shí)現(xiàn)文件上傳到指定文件夾,同時(shí),展示了如何使用AJAX實(shí)現(xiàn)局部刷新的異步登錄,優(yōu)化用戶(hù)體驗(yàn),詳細(xì)步驟包括配置springmvc.xml、編寫(xiě)前端頁(yè)面和控制器等2024-10-10
Spring如何更簡(jiǎn)單的讀取和存儲(chǔ)對(duì)象
這篇文章主要給大家介紹了關(guān)于Spring如何更簡(jiǎn)單的讀取和存儲(chǔ)對(duì)象的相關(guān)資料,在Spring 中想要更簡(jiǎn)單的存儲(chǔ)和讀取對(duì)象的核?是使?注解,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
Spring Boot 實(shí)現(xiàn)Restful webservice服務(wù)端示例代碼
這篇文章主要介紹了Spring Boot 實(shí)現(xiàn)Restful webservice服務(wù)端示例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-11-11

