欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

poi实现合并word文档,兼容图片的合并

程序员文章站 2024-01-30 13:20:46
...

问题

       这两天一直在找java合并wrod的实现方法,找到了一个不错的文章,地址如下:http://www.cnblogs.com/tianyublog/p/6957953.html,copy代码试验了一翻,的确是可以实现合并的word的效果的,但是有一个致命的缺陷,word里的图片没办法正确的合并到目标文件。

 

解决

       研究了大半天,终于找到了解决方案。上面的合并word原理是,将word文档的内容转换为xml字符串,然后把要合并文档的xml进行拼接,生成新的文档。之所以图片无法合并是因为xml里只保存了图片的基本信息及ID,但没有保存图片的具体二进制数据,所以解决思路就是如何将文档中的图片合并到目标word之中。于是我对原来合并的代码进行了改造,实现了我想要的效果

 

直接上代码,不能说很巧妙,但是至少解决了问题。

 

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
/**
 * @author: Max
 *  
 * @Date: 2018/6/8
 *  
 * @name: 多个word文件合并,采用poi实现,兼容图片的迁移
 *
 * @Description: 
 */
public class MergeDoc {


    public static void main (String[] args) throws Exception {
        InputStream in1 = null;
        InputStream in2 = null;
        InputStream in3 = null;
        OPCPackage src1Package = null;
        OPCPackage src2Package = null;
        OPCPackage src3Package = null;
        OutputStream dest = new FileOutputStream("d:\\merge.docx");
        try {
            in1 = new FileInputStream("my/word/图片表格测试模板.docx");
            in2 = new FileInputStream("my/word/图片.docx");
            in3 = new FileInputStream("my/word/图片.docx");
            src1Package = OPCPackage.open(in1);
            src2Package = OPCPackage.open(in2);
            src3Package = OPCPackage.open(in3);
        } catch (Exception e) {
            e.printStackTrace();
        }

        XWPFDocument src1Document = new XWPFDocument(src1Package);
        XWPFDocument src2Document = new XWPFDocument(src2Package);
        XWPFDocument src3Document = new XWPFDocument(src2Package);

        appendBody(src1Document, src2Document);
        appendBody(src1Document, src3Document);

        src1Document.write(dest);


    }

    public static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();

        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID
        Map<String,String> map = new HashMap();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after);
        }

        appendBody(src1Body, src2Body,map);

    }

    private static void appendBody(CTBody src, CTBody append,Map<String,String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);

        String srcString = src.xmlText();
        String prefix = srcString.substring(0,srcString.indexOf(">")+1);
        String mainPart = srcString.substring(srcString.indexOf(">")+1,srcString.lastIndexOf("<"));
        String sufix = srcString.substring( srcString.lastIndexOf("<") );
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        
        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
        }
        //将两个文档的xml内容进行拼接
        CTBody makeBody = CTBody.Factory.parse(prefix+mainPart+addPart+sufix);

        src.set(makeBody);
    }
}

 

 

相关标签: java word 合并