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

Java 使用 Jsoup + Jacob 生成 Word 文檔 (含圖片嵌入)

     編輯:Java 程式設計入門

技術架構

結合 Jsoup 解析/標準化 HTML 與 Jacob (Java-COM Bridge) 驅動 Microsoft Word,實現 HTML 轉 Word 並解決圖片外部連結失效問題。

核心流程

  1. HTML 標準化:Jsoup.parse(html) 修正不合法標籤
  2. 圖片佔位符替換:遍歷 <img> 標籤,提取 src 存入 Map<Integer, String>,HTML 中替換為 ${image_1} 等標記
  3. 寫入臨時 .doc:用 FileWriter 輸出處理後 HTML 為 template.doc
  4. Jacob 啟動 Word:開啟 template.doc,調用 replaceText2Image 將佔位符替換為實際圖片
  5. 複製內容至新文檔:selectAll → copy → createNewDocument → paste → saveAs
  6. 避免大量複製提示:退出前建立空文檔複製少量文字,清空剪貼簿

關鍵代碼片段

Jsoup 處理圖片

Document doc = Jsoup.parse(html);
Map<Integer, String> imgMap = new HashMap<>();
int idx = 1;
for (Element img : doc.select("img")) {
    String src = img.attr("src");
    imgMap.put(idx, src);
    img.replaceWith(new TextNode("${image_" + idx + "}", ""));
    idx++;
}
String processedHtml = doc.outerHtml();

Jacob 核心工具類 (節錄)

public class MSOfficeGeneratorUtils {
    private ActiveXComponent word;
    private Dispatch document, selection;

    public MSOfficeGeneratorUtils(boolean visible) {
        word = new ActiveXComponent("Word.Application");
        word.setProperty("Visible", new Variant(visible));
        word.setProperty("AutomationSecurity", new Variant(3)); // 禁用巨集
    }

    public void openDocument(String path) {
        document = Dispatch.call(word.getProperty("Documents"), "Open", path).toDispatch();
        selection = word.getProperty("Selection").toDispatch();
    }

    public void replaceText2Image(String placeholder, String imgPath) {
        moveStart();
        while (find(placeholder)) {
            insertImage(imgPath);
            moveEnd(); enterDown(1);
        }
    }

    private void insertImage(String path) {
        Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(), 
                      "AddPicture", path);
    }

    public void copyAll() {
        Dispatch.call(document, "Select");
        Dispatch.call(selection, "Copy");
    }

    public void paste() { Dispatch.call(selection, "Paste"); }
    
    public void saveAs(String path) { 
        Dispatch.call(document, "SaveAs", path); 
    }
    
    public void quit() { 
        word.invoke("Quit", new Variant[0]); 
        ComThread.Release(); 
    }
}

完整生成範例

public void generateWord(String html, String outputPath) throws IOException {
    // 1. Jsoup 處理
    Document doc = Jsoup.parse(html);
    Map<Integer, String> imgMap = new LinkedHashMap<>();
    int i = 1;
    for (Element img : doc.select("img")) {
        imgMap.put(i, img.attr("abs:src"));  // 確保絕對路徑
        img.replaceWith(new TextNode("${img_" + i + "}", ""));
        i++;
    }
    File temp = File.createTempFile("template", ".doc");
    Files.write(temp.toPath(), doc.outerHtml().getBytes(StandardCharsets.UTF_8));

    // 2. Jacob 處理
    MSOfficeGeneratorUtils word = new MSOfficeGeneratorUtils(false);
    try {
        word.openDocument(temp.getAbsolutePath());
        for (Map.Entry<Integer, String> e : imgMap.entrySet()) {
            word.replaceText2Image("${img_" + e.getKey() + "}", e.getValue());
        }
        word.copyAll();
        word.createNewDocument();
        word.paste();
        word.saveAs(outputPath);
    } finally {
        word.quit();
        temp.delete();
    }
}

依賴與環境要求

  • Jsoup:org.jsoup:jsoup:1.17.2
  • Jacob:com.jacob:jacob:1.20 + jacob.dll 放入 java.library.path (系統路徑或 -Djava.library.path)
  • 運行環境:Windows + 安裝 Microsoft Word (需授權)
  • 32/64 位元:JVM、Jacob DLL、Word 必須位元數一致

常見問題

  • ComThread 錯誤:多線程需各自 ComThread.InitSTA() / Release()
  • 圖片不顯示:路徑需為絕對路徑,且 Word 能存取該路徑
  • 中文亂碼:HTML 指定 <meta charset="UTF-8">,Jacob 端確保編碼一致
  • 效能:啟動 Word 耗時較大,批量生成建議複用 Word 實例或改用 Apache POI / docx4j 純 Java 方案
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved