我的方案可能不是最好的,却是我经过尝试觉得可用的方案,分享给大家。代码比较拙劣,希望大家指正。刚好在项目中有这个需求,因此我在网上也查了很多blog,大家的处理办法不外乎下边两个,我也是尝试过的,但都不尽如人意:
word模板:
1、不要在word中直接输入参数,通过在文本中写好复制粘贴过来。
经过实践证明某些字段确实可以,但是像我上面的模板中month_fd和month_ld这种还是被分隔到多个runs中,还有其它情况也会被分隔。
2、将word另存为xml文件,在编辑器中将变量写进去,然后存为docx。
这种方式最终结果是可以实现的。但是在xml中找非常费神且容易改错,另外如果文档过大,基本上编辑器就被卡死了。
经过上面的实践浪费了我很多时间,而且并解决不了问题,所以我就尝试自己想办法处理。方法其实也是非常简单,既然变量被分隔了,那么就可以通过代码合并,将分隔的内容合并回来,然后重新把变量设置进去。下边省略了“[”和“]”可能在文档中是普通文本,替换为非常特殊的字符就可以了。
public XWPFDocument generateDoc(String path,Map param){ //创建文档对象 XWPFDocument doc = new XWPFDocument(new FileInputstream(new File("filePath"))); //获取所有段落 ListparagraphList = doc.getParagraphs(); for(XWPFParagraph paragraph:paragraphList){ //遍历获取段落中所有的runs List runs = paragraph.getRuns(); //合并逻辑 for(Integer i = 0; i < runs.size(); i++){ String text0 = runs.get(i).getText(runs.get(i).getTextPosition()); if(text0!=null && text0.startsWith("[")){ //记录分隔符中间跨越的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.endsWith("]")){ 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()); newText.append(text2); runs.get(s).setText(null, 0); } runs.get(i).setText(newText.toString(),0); //重新定义遍历位置,跳过设置为null的位置 i=j+1; } } } //变量替换逻辑 for(int i = 0; i < runs.size(); i++){ XWPFRun run = runs.get(i); String text = run.getText(runs.get(i).getTextPosition()); if(text != null){ boolean isSetText = false; for (Map.Entry entry : param.entrySet()) { String key = entry.getKey(); if(text.indexOf(key) != -1){ isSetText = true; Object value = entry.getValue(); if (value instanceof String) {//文本替换 text = text.replace(key, value.toString()); } else if (value instanceof Map) {//图片替换 //从map中获取图片的宽、高、位置和描述信息,编写图片定义xml 放入 } } } if(isSetText){ run.setText(text,0); } } } } return doc; }