首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 操作 Word 文檔實戰:基於 Apache POI 的導出與模板填充

     編輯:Java 相關知識

前言

在企業級應用中,動態生成 Word 文檔(合同、報表、證書等)是常見需求。Apache POI 是 Java 操作 Microsoft Office 格式的事實標準庫。本文演示兩種核心場景:純代碼生成文檔與基於模板佔位符替換生成文檔,針對舊版 .doc 格式(HWPF),並給出完整可運行代碼。

環境依賴

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.3.0</version> <!-- 請使用最新版 -->
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>5.3.0</version> <!-- HWPF 需要此模塊 -->
</dependency>

注意:HWPF 僅支持 .doc (Word 97-2003) 格式。現代 .docx (OOXML) 請使用 poi-ooxml 中的 XWPFDocument,功能更強、維護更活躍。

場景一:純代碼生成 Word 文檔

適用於結構固定、無現成模板的簡單導出。

public void exportDoc(String destFile, String content) {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
         POIFSFileSystem fs = new POIFSFileSystem();
         FileOutputStream fos = new FileOutputStream(destFile)) {

        DirectoryEntry root = fs.getRoot();
        root.createDocument("WordDocument", bais); // 核心:寫入流到 POIFS 文檔流
        fs.writeFilesystem(fos); // 序列化為 .doc 文件
    } catch (IOException e) {
        throw new RuntimeException("生成 Word 失敗", e);
    }
}

調用示例:

StringBuilder sb = new StringBuilder();
sb.append("姓名:張三\n性別:男\n身份證:1234567890\n");
// ... 追加更多內容
exportDoc("D:/output.doc", sb.toString());

場景二:基於模板佔位符替換(推薦實際業務使用)

準備一個 template.doc,內容包含佔位符如 ${name}、${idCard} 等。

public HWPFDocument replaceDoc(String templatePath, Map<String, String> placeholders) {
    try (FileInputStream fis = new FileInputStream(templatePath)) {
        HWPFDocument doc = new HWPFDocument(fis);
        Range range = doc.getRange(); // 獲取全文範圍
        for (Map.Entry<String, String> entry : placeholders.entrySet()) {
            // 替換所有匹配的佔位符
            range.replaceText("${" + entry.getKey() + "}", entry.getValue());
        }
        return doc; // 調用者負責 write 到輸出流
    } catch (IOException e) {
        throw new RuntimeException("模板處理失敗", e);
    }
}

調用並保存:

Map<String, String> data = new HashMap<>();
data.put("name", "李四");
data.put("sex", "女");
data.put("idCard", "9876543210");
// ... 填充其他字段

HWPFDocument doc = replaceDoc("template.doc", data);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
     FileOutputStream fos = new FileOutputStream("D:/filled.doc")) {
    doc.write(baos);
    fos.write(baos.toByteArray());
}

核心 API 對照表

類/接口用途備註
POIFSFileSystemOLE2 複合文檔系統入口舊版 .doc 底層存儲結構
HWPFDocumentWord 97-2003 文檔模型需 poi-scratchpad 依賴
Range文檔文本範圍操作replaceText、getText 等
DirectoryEntryPOIFS 目錄節點創建文檔流入口

常見坑與避雷指南

  • 中文亂碼:確保輸入字符串編碼與模板一致,建議統一 UTF-8,若模板為 GBK 需轉碼。
  • 佔位符未替換:檢查模板中佔位符是否被 Word 自動斷字符(如 ${na me})拆分,建議在 Word 中關閉「自動斷詞」或使用連續字符佔位符(如 #{name}#)。
  • 大文件 OOM:HWPF 全量載入內存,超過 50MB 文檔易 OOM,大文件場景必須遷移至 XWPFDocument (SXWPF 流式寫入)。
  • 圖片/表格/樣式不支持:HWPF 對複雜排版支持極弱,複雜報表請改用 docx4j 或 FreeMarker + docx 方案。

遷移建議:拥抱 .docx (XWPF)

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.3.0</version>
</dependency>

// XWPF 替換佔位符示例
XWPFDocument doc = new XWPFDocument(new FileInputStream("template.docx"));
for (XWPFParagraph p : doc.getParagraphs()) {
    for (XWPFRun run : p.getRuns()) {
        String text = run.getText(0);
        if (text != null && text.contains("${name}")) {
            run.setText(text.replace("${name}", "張三"), 0);
        }
    }
}
// 表格、圖片、樣式操作豐富得多

總結

Apache POI HWPF 可快速實現簡單 .doc 文檔的生成與模板填充,代碼量極小。但受限於舊格式架構,複雜排版、大文件、高併發場景下建議全面遷移至 .docx + XWPF 或模板引擎方案。掌握 Range.replaceText 核心 API,配合良好的模板設計,能覆蓋 80% 以上的業務導出需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved