Java利用Apache POI實(shí)現(xiàn)多模板Word文檔生成的示例代碼
處理思路
- 識(shí)別表單元素:復(fù)雜表單里可能包含表格、文本框、下拉框等元素。你需要對(duì)這些元素進(jìn)行識(shí)別,并且明確要替換內(nèi)容的位置。
- 替換表格內(nèi)容:對(duì)于表格,要定位到具體的單元格,然后對(duì)單元格內(nèi)的內(nèi)容進(jìn)行替換。
- 處理文本框:文本框也是需要特別處理的元素,要遍歷文檔中的文本框并替換其中的內(nèi)容。
- 動(dòng)態(tài)賦值:和處理普通文字一樣,利用占位符來(lái)進(jìn)行動(dòng)態(tài)賦值。
示例代碼
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class ComplexFormDocGenerator {
public static void main(String[] args) {
String[] templatePaths = {"complex_template.docx"};
String outputPath = "complex_output.docx";
Map<String, String> values = new HashMap<>();
values.put("${name}", "李四");
values.put("${department}", "技術(shù)部");
try {
generateDocument(templatePaths, outputPath, values);
System.out.println("文檔生成成功,路徑為: " + outputPath);
} catch (IOException e) {
System.err.println("生成文檔時(shí)出現(xiàn)錯(cuò)誤: " + e.getMessage());
e.printStackTrace();
}
}
public static void generateDocument(String[] templatePaths, String outputPath, Map<String, String> values) throws IOException {
XWPFDocument finalDocument = new XWPFDocument();
for (String templatePath : templatePaths) {
try (FileInputStream templateStream = new FileInputStream(templatePath);
XWPFDocument templateDocument = new XWPFDocument(templateStream)) {
replacePlaceholders(templateDocument, values);
appendDocument(finalDocument, templateDocument);
}
}
try (FileOutputStream outputStream = new FileOutputStream(outputPath)) {
finalDocument.write(outputStream);
}
}
private static void replacePlaceholders(XWPFDocument document, Map<String, String> values) {
// 處理段落中的占位符
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, String> entry : values.entrySet()) {
text = text.replace(entry.getKey(), entry.getValue());
}
run.setText(text, 0);
}
}
}
// 處理表格中的占位符
for (XWPFTable table : document.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, String> entry : values.entrySet()) {
text = text.replace(entry.getKey(), entry.getValue());
}
run.setText(text, 0);
}
}
}
}
}
}
// 處理文本框中的占位符(POI 對(duì)文本框處理有限,可結(jié)合其他庫(kù))
// 這里僅簡(jiǎn)單示例,實(shí)際可能需要更復(fù)雜邏輯
// 可以使用 docx4j 等庫(kù)來(lái)更好地處理文本框
for (IBodyElement element : document.getBodyElements()) {
if (element instanceof XWPFSDT) {
XWPFSDT sdt = (XWPFSDT) element;
for (XWPFParagraph paragraph : sdt.getContent().getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, String> entry : values.entrySet()) {
text = text.replace(entry.getKey(), entry.getValue());
}
run.setText(text, 0);
}
}
}
}
}
}
private static void appendDocument(XWPFDocument mainDocument, XWPFDocument appendDocument) throws IOException {
CTBody mainBody = mainDocument.getDocument().getBody();
CTBody appendBody = appendDocument.getDocument().getBody();
for (Object object : appendBody.getContent()) {
mainBody.addNewP().set(object);
}
}
}
代碼解釋
- ?
?main?? 方法:和處理普通文字的示例類(lèi)似,定義了模板文件路徑、輸出文件路徑以及動(dòng)態(tài)賦值的內(nèi)容,然后調(diào)用 ??generateDocument?? 方法生成文檔。 - ?
?generateDocument?? 方法:循環(huán)讀取每個(gè)模板文件,對(duì)其進(jìn)行動(dòng)態(tài)賦值,再將內(nèi)容追加到最終文檔里,最后把最終文檔寫(xiě)入輸出文件。 - ?
?replacePlaceholders?? 方法:
- 處理段落:和普通文字處理一樣,遍歷文檔中的段落和運(yùn)行對(duì)象,把占位符替換成實(shí)際的值。
- 處理表格:遍歷文檔中的所有表格,再遍歷表格的行和單元格,對(duì)單元格內(nèi)的段落和運(yùn)行對(duì)象進(jìn)行占位符替換。
- 處理文本框:使用 ?
?XWPFSDT??? 來(lái)識(shí)別文本框,遍歷文本框內(nèi)的段落和運(yùn)行對(duì)象,進(jìn)行占位符替換。不過(guò) Apache POI 對(duì)文本框的處理能力有限,實(shí)際應(yīng)用中可能需要結(jié)合 ??docx4j?? 等其他庫(kù)。
- ?
?appendDocument?? 方法:將一個(gè)文檔的內(nèi)容追加到另一個(gè)文檔中。
注意事項(xiàng)
- 要保證 ?
?complex_template.docx?? 文件存在于項(xiàng)目的根目錄下,或者根據(jù)實(shí)際情況修改文件路徑。 - 運(yùn)行代碼前,要確保項(xiàng)目中已經(jīng)正確引入了 Apache POI 的依賴(lài)。
- 對(duì)于復(fù)雜的表單元素,如下拉框、復(fù)選框等,可能需要更復(fù)雜的處理邏輯,你可以結(jié)合 ?
?docx4j?? 等庫(kù)來(lái)實(shí)現(xiàn)。
到此這篇關(guān)于Java利用Apache POI實(shí)現(xiàn)多模板Word文檔生成的示例代碼的文章就介紹到這了,更多相關(guān)Java Apache POI多模板Word生成內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在SpringBoot中更改默認(rèn)端口的方法總結(jié)
在本文中,小編將帶大家學(xué)習(xí)如何在 Spring Boot 中更改默認(rèn)端口,默認(rèn)情況下,嵌入式 Web 服務(wù)器使用 8080端口來(lái)啟動(dòng) Spring 引導(dǎo)應(yīng)用程序,有幾種方法可以更改該端口,文中介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
老生常談設(shè)計(jì)模式之動(dòng)態(tài)代理
下面小編就為大家?guī)?lái)一篇老生常談設(shè)計(jì)模式之動(dòng)態(tài)代理。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
springboot整合Nacos組件環(huán)境搭建和入門(mén)案例詳解(最新推薦)
本文介紹了Nacos的基礎(chǔ)概念、關(guān)鍵特性、專(zhuān)業(yè)術(shù)語(yǔ)和生態(tài)圈,如何在Windows環(huán)境下搭建Nacos單個(gè)服務(wù),以及如何整合SpringBoot2來(lái)使用Nacos進(jìn)行服務(wù)注冊(cè)和配置管理,感興趣的朋友一起看看吧2025-03-03
Java實(shí)現(xiàn)Token工具類(lèi)進(jìn)行登錄和攔截
在應(yīng)用的登錄時(shí)需要生成token進(jìn)行驗(yàn)證,并放入信息,之后的話可以直接使用瀏覽器的session進(jìn)行登錄,本文就來(lái)利用java編寫(xiě)一個(gè)token工具類(lèi),可以很方便的生成和解析token,感興趣的可以了解下2023-12-12
運(yùn)行jar程序時(shí)添加vm參數(shù)的方法
下面小編就為大家?guī)?lái)一篇運(yùn)行jar程序時(shí)添加vm參數(shù)的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
JVM執(zhí)行引擎和垃圾回收要點(diǎn)總結(jié)
不論是在問(wèn)題現(xiàn)場(chǎng)還是跳槽面試,我們面對(duì)JVM性能問(wèn)題,依舊會(huì)束手無(wú)辭,它需要你對(duì)Java虛擬機(jī)的實(shí)現(xiàn)和優(yōu)化,有極為深刻的理解。所以我在這里整理了一下 JVM的知識(shí)點(diǎn)。今天說(shuō)說(shuō)虛擬機(jī)執(zhí)行引擎和垃圾回收,都是十足的干貨,請(qǐng)各位看官耐心批閱!2021-06-06

