代码:
public static OutputStream replaceBySteam(InputStream srcStream, String destPath, Map<String, String> map,String name,String id,HttpServletResponse response) throws Exception { XWPFDocument document = new XWPFDocument(srcStream); return replace(document, destPath, map, name, id, response); } private static OutputStream replace(XWPFDocument document, String destPath, Map<String, String> map, String name, String id, HttpServletResponse response) { OutputStream outStream = null; try { /** * 替换段落中的指定文字 */ Iterator<XWPFParagraph> itPara = document.getParagraphsIterator(); while (itPara.hasNext()) { XWPFParagraph paragraph = itPara.next(); List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { String oneparaString = run.getText(run.getTextPosition()); if (StringUtils.isBlank(oneparaString)){ continue; } for (Map.Entry<String, String> entry : map.entrySet()) { if(entry.getValue()!=null){ oneparaString = oneparaString.replace(entry.getKey(), entry.getValue()); } } run.setText(oneparaString, 0); } } // while (itPara.hasNext()) { // XWPFParagraph paragraph = (XWPFParagraph) itPara.next(); // Set<String> set = map.keySet(); // Iterator<String> iterator = set.iterator(); // while (iterator.hasNext()) { // String key = iterator.next(); // List<XWPFRun> run = paragraph.getRuns(); // for (int i = 0; i < run.size(); i++) { // if (run.get(i).getText(run.get(i).getTextPosition()) != null && // run.get(i).getText(run.get(i).getTextPosition()).equals(key)) { // /** // * 参数0表示生成的文字是要从哪一个地方开始放置,设置文字从位置0开始 // * 就可以把原来的文字全部替换掉了 // */ // run.get(i).setText(map.get(key), 0); // } // } // } // } /** * 替换表格中的指定文字 */ Iterator<XWPFTable> itTable = document.getTablesIterator(); while (itTable.hasNext()) { XWPFTable table = (XWPFTable) itTable.next(); int count = table.getNumberOfRows(); for (int i = 0; i < count; i++) { XWPFTableRow row = table.getRow(i); List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { for (Map.Entry<String, String> e : map.entrySet()) { if (cell.getText().equals(e.getKey())) { cell.removeParagraph(0); cell.setText(e.getValue()); } } } } } // outStream = response.getOutputStream(); // FileOutputStream outStream = null; outStream = new FileOutputStream(destPath+name+".docx"); document.write(outStream); } catch (Exception e) { e.printStackTrace(); } return outStream; }
出错原因:
在段落替换部分,最小单位是XWPFRun,XWPFRun是一个XML节点,包含了各种样式,属性和文字
2.从XWPFRun中取出文字进行替换,失败的原因就是:${变量}被分割在了数个XWPFRun里面,替换失败
解决方法
1.word打开原docx文件,取消各种拼写检查,另存为 xml文件
2.文本编辑器打开xml,找到要替换的属性占位符,手动处理.
3.保存xml,用word打开xml,另存为,docx.
如果还不行,可以在换一种段落的替换方式.
第一种:
while (itPara.hasNext()) { // XWPFParagraph paragraph = (XWPFParagraph) itPara.next(); // Set<String> set = map.keySet(); // Iterator<String> iterator = set.iterator(); // while (iterator.hasNext()) { // String key = iterator.next(); // List<XWPFRun> run = paragraph.getRuns(); // for (int i = 0; i < run.size(); i++) { // if (run.get(i).getText(run.get(i).getTextPosition()) != null && // run.get(i).getText(run.get(i).getTextPosition()).equals(key)) { // /** // * 参数0表示生成的文字是要从哪一个地方开始放置,设置文字从位置0开始 // * 就可以把原来的文字全部替换掉了 // */ // run.get(i).setText(map.get(key), 0); // } // } // } // }
第二种:
while (itPara.hasNext()) { XWPFParagraph paragraph = itPara.next(); List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { String oneparaString = run.getText(run.getTextPosition()); if (StringUtils.isBlank(oneparaString)){ continue; } for (Map.Entry<String, String> entry : map.entrySet()) { if(entry.getValue()!=null){ oneparaString = oneparaString.replace(entry.getKey(), entry.getValue()); } } run.setText(oneparaString, 0); } }