一、poi word关键字替换踩过的巨坑
案例:@加盟商} 把关键字替换成为南京海瀚软件科技有限公司
通过XWPFRun获取文本时,可能会被word分成了三段 @ 加盟商 },这时无法识别一个完整的变量去做替换。
二、解决方式
1、不要在word中直接输入参数,通过在文本中写好复制粘贴过来。
经过实践证明某些字段确实可以,但是还是会出现被分段。(wps去做变量时不分段率高一些)
2、将word另存为xml文件,在编辑器中将变量在一个<w:t></w:t>节点里完整的放在里面
这种方式最终结果是可以实现的。但是在xml中找非常费神且容易改错,且文档量过大的时候,每一个都去改不太实际
3、使用代码的方式去做替换
- 先把变量处理成完整的变量(采用从@开始符拼接到}结束,中间有很多判断逻辑,看代码)
// 遍历获取段落中所有的runs
List<XWPFRun> runs = paragraph.getRuns();
// 合并逻辑
for (int i = 0; i < runs.size(); i++) {
String text0 = runs.get(i).getText(runs.get(i).getTextPosition());
if (text0 != null&&text0.contains("@")) {
int startIndex = text0.lastIndexOf("@");
int endIndex = 1;
if (startIndex != -1) {
endIndex = text0.substring(startIndex).indexOf("}");
}
if (endIndex < 0) {
// 记录分隔符中间跨越的runs数量,用于字符串拼接和替换
int num = 0;
int j = i+1 ;
for (; j < runs.size(); j++) {
String text1 = runs.get(j).getText(runs.get(j).getTextPosition());
if (text1 != null && text1.contains("}")) {
num = j - i;
break;
}
}
if (num != 0) {
// num!=0说明找到了@@配对,需要替换
StringBuilder newText = new StringBuilder();
for (int s = i; s <= i + num; s++) {
String text2 = runs.get(s).getText(runs.get(s).getTextPosition());
String replaceText = text2;
if(s==i&&text2.contains("@")&&text2.contains("}")) {
newText.append(text2);
}
else if(s==i&&text2.contains("@")) {
replaceText = text2.substring(0, text2.indexOf("@"));
newText.append(text2.substring(text2.indexOf("@")));
}
else if (text2.contains("}")) {
replaceText = text2.substring(replaceText.indexOf("}") + 1);
newText.append(text2.substring(0, text2.indexOf("}") + 1));
} else {
replaceText = "";
newText.append(text2);
}
runs.get(s).setText(replaceText, 0);
}
runs.get(i).setText(newText.toString(), 0);
i = i - 1;
}
}
}
}
最后附上poi 处理 word,关键字替换文本、图片、插入excel表、转pdf的完整案例代码
- generateWord(param, data, template, descpath); 替换
- wordToPDF(shamName, sfileName, toFileName, readname, ht_attach_id); jacob方式worf转pdf
package com.agilecontrol.fair.ifc.gold.poi.utils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagra