public class WordTest2 {
public static void main(String[] args) { /** 此Map存放动态替换的内容,key-Word中定义的变量,value-要替换的内容 **/
Map map = Maps.newHashMap();
map.put("CL_XT_zlContractNo", "55555556444444888544");
map.put("LOAN_memberName", "小赵");
map.put("LOAN_certNo", "1234568524545");
map.put("LOAN_address", "重庆市沙坪坝积极");
map.put("LOAN_mobileNo", "110110110");
map.put("LOAN_memberName", "张三");
map.put("LOAN_certNo", "510254545488445");
map.put("LOAN_address", "四川省锦州达到");
map.put("LOAN_mobileNo", "023-5854555");
map.put("GUARANTEE_guaPersonName", "李四"); /** 此Map存放动态 批量生产Word中表格的内容 **/
List<String[]> tableDataList = new ArrayList<String[]>();
tableDataList.add(new String[] { "应还款日", "应还本金", "应付利息", "应还(付)总额" });
tableDataList.add(new String[] { "2018-01-01", "23", "0.2", "111" });
tableDataList.add(new String[] { "2018-01-02", "233", "0.2", "123" });
tableDataList.add(new String[] { "2018-01-03", "2333", "0.2", "321" });
tableDataList.add(new String[] { "2018-01-04", "2333", "0.2", "321" });
tableDataList.add(new String[] { "2018-01-05", "2333", "0.2", "321" });
tableDataList.add(new String[] { "2018-01-06", "2333", "0.2", "321" });
tableDataList.add(new String[] { "2018-01-07", "2333", "0.2", "321" }); String localTemplateTmpPath = "E:\\new\\TestWord.docx";
String newContractLocalPath = "E:\\new\\TestWord2.docx"; WordUtil.changWord(localTemplateTmpPath, newContractLocalPath, map, tableDataList); }
}

核心代码:

