一、问题描述

  通过POI,把Word中的占位符替换为实际的值,以生成复杂结构的业务报告。

  在POI 3.9上,功能正常。由于某些原因升级到POI 3.10.1后,项目组反馈说Word模板出错,无法生成Word文件,总是报解析错误。

二、问题分析

  Word模板功能相关的代码应该说是比较稳定了,相关代码很久没有变动过,而且已经有投产项目在正式使用。现在出了问题,应该是升级POI版本导致的。

  Word模板内容示例:

  本期产品为向${ds:ds001,col:INVESTER_TYPE_NAME}发行的混合类理财产品,本期产品投资期限为${ds:ds001,col:TERM}天,收益率为${ds:ds001,col:YTM_100}%/年,为${ds:ds001,col:INCOME_TYPE_NAME}类产品,到期还本付息。是一款具有投资安全性高、回报率高重点的理财产品。

  分析、调试代码。发现两个版本的POI在处理Paragraph.getRuns()有区别:

  3.9版本:一个段落就是一个XWPFRun;

  3.10.1版本:一个段落不知道根据什么规则,胡乱分成了List<XWPFRun>。如上述示例模板,会被切换为长度为14的List;

  这样就导致获取、替换段落文本时出错。

三、问题解决

  问题被定位后,就尝试解决。主要的思路,就是强制把List中的内容合并成一个字符串,替换内容后,把段落中的XWPFRun全部remove掉,然后新建一个含有替换后内容的XPWFRun,并赋给当前段落。

  解决问题的过程中,“对于removeRun方法无法达到本应达成的预期效果的问题”,耗费了不少时间。总结来说:不能从0到size()移除Run,这样的话Run不会被移除;而应该从size()到0进行移除。

  需要继续关注表格替换时是否会有问题。

  解决这类第三方软件引起的问题,几乎没有道理可言,如果不想被埋在相关源代码中,只能靠经验+运气。

四、附代码

在3.10.1下有问题的代码示意:

while (itPara.hasNext()) {

XWPFParagraph paragraph = (XWPFParagraph) itPara.next();

  int length = paragraph.getRuns().size();

  if (length > 0) {

String text = paragraph.getText();

if (text.indexOf(tag) < 0) {

      continue;

}

while (length-- > 0) {

      paragraph.removeRun(0);

}

XWPFRun newrun = paragraph.insertNewRun(0);

newrun.setText(text.replace(tag, val));

}

}

修改后的代码示意:

while (itPara.hasNext()) {

XWPFParagraph paragraph = (XWPFParagraph) itPara.next();

int length = paragraph.getRuns().size();

if (length > 0) {

String text = StringUtils.join(paragraph.getRuns().toArray());

if (text.indexOf(tag) < 0) {

    continue;

}

for (int i = (length - 1); i >= 0; i--) {

    paragraph.removeRun(i);

}

XWPFRun newRun = paragraph.insertNewRun(0);

text = text.replaceAll(tag, val);

newRun.setText(text, 0);

}

}

