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[] ...
随机推荐
- 【Kafka】
KafkaProducer Kafka消息发布客户端. 线程安全,跨线程共享单个生产者实例通常比拥有多个实例的速度更快. 例子,使用生产者发送包含序列号的字符串作为键/值对的记录: Propertie ...
- python --- json模块和pickle模块详解
json:JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式(用于数据序列化和反序列化).(适用于多种编程语言,可以与其他编程语言做数据交换 ...
- 【京东个人中心】——Nodejs/Ajax/HTML5/Mysql爬坑之注册与登录监听
一.引言 在数据库和静态页面都创建好之后,下面就该接着完成后台Node.js监听注册和登录的部分了.这个部分主要使用的技术是:Node.js的Express框架和ajax异步请求.登录和注册的代码实现 ...
- HDU1285 确定比赛名次
有N个比赛队(<=N<=),编号依次为1,,,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结 ...
- django中间件Middleware
熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截. django中的中间件(middleware)就是类似钩子的一种存在.下面我们来介绍一下,并 ...
- iOS10适配相关
2016年9月7日,苹果发布iOS 10.2016年9月14日,全新的操作系统iOS 10将正式上线. 作为开发者,如何适配iOS10呢? 1.Notification(通知) 自从Notificat ...
- BZOJ-3040-最短路(road)
Description N个点,M条边的有向图,求点1到点N的最短路(保证存在).1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表 ...
- uva10003 - Cutting Sticks(简单动规)
/* * Author: Bingo * Created Time: 2015/2/13 18:33:03 * File Name: uva10003.cpp */ #include <iost ...
- MQTT——入门介绍
笔者相信大家对HTTP一定不能陌生."HTTP协议的三次握手四次挥手"相信也略有耳闻.HTTP协议的优势相信大家都明白.不然他不会这流行.然而这并不能忽略他的缺点.最大的特点就是无 ...
- 浅谈前后端分离与实践 之 nodejs 中间层服务(二)
一.背景 书接上文,浅谈前后端分离与实践(一) 我们用mock服务器搭建起来了自己的前端数据模拟服务,前后端开发过程中只需定义好接口规范,便可以相互进行各自的开发任务.联调的时候,按照之前定义的开发规 ...