使用Java填充Word模板的方法詳解

清清飞扬發表於2024-11-12

From: https://www.jb51.net/program/324679hhw.htm

Java填充Word模板是一種將動態資料插入到Word文件模板中生成最終文件的過程,通常用於批次建立包含個人資訊、報告結果或其他動態內容的文件,本文給大家介紹了使用Java填充Word模板的方法,需要的朋友可以參考下

概述

在Java中填充Word模板的需求通常涉及以下幾個步驟:

  1. 準備一個Word模板檔案,包含佔位符。
  2. 使用Java程式碼讀取模板檔案。
  3. 根據實際資料替換模板中的佔位符。
  4. 生成最終的Word文件並儲存或輸出。

為了實現這一過程,我們可以選擇不同的Java庫,每種庫有其獨特的優勢和使用場景。本文將介紹三種常見的Java Word處理庫:Apache POI、Aspose.Words for Java和Docx4j。

常見的Java Word處理庫

Apache POI

Apache POI是一個開源的Java API,用於讀取和寫入Microsoft Office文件。POI支援Word、Excel和PowerPoint檔案格式。它是處理Word文件的一個常用選擇,尤其是在需要處理較簡單的文件操作時。

優點:

  • 開源免費
  • 社群支援活躍
  • 適用於簡單的文件操作

缺點:

  • 對複雜文件操作支援有限
  • API較為底層,使用複雜

Aspose.Words for Java

Aspose.Words for Java是一個功能強大的商業庫,用於建立、修改、轉換和渲染Word文件。它支援各種複雜的Word文件操作,包括填充模板、插入圖片、設定樣式等。

優點:

  • 功能強大,支援複雜的文件操作
  • API簡潔易用
  • 優秀的文件和示例支援

缺點:

  • 商業庫,需要購買許可證
  • 較高的學習成本

Docx4j

Docx4j是一個開源的Java庫,用於建立和操作Office Open XML(OOXML)檔案。它特別適用於處理Word(.docx)文件,支援較複雜的文件操作和格式。

優點:

  • 開源免費
  • 支援複雜的文件操作
  • 良好的文件和社群支援

缺點:

  • 學習曲線較陡
  • 對某些高階特性支援有限

使用Apache POI填充Word模板

建立和讀取Word文件

首先,我們需要建立一個Word模板文件,並在Java程式碼中讀取它。以下是如何使用Apache POI建立和讀取Word文件的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class PoiExample {
public static void main(String[] args) throws IOException {
// 建立Word文件
XWPFDocument document = new XWPFDocument();
// 建立檔案輸出流
FileOutputStream out = new FileOutputStream("template.docx");
document.write(out);
out.close();
// 讀取Word文件
FileInputStream fis = new FileInputStream("template.docx");
XWPFDocument doc = new XWPFDocument(fis);
fis.close();
}
}

填充文字

在模板中,使用佔位符(如${placeholder})來表示需要填充的資料。以下示例展示瞭如何使用Apache POI替換佔位符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import java.util.List;
public class PoiTextFiller {
public static void fillText(XWPFDocument document, String placeholder, String value) {
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String text = run.getText(0);
if (text != null && text.contains(placeholder)) {
text = text.replace(placeholder, value);
run.setText(text, 0);
}
}
}
}
}

填充表格

對於表格資料,可以使用類似的方法遍歷表格並替換佔位符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
public class PoiTableFiller {
public static void fillTable(XWPFDocument document, String placeholder, String value) {
List<XWPFTable> tables = document.getTables();
for (XWPFTable table : tables) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
String text = cell.getText();
if (text != null && text.contains(placeholder)) {
text = text.replace(placeholder, value);
cell.removeParagraph(0);
cell.setText(text);
}
}
}
}
}
}

使用Aspose.Words for Java填充Word模板

建立和讀取Word文件

使用Aspose.Words for Java建立和讀取Word文件相對簡單,以下是示例程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import com.aspose.words.Document;
import com.aspose.words.DocumentBuilder;
public class AsposeExample {
public static void main(String[] args) throws Exception {
// 建立Word文件
Document document = new Document();
DocumentBuilder builder = new DocumentBuilder(document);
// 新增內容到文件
builder.write("Hello World!");
// 儲存文件
document.save("template.docx");
// 讀取Word文件
Document doc = new Document("template.docx");
}
}

填充文字

Aspose.Words提供了更高階的API來替換文字佔位符,例如使用DocumentBuilder類:

1
2
3
4
5
public class AsposeTextFiller {
public static void fillText(Document document, String placeholder, String value) throws Exception {
document.getRange().replace(placeholder, value, new FindReplaceOptions());
}
}

填充表格

使用Aspose.Words填充表格也非常簡單,以下是示例程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.aspose.words.Cell;
import com.aspose.words.Row;
import com.aspose.words.Table;
public class AsposeTableFiller {
public static void fillTable(Document document, String placeholder, String value) throws Exception {
Table table = (Table) document.getChild(NodeType.TABLE, 0, true);
for (Row row : table.getRows()) {
for (Cell cell : row.getCells()) {
if (cell.getText().contains(placeholder)) {
cell.getFirstParagraph().getRuns().clear();
cell.getFirstParagraph().appendChild(new Run(document, value));
}
}
}
}
}

使用Docx4j填充Word模板

建立和讀取Word文件

使用Docx4j建立和讀取Word文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4
j.openpackaging.parts.WordprocessingML.MainDocumentPart;
public class Docx4jExample {
public static void main(String[] args) throws Exception {
// 建立Word文件
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();
// 新增內容到文件
mainDocumentPart.addParagraphOfText("Hello World!");
// 儲存文件
wordMLPackage.save(new java.io.File("template.docx"));
// 讀取Word文件
WordprocessingMLPackage wordMLPackageRead = WordprocessingMLPackage.load(new java.io.File("template.docx"));
}
}