public class WordUtil {
/**
* 根据模板生成新word文档
* 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
*
* @param inputUrl 模板存放地址
* @param outputUrl 新文档存放地址
* @param textMap 需要替换的信息集合
* @param tableList 需要插入的表格信息集合
* @return 成功返回true, 失败返回false
*/
public static boolean changWord(String inputUrl, String outputUrl, Map<String, String> textMap, List<String[]> tableList) { // 模板转换默认成功
boolean changeFlag = true;
try {
// 获取docx解析对象
XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
// 解析替换文本段落对象
WordUtil.changeText(document, textMap);
// 解析替换表格对象
WordUtil.changeTable2(document, textMap, tableList); // 生成新的word
File file = new File(outputUrl);
FileOutputStream stream = new FileOutputStream(file);
document.write(stream);
stream.close();
} catch (Exception e) {
e.printStackTrace();
changeFlag = false;
}
return changeFlag;
} /**
* 替换段落文本
*
* @param document docx解析对象
* @param textMap 需要替换的信息集合
*/
public static void changeText(XWPFDocument document, Map<String, String> textMap) {
// 获取段落集合
List<XWPFParagraph> paragraphs = document.getParagraphs();
Set<String> keySet = textMap.keySet();
changeParagraph(textMap, paragraphs, keySet);
// 获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (XWPFTable table : tables) {
List<XWPFParagraph> paras;
int rcount = table.getNumberOfRows();
for (int j = 0; j < rcount; j++) {
XWPFTableRow row = table.getRow(j);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
paras = cell.getParagraphs();
changeParagraph(textMap, paras, keySet);
}
}
}
} private static void changeParagraph(Map<String, String> textMap, List<XWPFParagraph> paragraphs, Set<String> keySet) {
reBuildParagraph2(textMap, paragraphs, keySet);
} private static void reBuildParagraph2(Map<String, String> textMap, List<XWPFParagraph> paragraphs, Set<String> keySet) {
for (XWPFParagraph paragraph : paragraphs) { /**
* 此处For循环的思路:
* 将原来的XWPFParagraph中的多个XWPFRun转化成一个XWPFRun,如此做的好处是不会改变原Word的格式
* 如果直接通过XWPFParagraph获取文本内容,再进行赋值,会改变原有的Word的格式
*/
String paragraphText = paragraph.getText();
for (String key : keySet) {
String regex = "\\$\\{" + key + "\\}";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(paragraphText);
while (matcher.find()) {
List<XWPFRun> runs = paragraph.getRuns();
StringBuffer sb = new StringBuffer("");
for (XWPFRun run : runs) {
int testPosition = run.getTextPosition();
String text = run.getText(testPosition);
if (StringUtils.isNotBlank(text)) {
sb.append(text);
}
}
String newText = sb.toString();
int runLength = runs.size();
for (int i = runLength - 1; i >= 0; i--) {
if (i == 0) {
runs.get(i).setText(newText, 0);
} else {
paragraph.removeRun(i);
if (runLength > 1) {
runLength = runLength - 1;
}
}
}
}
} /**
* 此处的思路:
* 转换后的XWPFParagraph只会存在一个XWPFRun,并保留了原Word的格式
* 将XWPFRun按照正则进行截取成多个XWPFRun;(具体实现是,将原有的XWPFRun拆分成多个,删除原有的XWPFRun,再将拆分后的XWPFRun创建到原XWPFParagraph)
* 如此做的目的是:对Word中定义的变量(例如:${abc})进行格式操作,比如添加下划线
*/
List<XWPFRun> runs = paragraph.getRuns();
List<String> list = Lists.newArrayList();
if (runs.size() > 0) {
XWPFRun run = runs.get(0);
int testPosition = run.getTextPosition();
String text = run.getText(testPosition);
String regex2 = "\\$\\{\\w*\\}";
String[] strs = text.split(regex2);
String totalStr = "";
if (strs.length == 1) {
if (text.contains("${")) {
list.add(strs[0]);
String regexStr = text.substring(strs[0].length());
list.add(regexStr);
paragraph.removeRun(0);
}
} else {
if (strs.length > 1) {
for (int i = 0; i < strs.length; i++) {
String splitStr = strs[i];
totalStr = totalStr + splitStr;
String regexStr = "";
list.add(strs[i]);
if (i + 1 < strs.length) {
regexStr = text.substring(totalStr.length(), text.indexOf(strs[i + 1], totalStr.length()));
}
list.add(regexStr);
totalStr = totalStr + regexStr;
}
paragraph.removeRun(0);
}
} for (int i = 0; i < list.size(); i++) {
XWPFRun newRun = paragraph.createRun();
newRun.setText(list.get(i));
}
/**
* 此处的思路:
* 获取转换后的XWPFParagraph上的多个XWPFRun
* 将XWPFRun按照正则进行文本内容替换(动态替换)
*/
List<XWPFRun> newRuns = paragraph.getRuns();
for (XWPFRun newRun : newRuns) {
int position = newRun.getTextPosition();
String newText = newRun.getText(position);
for (String key : keySet) {
String regex = "\\$\\{" + key + "\\}";
Pattern pattern = Pattern.compile(regex);
if (null != pattern && StringUtil.isNotBlank(newText)) {
Matcher matcher = pattern.matcher(newText);
while (matcher.find()) {
String replaceText = newText.replaceAll(regex, textMap.get(key));
replaceText = " " + replaceText + " ";
newRun.setText(replaceText, 0);
newRun.setUnderline(UnderlinePatterns.SINGLE);
}
}
}
}
} }
} /**
* 替换表格对象方法
*
* @param document docx解析对象
* @param textMap 需要替换的信息集合
* @param tableList 需要插入的表格信息集合
*/
public static void changeTable2(XWPFDocument document, Map<String, String> textMap, List<String[]> tableList) {
// 获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (int i = 0; i < tables.size(); i++) {
// 只处理行数大于等于2的表格,且不循环表头
XWPFTable table = tables.get(i); // 表头
String[] tableHeads = tableList.get(0);
String tableHead = "";
for (int a = 0; a < tableHeads.length; a++) {
tableHead = tableHead + tableHeads[a];
}
String templateTableHead = table.getText().replaceAll("\t", "").replaceAll("\n", "");
System.out.println(templateTableHead.contains(tableHead));
if (templateTableHead.contains(tableHead)) {
// 创建20行7列
int rows = tableList.size();
int cols = tableList.get(0).length; for (int l = 1; l < rows; l++) {
XWPFTableRow targetRow = table.insertNewTableRow(l + 1);
targetRow.getCtRow().setTrPr(table.getRow(l).getCtRow().getTrPr());
List<XWPFTableCell> cellList = table.getRow(l).getTableCells();
XWPFTableCell targetCell = null;
for (XWPFTableCell sourceCell : cellList) {
targetCell = targetRow.addNewTableCell();
targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
targetCell.getParagraphs().get(0).getCTP().setPPr(sourceCell.getParagraphs().get(0).getCTP().getPPr());
}
XWPFTableRow row = table.getRow(l);
for (int j = 0; j < cols; j++) {
// 设置单元格内容
row.getCell(j).setText(tableList.get(l)[j]);
}
}
}
}
} }

