1.基础代码是使用 参考别人的文章(jar 到处都能找到),此文章也只是---记录 自己在开发时遇到的一个坑:
参考文章地址:http://max1487.iteye.com/blog/2424890
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