poi操作word模板段落中的变量替换失败问题的解决

概述:手头上有个项目,有出具报告的需求,我拿到的报告文件是一个已经写好的真实的word的文件。实现思路是把这个真实的报告中涉及到的变动数据替换为变量(${xxxx}这种方式替换),替换好后就形成了一个真正的报告模板。写好模板后,生成报告后发现有些段落中的变量无法被替换掉

poi 文档官网:Apache POI - Javadocs

有问题的报告模板部分截图:

变量替换后生成的报告截图:没有处在表格中的段落 变量 有的 $ 符号没了,有的 ${  没了,真正的变量值没有成功替换。但是发现处在表格中的段落 变量 替换是正常的。

 debug看下内存中的情况:

正常的情况下这个runs数组大小应该是2,runs[0]存的是“报告编号:”,runs[1]存的应当是“${report_no}” ,便可以替换成功,因为逻辑就是根据这个规律写的。但问题是现在runs被程序分成了4个。变量替换自然会失败了。

发现与思考:

1、发现表格中的变量替换是没有问题的。

2、思考为啥正常段落中的变量会被解析成4组了呢?

我想到的问题解决方案:

方案1、使用隐藏表格,也就是画个表格,这个表格可能只有一个单元格,在word的中不可见,然后把变量放入这个表格中。

方案2、写一套基于runs大小为4的,替换规则逻辑,封装成函数进行调用。

方案3、把word模板另存为xml格式,然后用编辑器打开,手动修改将runs[2],runs[3]中的内容放入runs[1],组成正常可识别的规则数据,修改完后改成.docx格式。

方案4、把适合用隐藏表格的地方把变量放入表格,另外找到为啥正常解析2组的runs变成4组的runs的原因然后解决。

我选择的是方案4:

我认为报告首页有一个部分可以用一个4行2列的隐藏表格进行替代,然后解决这部分变量替换失败的问题。如下图:

替换成表格后如图(我打开了网格线):

 关闭网格线如图:

 寻找为啥runs大小2组,变4组的原因:

通过测试发现,同样是非表格段落中的变量,这个${summary}变量可以正常被替换,而${report_no}和${report_time}却不可以。

请看截图找不同:

 

 

 发现不同了吗?有注意那个红色的波浪线吗?告诉你这就是2组变4组的根本原因。

解决方法:

第一步:点击文件

 

第二步:点击选项 

 

 第三步:点击校对,去掉语法检测,点击确定

最后:删掉原来不正常的变量占位符,并保存word,然后重新输入变量占位符,并保存。 

现在debug看下:奇迹发生了,正常了。

总结:poi操作模板应当注意,创建word模板时,尤其是编写占位符变量时,需要关闭掉语法检查,以避免runs出现4组甚至是n组的情况,让文档的解析以及变量替换有规则可循。

未关闭语法检查的xml如下:不规则的4组或N组

 关闭语法检测后的xml如下:规则的2组

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要使用 Apache POI 操作 Word 模板替换内容,你可以使用以下步骤: 1. 首先,你需要创建一个空白 Word 文档,并将其保存为模板文件(.dotx 或 .dotm)。 2. 使用 Apache POI 创建 Word 文档对象,使用模板文件作为输入。 ```java // 创建 Word 文档对象 XWPFDocument document = new XWPFDocument(new FileInputStream("template.dotx")); ``` 3. 获取文档的所有段落和表格,并遍历它们以查找要替换的文本。 ```java // 获取文档的所有段落和表格 List<IBodyElement> elements = document.getBodyElements(); for (IBodyElement element : elements) { if (element instanceof XWPFParagraph) { // 处理段落 XWPFParagraph paragraph = (XWPFParagraph) element; List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { String text = run.getText(0); if (text != null && text.contains("要替换的文本")) { // 替换文本 text = text.replace("要替换的文本", "替换后的文本"); run.setText(text, 0); } } } else if (element instanceof XWPFTable) { // 处理表格 XWPFTable table = (XWPFTable) element; List<XWPFTableRow> rows = table.getRows(); for (XWPFTableRow row : rows) { List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { List<XWPFParagraph> paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { String text = run.getText(0); if (text != null && text.contains("要替换的文本")) { // 替换文本 text = text.replace("要替换的文本", "替换后的文本"); run.setText(text, 0); } } } } } } } ``` 4. 使用 Apache POI 将修改后的 Word 文档保存到文件。 ```java // 保存 Word 文档 FileOutputStream out = new FileOutputStream("output.docx"); document.write(out); out.close(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值