Word动态替换文本的更多相关文章

  1. C# 在word中查找及替换文本

    C# 在word中查找及替换文本 在处理word文档时,很多人都会用到查找和替换功能.尤其是在处理庞大的word文档的时候,Microsoft word的查找替换功能就变得尤为重要,它不仅能让我们轻易 ...

  2. 利用POI 技术动态替换word模板内容

    项目中需要实现一个功能,动态替换给定模板里面的内容,生成word文档提供下载功能. 中间解决了问题有: 1.页眉的文档logo图片解决,刚开始的时候,HWPFDocument 对象无法读取图片对象(已 ...

  3. C# 替换Word文本—— 用文档、图片、表格替换文本

    编辑文档时,对一些需要修改的字符或段落可以通过查找替换的方式,快速地更改.在C# 在word中查找及替换文本一文中,主要介绍了在Word中以文本替换文本的方法,在本篇文章中,将介绍如何用一篇Word文 ...

  4. Java Word中的文本、图片替换功能

    Word中的替换功能以查找指定文本然后替换为新的文本,可单个替换或全部替换.以下将要介绍的内容,除常见的以文本替换文本外,还将介绍使用不同对象进行替换的方法,具体可包括: 1. 指定字符串内容替换文本 ...

  5. Java 添加、删除、替换、格式化Word中的文本(基于Spire.Cloud.SDK for Java)

    Spire.Cloud.SDK for Java提供了TextRangesApi接口可通过addTextRange()添加文本.deleteTextRange()删除文本.updateTextRang ...

  6. Java 程序动态替换 docx 模板中定制值的实现例子

    项目系统中打印功能,导出 word 文档功能是挺常用的,本文介绍自定文档模板,程序实现模板内容中值替代的功能. 模板文件 template.docx ​ 执行 main public static v ...

  7. Word 查找替换高级玩法系列之 -- 把论文中的缩写词快速变成目录下边的注释表

    1. 前言 问题:Word写论文如何把文中的缩写快速转换成注释表? 原来样子: 想要的样子: 2. 步骤 使用查找替换高级用法,替换缩写顺序 选中所有文字 打开查找替换对话框,输入以下表达式: 替换后 ...

  8. 【实践】js 如何实现动态添加文本节点

    对于我这个js 小白来说 今天鼓起勇气做起了邮箱认证这个特效 但是这次不是想说如何实现这这个特效而是想记录一下特效当中的某个部分 那就是向元素节点动态添加文本节点 百度了一下动态添加文本节点的方式 是 ...

  9. SSRS动态设置文本框属性

    SSRS可以通过表达式动态设置文本框所有的属性,比如字体,字号,是否加粗,如下图所示: 汉字和数字英文字母占用的空间不一样,一个汉字占用两个数字和英文字母的空间,VB里有LENB取得字节数,这SSRS ...

随机推荐

  1. LM3S之boot loader学习笔记-1

    LM3S之boot loader学习笔记-1 彭会锋 (首先声明,此系列文章编写参考了很多资料,其中一些内容是原版内容的引用和整理,并加入了一些自己的见解,我已经尽量标明引用部分,如有未全部标注部分, ...

  2. 转:在Eclipse的Debug页签中设置虚拟机参数

    http://blog.csdn.net/decorator2015/article/details/50914479 在Eclipse的Debug页签中设置虚拟机参数 步骤 1,Run->De ...

  3. 二十三 Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制

    用命令创建自动爬虫文件 创建爬虫文件是根据scrapy的母版来创建爬虫文件的 scrapy genspider -l  查看scrapy创建爬虫文件可用的母版 Available templates: ...

  4. zabbix selinux audit2allow 问题

    he following example demonstrates using audit2allow to create a policy module: A denial and the asso ...

  5. 【javascript基础】函数前面的一元操作符

    在函数前面加:+  ;  ~ !  - 等等一元操作符,javascript 引擎都会将后面的statement转换成表达式(expression),这样就可以调用了.

  6. _routing字段介绍

    一个document通过以下公式被路由到该索引下一个特定的分片: shard_num = hash(_routing) % num_primary_shards _routing的默认值是文档的_id ...

  7. [转载]面试心得与总结---BAT、网易、蘑菇街等

    转载自:http://mp.weixin.qq.com/s?__biz=MzIzMDIxNTQ3NA==&mid=2649111851&idx=1&sn=f43c42f7262 ...

  8. Android程序员学WEB前端(8)-CSS(3)-盒子内联块级定位浮动-Sublime

    转载请注明出处:http://blog.csdn.net/iwanghang/article/details/76618473 觉得博文有用,请点赞,请评论,请关注,谢谢!~ 盒子模型: <!D ...

  9. 同一台电脑的多ssh 配置

    转载自:https://w3ctrain.com/2016/03/06/mutiple-ssh-key/ ps:此文基于你已经能够正常的生成sshkey 对于sshkey的功能这里就不多做介绍了,本文 ...

  10. SEO - H标签

    前言 这两天在做网站的SEO.虽然之前SEO的资料看过很多,但是因为正职是美工的缘故,SEO的具体实施参与的较少.现在的公司有点特殊,SEO团队基本不懂代码,所以需要参与的比较多.以下内容主要是通过自 ...