POI批量替换world文档XWPFParagraph.getRuns 出现分段混乱(附源码)

来源:互联网 发布:s7-200仿真软件 编辑:程序博客网 时间:2024/06/05 17:38

问题:在操作POI替换world时发现getRuns将我们预设的${product}自动切换成了

  ${product, }]${product  }成了两个部分

生成错误时的图片
解决方法一。(未尝试)
强制把List中的内容合并成一个字符串,替换内容后,把段落中的XWPFRun全部remove掉,然后新建一个含有替换后内容的XPWFRun,并赋给当前段落。
解决方法二.
请用复制粘贴把你的${product}添加进world文档里面即可解决,不要手打 目前发现复制粘贴是没有问题的,感觉像是poi的一个bug不知道立贴为证。

注意:${这里尽量不要存中文,否在还出现上面情况}

下面上代码:

public class WorldUtil {        public static String doc2String2() {            try {                WorldUtil wd = new WorldUtil();                Map<String, Object> params = new HashMap<String, Object>();                params.put("reportDate", "2014-02-28");/*              params.put("appleAmt", "100.00");                params.put("bananaAmt", "200.00");                params.put("totalAmt", "300.00");*/                String filePath = "d:\\1.docx";                InputStream is = new FileInputStream(filePath);                XWPFDocument doc = new XWPFDocument(is);                //替换段落里面的变量                  wd.replaceInPara(doc, params);                //替换表格里面的变量                  wd.replaceInTable(doc, params);                OutputStream os = new FileOutputStream("d:\\sample.docx");                doc.write(os);                wd.close(os);                wd.close(is);            } catch (Exception e) {                // TODO: handle exception            }            return null;        }        /**         * 读取doc文件内容         * @param file 想要读取的文件对象         * @return 返回文件内容         */        public static String doc2String(){            try {                FileInputStream stream = new FileInputStream("d://1.docx");                XWPFDocument doc = new XWPFDocument(stream);// 创建Word文件                for(XWPFParagraph p : doc.getParagraphs())//遍历段落                {                    System.out.println(p.getParagraphText());                }                for(XWPFTable table : doc.getTables())//遍历表格                {                     for(XWPFTableRow row : table.getRows())                     {                         for(XWPFTableCell cell : row.getTableCells())                         {                             System.out.println(cell.getText());                         }                     }                }                FileOutputStream out = new FileOutputStream("d://sample.docx");                doc.write(out);                out.close();                stream.close();            } catch (Exception e) {                // TODO: handle exception            }            return null;        }        /**          * 替换段落里面的变量          * @param doc 要替换的文档          * @param params 参数          */          private void replaceInPara(XWPFDocument doc, Map<String, Object> params) {             Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();             XWPFParagraph para;             while (iterator.hasNext()) {                para = iterator.next();                this.replaceInPara(para, params);             }          }          /**          * 替换段落里面的变量          * @param para 要替换的段落          * @param params 参数          */          private void replaceInPara(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);                   System.out.println(runText);                 if (matcher.find()) {                      System.out.println("进1");                     while ((matcher = this.matcher(runText)).find()) {                          runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));                       }                       //直接调用XWPFRun的setText()方法设置文本时,在底层会重新创建一个XWPFRun,把文本附加在当前文本后面,                       //所以我们不能直接设值,需要先删除当前run,然后再自己手动插入一个新的run。                       para.removeRun(i);                       para.insertNewRun(i).setText(runText);                   }                }             }          }          /**          * 替换表格里面的变量          * @param doc 要替换的文档          * @param params 参数          */          private void replaceInTable(XWPFDocument doc, Map<String, Object> params) {             Iterator<XWPFTable> iterator = doc.getTablesIterator();             XWPFTable table;             List<XWPFTableRow> rows;             List<XWPFTableCell> cells;             List<XWPFParagraph> paras;             while (iterator.hasNext()) {                table = iterator.next();                rows = table.getRows();                for (XWPFTableRow row : rows) {                   cells = row.getTableCells();                   for (XWPFTableCell cell : cells) {                       paras = cell.getParagraphs();                       for (XWPFParagraph para : paras) {                          this.replaceInPara(para, params);                       }                   }                }             }          }          /**          * 正则匹配字符串          * @param str          * @return          */          private Matcher matcher(String str) {             Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);             Matcher matcher = pattern.matcher(str);            return matcher;          }          /**          * 关闭输入流          * @param is          */          private void close(InputStream is) {             if (is != null) {                try {                   is.close();                } catch (IOException e) {                   e.printStackTrace();                }             }          }          /**          * 关闭输出流          * @param os          */          private void close(OutputStream os) {             if (os != null) {                try {                   os.close();                } catch (IOException e) {                   e.printStackTrace();                }             }          }        public static void main(String[] args) {        // TODO Auto-generated method stub        //doc2String();        doc2String2();    }}