使用Apache POI高效替换Word文档中的图片

使用Apache POI高效替换Word文档中的图片

在企业级应用开发中,经常需要动态生成或修改Word文档。Apache POI提供了对Office文档的读写支持。本文将介绍如何利用POI替换Word文档(.docx)中的图片,适用于模板替换、报告生成等场景。

基本原理

在POI的XWPF文档模型中,图片通常嵌入在段落(XWPFParagraph)的运行(XWPFRun)中。每个运行可以包含文本、图片或其他内联对象。替换图片的基本流程为:

  1. 遍历段落和运行,通过运行中的内嵌图片(XWPFPictureData)识别目标图片。
  2. 删除旧图片的引用,并从文档的图片列表中移除相关数据。
  3. 插入新的图片数据,创建新的运行或修改现有运行。

核心代码示例

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import java.io.*;
import java.util.List;

public class WordImageReplacer {
    public static void replaceImage(String docPath, String outputPath, String oldImageName, String newImagePath) throws IOException, InvalidFormatException {
        XWPFDocument document = new XWPFDocument(new FileInputStream(docPath));
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        boolean replaced = false;
        
        for (XWPFParagraph paragraph : paragraphs) {
            List<XWPFRun> runs = paragraph.getRuns();
            if (runs == null) continue;
            
            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                List<XWPFPicture> pictures = run.getEmbeddedPictures();
                if (pictures == null || pictures.isEmpty()) continue;
                
                for (XWPFPicture picture : pictures) {
                    XWPFPictureData pictureData = picture.getPictureData();
                    if (pictureData.getFileName().equals(oldImageName)) {
                        // 删除旧图片
                        run.removePicture(i);
                        // 插入新图片
                        try (InputStream newImageStream = new FileInputStream(newImagePath)) {
                            run.addPicture(newImageStream, Document.PICTURE_TYPE_PNG, oldImageName, 200, 100);
                        }
                        replaced = true;
                        break; // 假设只替换第一个匹配
                    }
                }
                if (replaced) break;
            }
            if (replaced) break;
        }
        
        if (!replaced) {
            System.out.println("未找到匹配的图片: " + oldImageName);
        }
        
        try (FileOutputStream out = new FileOutputStream(outputPath)) {
            document.write(out);
        }
        document.close();
    }
    
    public static void main(String[] args) throws Exception {
        replaceImage("template.docx", "output.docx", "image1.png", "newimage.png");
    }
}

注意事项

  • 图片识别:根据图片文件名(如image1.png)或ID来定位,确保唯一性。
  • 图片格式与尺寸:添加新图片时需指定类型(如PNG, JPEG)和尺寸(单位:EMU,可以通过Units.toEMU转换像素)。
  • 复杂文档结构:如果图片位于表格、页眉页脚中,需要遍历相应容器。
  • 性能优化:对于大文档,建议使用流式处理或缓存。

总结

通过Apache POI替换Word文档中的图片并不复杂,但需要理解内部结构。结合模板技术,可以轻松实现自动化文档生成。希望本文对您有所帮助。