1. 程式人生 > >poi 合併多個word 適應圖片

poi 合併多個word 適應圖片

1.基礎程式碼是使用 參考別人的文章(jar 到處都能找到),此文章也只是---記錄 自己在開發時遇到的一個坑:

2.主要程式碼:(我踩的坑,我已標紅,後面解釋

/**************合併 word start******************/
    public static int mergeDoc (String[] srcDocxs,String destDocx){  
        if(srcDocxs == null || srcDocxs.length<2){
            //請傳入多個word路徑
            return 1;
        }
        OutputStream dest = null;
            InputStream in1 = null;
            try {
                in1 = new FileInputStream(srcDocxs[0]);  
                dest = new FileOutputStream(destDocx);  
                OPCPackage src1Package = OPCPackage.open(in1);  
                XWPFDocument src1Document = new XWPFDocument(src1Package);  
                for (int i=1;i< srcDocxs.length;i++) {
                    InputStream item = new FileInputStream(srcDocxs[i]);   
                    OPCPackage src2Package = OPCPackage.open(item);  
                    XWPFDocument src2Document = new XWPFDocument(src2Package);  
                    appendBody(src1Document, src2Document);
                }
                src1Document.createNumbering();//操作_1


                src1Document.write(dest);
                return 0;
            } catch (Exception e) {
                logger.error("合併word失敗:"+e.getMessage());
            }
            return 1;
    }
    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<String,String>();  
        for (XWPFPictureData picture : allPictures) {  
            String before = append.getRelationId(picture);  
            //將原文件中的圖片加入到目標文件中  
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);  
            map.put(before, after.replace("rId", "myKey")
);  //操作_2
        }  
  
        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());  
            } 
            addPart = addPart.replace("myKey", "rId");//操作_3

        }  
        //將兩個文件的xml內容進行拼接  
        CTBody makeBody = CTBody.Factory.parse(prefix+mainPart+addPart+sufix);  
  
        src.set(makeBody);  
    }  
    
    /*************合併word end*****************/

3.呼叫:

public static void main(String[] args) {
        String[] srcDocxs = {"E:\\log\\test.docx","E:\\log\\testphoto.docx"};
        String destDocx = "E:\\log\\test_new.docx";
        mergeDoc(srcDocxs, destDocx);
    }

4.解釋:操作_1 的意思是:給合成的word自動編號(應該是分頁的意思),主要是因為 我在做 poi 的word轉pdf功能時 報錯--說的就是合成的word中沒有numbering值;

操作_2和操作_3 是對應關係:此問題出現在 兩個word 文件中都有多張圖片時,方法會將 後面的文件中的圖片 新增到 第1個文件的快取中,會生成對應的 rId 值, 然後再對 字串中的圖片ID進行替換時,會出現 覆蓋現象

如: map中的值為:{rId4:rId8,rId5:rId9,rId6:rId10,rId7:rId11,rId8:rId12,rId9:rId13,}   然後 進行替換 的時候,會先將 rId4替換為rId8,然後依次執行, 但到 替換rId8時,就出現了問題,因為頭一個 rId8是 替換後的,但在程式碼中replace 不會管你,會將兩個rId8都替換為 rid12,這樣就出現了問題,我的解決方法是先不用rId,用其他不易重複的值代替,在所有圖片id替換完成後,再改回來,也可以在 替換那步 判斷是不是替換最後一個,我沒考慮這個,因為 字串中有個replaceFirst,沒有replaceLast