POI不同版本替换Word模板时的问题的更多相关文章

  1. 利用POI 技术动态替换word模板内容

    项目中需要实现一个功能,动态替换给定模板里面的内容,生成word文档提供下载功能. 中间解决了问题有: 1.页眉的文档logo图片解决,刚开始的时候,HWPFDocument 对象无法读取图片对象(已 ...

  2. tp5 使用phpword 替换word模板并利用com组件转换pdf

    tp5   使用phpword 替换word模板并利用com组件转换pdf 一.首先composer安装PHPword,就不多说了 二.然后是把模板中要替换的部分用变量代替 三.把原始的模板文件放入项 ...

  3. javascript下用ActiveXObject控件替换word书签,将内容导出到word后打印第1/2页

    由于时间比较紧,没多的时候去学习研究上述工具包,现在用javascript操作ActiveXObject控件,用替换word模板中的书签方式解决. 最近有需求将数据导出到word里,然后编辑打印. 想 ...

  4. 【3】利用Word模板生成文档的总结

    阅读目录 Word二次开发概况 使用DsoFramer进行开发 使用Interop进行开发 打开.关闭和写入操作 批量替换文本 遍历段落替换文本 查找后逐个替换文本 结论 在各类应用系统开发中,和Wo ...

  5. Open Xml SDK Word模板开发最佳实践(Best Practice)

    1.概述 由于前面的引文已经对Open Xml SDK做了一个简要的介绍. 这次来点实际的——Word模板操作. 从本质上来讲,本文的操作都是基于模板替换思想的,即,我们通过替换Word模板中指定元素 ...

  6. Java中用Apache POI生成excel和word文档

    概述: 近期在做项目的过程中遇到了excel的数据导出和word的图文表报告的导出功能.最后决定用Apache POI来完毕该项功能.本文就项目实现过程中的一些思路与代码与大家共享.同一时候.也作为自 ...

  7. 读取word模板,填充数据后导出

    一.需求说明 定期生成word报告,报告中含有文本.表格.图表等元素,依次获取进行替换,保留原有样式,生成新的word文档 二.引入依赖 <dependency> <groupId& ...

  8. C# 利用占位符替换word中的字符串和添加图片

    利用占位符替换word中的字符串和添加图片   ///<summary>         /// 替换word模板文件内容,包括表格中内容         /// 调用如下:WordStr ...

  9. POI Word 模板 文字 图片 替换

    实验环境:POI3.7+Word2007 Word模板: 替换后效果: 代码: 1.入口文件 public class Test { public static void main(String[] ...

随机推荐

  1. Quartz学习——Spring和Quartz集成详解(三)

    Spring是一个很优秀的框架,它无缝的集成了Quartz,简单方便的让企业级应用更好的使用Quartz进行任务的调度.下面就对Spring集成Quartz进行简单的介绍和示例讲解!和上一节 Quar ...

  2. H5上传图片并使用canvas制作海报

    马上就要"十一"国庆节了,又恰逢公司已经三周岁了,所以市场部和产品共同策划了一个"正青春,共成长"的主题代言活动,准备在国庆节以及中秋节期间让公司员工和用户为公 ...

  3. Laravel5 控制器

    Request 一.取值 1.取值 echo $request->input('name','这是默认值'); 2.取得所有值 $array=$request->all(); 3.判断值是 ...

  4. CodeForces 242E二维线段树

                                                                                           E. XOR on Seg ...

  5. Spring REST 与 Zuul 代理

    http://www.baeldung.com/spring-rest-with-zuul-proxy 作者: Eugen Paraschiv 译者: http://oopsguy.com 1.概述 ...

  6. 悟透JavaScript(二)

    初看原型 prototype源自法语,软件界的标准翻译为“原型”,代表事物的初始形态,也含有模型和样板的意义.JavaScript中的prototype概念恰如其分地反映了这个词的内含,我们不能将其理 ...

  7. IDL Interpolate()函数

    Interpolate()函数:可以将数组调整到同维任意大小,并支持任意定位差值.调用格式为 Interpolate(数组,X[,Y[,Z]][,关键字]) 例子: IDL> arr=findg ...

  8. ASP.NET没有魔法——ASP.NET MVC是如何运行的?它的生命周期是什么?

    前面的文章我们使用ASP.NET MVC创建了个博客应用,那么它是如何工作的呢?我们都知道ASP.NET的程序需要部署到IIS上才能够通过浏览器来访问,那么IIS与ASP.NET MVC程序之间又是如 ...

  9. caffe源码 池化层 反向传播

    图示池化层(前向传播) 池化层其实和卷积层有点相似,有个类似卷积核的窗口按照固定的步长在移动,每个窗口做一定的操作,按照这个操作的类型可以分为两种池化层: 输入参数如下: 输入: 1 * 3 * 4 ...

  10. #tensorflow入门(1)

    tensorflow入门(1) 关于 TensorFlow TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操 ...