java替换word模板中占位符Docx4j和Poi实现 您所在的位置:网站首页 java短信模板替换 java替换word模板中占位符Docx4j和Poi实现

java替换word模板中占位符Docx4j和Poi实现

#java替换word模板中占位符Docx4j和Poi实现| 来源: 网络整理| 查看: 265

word模板动态替换占位符(eg:${placeholder})然后生成新的word

网上搜索的不管是docx4j还是poi都只是实现了占位符在同一个文本中(读取word行数据后,行数据会分为多个文本)的替换,针对占位符没有在同一个文本或者换行了都没有实现,总结docx4j和poi两种方式终极实现占位符替换生成新word,两种方式源码如下

1、Docx4J实现代码 import cn.hutool.core.util.ObjectUtil; import com.google.common.collect.Lists; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.wml.ContentAccessor; import org.docx4j.wml.Text; import org.junit.Test; import javax.xml.bind.JAXBElement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author liuchao * @date 2020/6/8 */ public class Test01 { /** * 设置最大Text类型节点个数 如果超过此值,在删除占位符时可能会重复计算导致错误 */ private static int MAX_TEXT_SIZE = 1000000; @Test public void test() throws Exception { String docxFile = "/Users/liuchao/java/temp/1.docx"; WordprocessingMLPackage template = WordprocessingMLPackage.load(new java.io.File(docxFile)); List texts = getAllElementFromObject( template.getMainDocumentPart(), Text.class); Map map = new HashMap(); map.put("${company}", "Company Name here..."); map.put("${address}", "xxxfffadfasdf"); map.put("${secondParty}", "xxxfffadfasdf"); map.put("${year}", "xxxfffadfasdf"); map.put("${month}", "xxxfffadfasdf"); map.put("${day}", "xxxfffadfasdf"); map.put("${money}", "1000"); searchAndReplace(texts, map); template.save(new java.io.File("/Users/liuchao/java/temp/NEW.docx")); } /** * 递归获取所有的节点 * * @param obj 当前文档 * @param toSearch 要查询的节点类型 * @return java.util.List * @author liuchao * @date 2020/6/9 */ private static List getAllElementFromObject(Object obj, Class toSearch) { List result = Lists.newArrayListWithCapacity(60); if (obj instanceof JAXBElement) { obj = ((JAXBElement) obj).getValue(); } if (obj.getClass().equals(toSearch)) { result.add(obj); } else if (obj instanceof ContentAccessor) { List children = ((ContentAccessor) obj).getContent(); for (Object child : children) { result.addAll(getAllElementFromObject(child, toSearch)); } } return result; } /** * 查找并且替换占位符 * * @param texts 当前文档所有的Text类型节点 * @param values 要替换的占位符key\value * @return void * @author liuchao * @date 2020/6/9 */ public static void searchAndReplace(List texts, Map values) { // 存储占位符 位置信息集合 List placeholderList = getPlaceholderList(texts, values); if (ObjectUtil.isEmpty(placeholderList)) { return; } int[] currentPlaceholder; // 删除元素占位符 for (int i = 0; i < texts.size(); i++) { if (ObjectUtil.isEmpty(placeholderList)) { break; } currentPlaceholder = placeholderList.get(0); Text textElement = (Text) texts.get(i); String v = textElement.getValue(); StringBuilder nval = new StringBuilder(); char[] textChars = v.toCharArray(); for (int j = 0; j < textChars.length; j++) { char c = textChars[j]; if (null == currentPlaceholder) { nval.append(c); continue; } // 计算是否需要排除当前节点 int start = currentPlaceholder[0] * MAX_TEXT_SIZE + currentPlaceholder[1]; int end = currentPlaceholder[2] * MAX_TEXT_SIZE + currentPlaceholder[3]; int cur = i * MAX_TEXT_SIZE + j; // 排除'$'和'}'两个字符之间的字符 if (!(cur >= start && cur currentPlaceholder[3] && i >= currentPlaceholder[2]) { placeholderList.remove(0); if (ObjectUtil.isEmpty(placeholderList)) { currentPlaceholder = null; continue; } currentPlaceholder = placeholderList.get(0); } } textElement.setValue(nval.toString()); } } /** * 获取占位符信息,并且在占位符后面填充值 * * @param texts Text类型节点集合 * @param values 要替换的占位符key\value * @return java.util.List * @author liuchao * @date 2020/6/9 */ public static List getPlaceholderList(List texts, Map values) { // 标识忽略 int ignoreTg = 0; // 标识已读取到'$'字符 int startTg = 1; // 标识已读取到'{'字符 int readTg = 2; // 当前标识 int modeTg = ignoreTg; // 存储占位符 位置信息集合 List placeholderList = new ArrayList(); // 当前占位符 0:'$'字符Text在texts中下标 // 1:'$'字符在Text.getValue().toCharArray()数组下标 // 2: '}'字符Text在texts中下标 // 3:'}'字符在Text.getValue().toCharArray()数组下标 int[] currentPlaceholder = new int[4]; StringBuilder sb = new StringBuilder(); for (int i = 0; i < texts.size(); i++) { Text textElement = (Text) texts.get(i); String newVal = ""; String text = textElement.getValue(); StringBuilder textSofar = new StringBuilder(); char[] textChars = text.toCharArray(); for (int col = 0; col < textChars.length; col++) { char c = textChars[col]; textSofar.append(c); switch (c) { case '$': { modeTg = startTg; sb.append(c); } break; case '{': { if (modeTg == startTg) { sb.append(c); modeTg = readTg; currentPlaceholder[0] = i; currentPlaceholder[1] = col - 1; } else { if (modeTg == readTg) { sb = new StringBuilder(); modeTg = ignoreTg; } } } break; case '}': { if (modeTg == readTg) { modeTg = ignoreTg; sb.append(c); newVal += textSofar.toString() + (null == values.get(sb.toString()) ? sb.toString() : values.get(sb.toString())); textSofar = new StringBuilder(); currentPlaceholder[2] = i; currentPlaceholder[3] = col; placeholderList.add(currentPlaceholder); currentPlaceholder = new int[4]; sb = new StringBuilder(); } else if (modeTg == startTg) { modeTg = ignoreTg; sb = new StringBuilder(); } } default: { if (modeTg == readTg) { sb.append(c); } else if (modeTg == startTg) { modeTg = ignoreTg; sb = new StringBuilder(); } } } } newVal += textSofar.toString(); textElement.setValue(newVal); } return placeholderList; }

依赖jar

org.docx4j docx4j-JAXB-ReferenceImpl 8.1.7 cn.hutool hutool-all 4.6.0 com.alibaba fastjson 1.2.60

2、Poi实现代码 import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ObjectUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.junit.Test; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author liuchao * @date 2020/6/9 */ public class Test03 { // 标识忽略 static final int ignoreTg = 0; // 标识已读取到'$'字符 static final int startTg = 1; // 标识已读取到'{'字符 static final int readTg = 2; @Test public void test() throws Exception { Map map = new HashMap(); map.put("${company}", "Company Name here..."); map.put("${address}", "xxxfffadfasdf"); map.put("${secondParty}", "xxxfffadfasdf"); map.put("${year}", "xxxfffadfasdf"); map.put("${month}", "xxxfffadfasdf"); map.put("${day}", "xxxfffadfasdf"); map.put("${money}", "1000"); XWPFDocument doc = new XWPFDocument(new FileInputStream(new File("/Users/liuchao/java/temp/1.docx"))); List paragraphList = Lists.newArrayList(doc.getParagraphs()); // 获取表格中的占位符信息 getTableParagraphs(doc, paragraphList, placeholderValues); //获取占位符,并且将占位符需要替换的值写入 List placeholderList = getPlaceholderList(paragraphList, map); //清除占位符信息 clearPlaceholder(placeholderList, paragraphList); BufferedOutputStream bos = FileUtil.getOutputStream(new File("/Users/liuchao/java/temp/NEW.docx")); doc.write(bos); bos.flush(); bos.close(); doc.close(); } /** * 获取表格中占位符信息 * * @param doc 当前文档 * @param list 存储占位符信息 * @param placeholderValues 需要替换的值 * @return void * @author liuchao * @date 2020/7/6 */ private void getTableParagraphs(XWPFDocument doc, List list, Map placeholderValues) { List tables = doc.getTables(); if (ObjectUtil.isEmpty(tables)) { return; } tables.forEach(table -> table.getRows().forEach(row -> row.getTableCells().forEach(cell -> { String text = cell.getText(); if (ObjectUtil.isEmpty(text)) { return; } Iterator it = placeholderValues.keySet().iterator(); while (it.hasNext()) { String key = it.next(); if (text.indexOf(key) != -1) { list.addAll(cell.getParagraphs()); } } }))); } /** * 清除占位符信息 * * @param placeholderList 占位符位置信息 * @param paragraphList 行数据 * @return void * @author liuchao * @date 2020/6/10 */ public static void clearPlaceholder(List placeholderList, List paragraphList) { if (ObjectUtil.isEmpty(placeholderList)) { return; } int[] currentPlaceholder = placeholderList.get(0); StringBuilder tempSb = new StringBuilder(); for (int i = 0; i < paragraphList.size(); i++) { XWPFParagraph p = paragraphList.get(i); List runs = p.getRuns(); for (int j = 0; j < runs.size(); j++) { XWPFRun run = runs.get(j); String text = run.getText(run.getTextPosition()); StringBuilder nval = new StringBuilder(); char[] textChars = text.toCharArray(); for (int m = 0; m < textChars.length; m++) { char c = textChars[m]; if (null == currentPlaceholder) { nval.append(c); continue; } // 排除'$'和'}'两个字符之间的字符 int start = currentPlaceholder[0] * 1000000 + currentPlaceholder[1] * 500 + currentPlaceholder[2]; int end = currentPlaceholder[3] * 1000000 + currentPlaceholder[4] * 500 + currentPlaceholder[5]; int cur = i * 1000000 + j * 500 + m; if (!(cur >= start && cur com.alibaba fastjson 1.2.60 org.apache.poi poi 4.1.1 org.apache.poi poi-ooxml 4.1.1 org.apache.poi poi-ooxml-schemas 4.1.1



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有