POI不同版本替换Word模板时的问题
一、问题描述
通过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模板时的问题的更多相关文章
- 利用POI 技术动态替换word模板内容
项目中需要实现一个功能,动态替换给定模板里面的内容,生成word文档提供下载功能. 中间解决了问题有: 1.页眉的文档logo图片解决,刚开始的时候,HWPFDocument 对象无法读取图片对象(已 ...
- tp5 使用phpword 替换word模板并利用com组件转换pdf
tp5 使用phpword 替换word模板并利用com组件转换pdf 一.首先composer安装PHPword,就不多说了 二.然后是把模板中要替换的部分用变量代替 三.把原始的模板文件放入项 ...
- javascript下用ActiveXObject控件替换word书签,将内容导出到word后打印第1/2页
由于时间比较紧,没多的时候去学习研究上述工具包,现在用javascript操作ActiveXObject控件,用替换word模板中的书签方式解决. 最近有需求将数据导出到word里,然后编辑打印. 想 ...
- 【3】利用Word模板生成文档的总结
阅读目录 Word二次开发概况 使用DsoFramer进行开发 使用Interop进行开发 打开.关闭和写入操作 批量替换文本 遍历段落替换文本 查找后逐个替换文本 结论 在各类应用系统开发中,和Wo ...
- Open Xml SDK Word模板开发最佳实践(Best Practice)
1.概述 由于前面的引文已经对Open Xml SDK做了一个简要的介绍. 这次来点实际的——Word模板操作. 从本质上来讲,本文的操作都是基于模板替换思想的,即,我们通过替换Word模板中指定元素 ...
- Java中用Apache POI生成excel和word文档
概述: 近期在做项目的过程中遇到了excel的数据导出和word的图文表报告的导出功能.最后决定用Apache POI来完毕该项功能.本文就项目实现过程中的一些思路与代码与大家共享.同一时候.也作为自 ...
- 读取word模板,填充数据后导出
一.需求说明 定期生成word报告,报告中含有文本.表格.图表等元素,依次获取进行替换,保留原有样式,生成新的word文档 二.引入依赖 <dependency> <groupId& ...
- C# 利用占位符替换word中的字符串和添加图片
利用占位符替换word中的字符串和添加图片 ///<summary> /// 替换word模板文件内容,包括表格中内容 /// 调用如下:WordStr ...
- POI Word 模板 文字 图片 替换
实验环境:POI3.7+Word2007 Word模板: 替换后效果: 代码: 1.入口文件 public class Test { public static void main(String[] ...
随机推荐
- 第5章 不要让线程成为脱缰的野马(Keeping your Threads on Leash) ---线程优先权(Thread priority)
有没有过这样的经验?你坐在你的车子里,目的地还在好几公里之遥,而时间已经很晚了.你拼命想告诉那些挡住你去路的人们,今天这个约会对你是多么多么重要,能不能请他们统统--呃--滚到马路外?很不幸,道路系统 ...
- HiWord()
#define HIWORD(I) ( ( WORD ) ( ( ( DWORD )( I ) >> 16) & 0xFFFF ) ). 这个宏传回一个WORD值(16位的无符号整 ...
- Happy 2006 poj2773
Happy 2006 Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 9049 Accepted: 3031 Descri ...
- P1050
问题 F: P1050 时间限制: 1 Sec 内存限制: 128 MB提交: 37 解决: 27[提交][状态][讨论版] 题目描述 一个字符串A的子串被定义成从A中顺次选出若干个字符构成的串. ...
- Number Complement
Given a positive integer, output its complement number. The complement strategy is to flip the bits ...
- cnpm的全局安装
npm install -g cnpm --registry=https://registry.npm.taobao.org
- 多个activity跳转保留内存使用intent传递数据问题_新手
/////本来是做的activity跳转,普通那种,但是会在调回来会销毁原来的,重新调用onCreate方法, 后来参考[http://blog.csdn.net/qq_26918031/articl ...
- M-定在下边的区域
1 效果 2 布局 3 样式
- NOIP初赛 之 逻辑运算
NOIP初赛 之 逻辑运算 逻辑运算先掌握各种运算,注意运算符的级别比较,做题是要细心.在NOIP中一般一题,分值为1.5分. 概念介绍: 非:not ¬ 与:and ∧ 或:o ...
- SpringMVC 实现文件的上传与下载
一 配置SpringMVC ,并导入与文件上传下载有关的jar包(在此不再赘述) 二 新建 相应 jsp 和controller FileUpAndDown.jsp <%@ page lang ...