一、问题描述

  通过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. 【Kafka】

    KafkaProducer Kafka消息发布客户端. 线程安全,跨线程共享单个生产者实例通常比拥有多个实例的速度更快. 例子,使用生产者发送包含序列号的字符串作为键/值对的记录: Propertie ...

  2. python --- json模块和pickle模块详解

    json:JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式(用于数据序列化和反序列化).(适用于多种编程语言,可以与其他编程语言做数据交换 ...

  3. 【京东个人中心】——Nodejs/Ajax/HTML5/Mysql爬坑之注册与登录监听

    一.引言 在数据库和静态页面都创建好之后,下面就该接着完成后台Node.js监听注册和登录的部分了.这个部分主要使用的技术是:Node.js的Express框架和ajax异步请求.登录和注册的代码实现 ...

  4. HDU1285 确定比赛名次

    有N个比赛队(<=N<=),编号依次为1,,,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结 ...

  5. django中间件Middleware

    熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截. django中的中间件(middleware)就是类似钩子的一种存在.下面我们来介绍一下,并 ...

  6. iOS10适配相关

    2016年9月7日,苹果发布iOS 10.2016年9月14日,全新的操作系统iOS 10将正式上线. 作为开发者,如何适配iOS10呢? 1.Notification(通知) 自从Notificat ...

  7. BZOJ-3040-最短路(road)

    Description N个点,M条边的有向图,求点1到点N的最短路(保证存在).1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表 ...

  8. uva10003 - Cutting Sticks(简单动规)

    /* * Author: Bingo * Created Time: 2015/2/13 18:33:03 * File Name: uva10003.cpp */ #include <iost ...

  9. MQTT——入门介绍

    笔者相信大家对HTTP一定不能陌生."HTTP协议的三次握手四次挥手"相信也略有耳闻.HTTP协议的优势相信大家都明白.不然他不会这流行.然而这并不能忽略他的缺点.最大的特点就是无 ...

  10. 浅谈前后端分离与实践 之 nodejs 中间层服务(二)

    一.背景 书接上文,浅谈前后端分离与实践(一) 我们用mock服务器搭建起来了自己的前端数据模拟服务,前后端开发过程中只需定义好接口规范,便可以相互进行各自的开发任务.联调的时候,按照之前定义的开发规 ...