填充文字

使用Docx4j替換文字佔位符的示例如下:

1
2
3
4
5
6
7
8
9
10
11
import org.docx4j.wml.Text;
import org.docx4j.XmlUtils;
public class Docx4jTextFiller {
public static void fillText(WordprocessingMLPackage wordMLPackage, String placeholder, String value) throws Exception {
String xml = XmlUtils.marshaltoString(wordMLPackage.getMainDocumentPart().getJaxbElement(), true, true);
xml = xml.replaceAll(placeholder, value);
wordMLPackage.getMainDocumentPart().setJaxbElement(
(org.docx4j.wml.Document) XmlUtils.unmarshalString(xml));
}
}

填充表格

使用Docx4j填充表格資料的示例程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import org.docx4j.wml.Tc;
import org.docx4j.wml.Tr;
import org.docx4j.wml.Tbl;
public class Docx4jTableFiller {
public static void fillTable(WordprocessingMLPackage wordMLPackage, String placeholder, String value) throws Exception {
List<Object> tables = getAllElementsFromObject(wordMLPackage.getMainDocumentPart(), Tbl.class);
if (tables.size() > 0) {
Tbl table = (Tbl) tables.get(0);
List<Object> rows = getAllElementsFromObject(table, Tr.class);
for (Object row : rows) {
List<Object> cells = getAllElementsFromObject(row, Tc.class);
for (Object cell : cells) {
Tc tableCell = (Tc) cell;
if (tableCell.toString().contains(placeholder)) {
tableCell.getContent().clear();
tableCell.getContent().add(wordMLPackage.getMainDocumentPart().createParagraphOfText(value));
}
}
}
}
}
private static List<Object> getAllElementsFromObject(Object obj, Class<?> toSearch) {
List<Object> result = new ArrayList<>();
if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();
if (obj.getClass().equals(toSearch)) result.add(obj);
else if (obj instanceof ContentAccessor) {
List<?> children = ((ContentAccessor) obj).getContent();
for (Object child : children) result.addAll(getAllElementsFromObject(child, toSearch));
}
return result;
}
}

實際應用示例

生成合同文件

合同文件通常包含多個部分和表格,需要填充客戶資訊、合同條款等。以下是一個使用Apache POI生成合同文件的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.FileOutputStream;
import java.io.IOException;
public class ContractGenerator {
public static void main(String[] args) throws IOException {
XWPFDocument document = new XWPFDocument();
// 填充合同內容
PoiTextFiller.fillText(document, "${customerName}", "張三");
PoiTextFiller.fillText(document, "${contractDate}", "2024-07-05");
PoiTableFiller.fillTable(document, "${itemDescription}", "服務專案");
// 儲存合同文件
FileOutputStream out = new FileOutputStream("contract.docx");
document.write(out);
out.close();
}
}

生成發票文件

發票文件需要填充客戶資訊、商品明細和金額等。以下是一個使用Aspose.Words for Java生成發票文件的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.aspose.words.Document;
import com.aspose.words.DocumentBuilder;
import java.util.List;
public class InvoiceGenerator {
public static void main(String[] args) throws Exception {
Document document = new Document("invoice_template.docx");
// 填充發票內容
AsposeTextFiller.fillText(document, "${customerName}", "李四");
AsposeTextFiller.fillText(document, "${invoiceDate}", "2024-07-05");
AsposeTableFiller.fillTable(document, "${itemDescription}", "商品明細");
// 儲存發票文件
document.save("invoice.docx");
}
}

生成報告文件

報告文件通常包含多個章節和資料圖表,需要填充資料分析結果和圖表。以下是一個使用Docx4j生成報告文件的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import java.io.File;
public class ReportGenerator {
public static void main(String[] args) throws Exception {
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File("report_template.docx"));
// 填充報告內容
Docx4jTextFiller.fillText(wordMLPackage, "${reportTitle}", "2024年度報告");
Docx4jTextFiller.fillText(wordMLPackage, "${reportDate}", "2024-07-05");
Docx4jTableFiller.fillTable(wordMLPackage, "${dataDescription}", "資料分析結果");
// 儲存報告文件
wordMLPackage.save(new File("report.docx"));
}
}

最佳實踐

模板設計

  • 使用清晰的佔位符:選擇易於識別和替換的佔位符,如${placeholder}
  • 保持模板簡潔:儘量減少複雜的格式和樣式,確保模板易於維護。
  • 分段設計:將模板分為多個獨立的部分,便於單獨替換和填充。

效能最佳化

  • 批次處理:對於大量文件生成任務,使用批次處理方法,減少單次操作的開銷。
  • 快取資料:將常用的資料快取到記憶體中,減少重複讀取的開銷。
  • 非同步處理:對於耗時的文件生成任務,使用非同步處理方式,提高系統的響應速度。

錯誤處理

  • 捕獲異常:在文件操作過程中,捕獲可能出現的異常,並記錄錯誤日誌。
  • 資料驗證:在填充模板之前,驗證資料的完整性和準確性,避免生成錯誤的文件。
  • 回滾機制:在批次生成文件過程中,出現錯誤時,支援回滾機制,避免部分資料的生成失敗。

總結

本文詳細介紹瞭如何使用Java填充Word模板,包括常見的Java Word處理庫(Apache POI、Aspose.Words for Java和Docx4j)的使用方法和實際應用示例。透過理解和應用這些技術,可以高效地生成符合特定格式的Word文件,滿足各種業務需求。

相關文章