最近多了一個需求,需要對word模板內容進行替換,一開始用的是word03版的,替換起來比較簡單,主要是range對像替換非常方便,而且可以保留替換前的字體樣式。
1 InputStream is = new FileInputStream(srcFath); 2 OutputStream os = new FileOutputStream(tempFile); 3 XWPFDocument doc = new XWPFDocument(is); 4 Range range = doc.getRange(); 5 range.replaceText("${name}","aaa"); 6 doc.write(os); 7 is.close(); 8 os.flush(); 9 os.close();
最后看到word里包含了圖片,需要同時保存一張png圖片,對於jpg的圖片是可以的,但是png的顯示不出來,改為操作2007的文檔,07版的沒有了Range,使用XWPFParagraph和XWPFRun來操作。XWPFParagraph表示段落,有的word里有表格內容,需要使用XWPFTable來處理,與段落區分開來處理。
private void replaceText(XWPFDocument doc, Map<String, Object> params) { Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator(); XWPFParagraph para; while (iterator.hasNext()) { para = iterator.next(); this.replaceInPara(para, params); } } private void replaceText(XWPFParagraph para, Map<String, Object> params) { List<XWPFRun> runs; Matcher matcher; if (matcher(para.getParagraphText()).find()) { runs = para.getRuns(); for (int i=0; i<runs.size(); i++) { XWPFRun run = runs.get(i); String runText = run.toString(); matcher = matcher(runText); if (matcher.find()) { while ((matcher = matcher(runText)).find()) { runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1)))); } para.removeRun(i); //重新插入run里內容格式可能與原來模板的格式不一致 para.insertNewRun(i).setText(runText); } } } }
private Matcher matcher(String str) {
Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher;
}
再次處理替換內容的格式問題,通過一個臨時文件先保存替換模板變量后的文件,在與之前模板文檔一起通過正則匹配出變量位置,由於替換變量時先刪除再插入,所以位置是一致的。
private void setStyle(XWPFDocument doc,XWPFDocument tempdoc, Map<String, Object> params) { Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator(); Iterator<XWPFParagraph> iterator2 = tempdoc.getParagraphsIterator(); XWPFParagraph para ; XWPFParagraph para2; while (iterator.hasNext()) { para = iterator.next(); para2 = iterator2.next(); this.styleInPara(para,para2, params); } } private void setStyle(XWPFParagraph para, XWPFParagraph para2,Map<String, Object> params) { List<XWPFRun> runs; List<XWPFRun> runs2; Matcher matcher; if (matcher(para.getParagraphText()).find()) { runs = para.getRuns(); runs2 = para2.getRuns(); for (int i=0; i<runs.size(); i++) { XWPFRun run = runs.get(i); XWPFRun run2 = runs2.get(i); String runText = run.toString(); matcher = matcher(runText); if (matcher.find()) { //按模板文件格式設置格式 run2.getCTR().setRPr(run.getCTR().getRPr()); } } } }
按照原模板格式設置好替換后格式后顯示正常。
ps:XWPFRun表示有相同屬性的一段文本,所以模板里變量內容需要從左到右的順序寫,${userName},如果先寫${},再添加內容,會拆分成幾部分,不能正常使用