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. 大小堆C++实现

    C++大小堆实现(仿函数) 具体代码如下 #pragma once #include<iostream> #include<vector> using namespace st ...

  2. 捕获enter键盘事件绑定到登录按钮

    /** *捕获enter键盘事件绑定到登录按钮 */ function keyLogin(event) { if (event.keyCode == 13) { document.getElement ...

  3. jQuery绑定事件的on()

    jQuery绑定事件 语法:$(selector).on(event,childselector,function(){}); 可以为自身的加事件(一个或多个)  也可以为其子元素加事件(一个或多个) ...

  4. H3C Huawei 交换机 IPv6环境配置

    # 使能IPv6报文转发功能. <Sysname> system-view [Sysname] ipv6 # 使能DHCPv6服务器功能. <Sysname> system-v ...

  5. 伪基站,卒于5G——本质上是基于网络和UE辅助的伪基站检测,就是将相邻基站的CI、信号强度等信息通过测量报告上报给网络,网络结合网络拓扑、配置信息等相关数据,对所有数据进行综合分析,确认在某个区域中是否存在伪基站

    伪基站,卒于5G from:https://www.huxiu.com/article/251252.html?h_s=h8 2018-07-05 21:58收藏27评论6社交通讯     本文来自微 ...

  6. form表单注册——HTML

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  7. 【后台测试】postman简介

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/6266047.html 在接口测试的过程中,经常拿到一个接口 ...

  8. Java类的finalize()方法

    Java的Object类提供了一个finalize()方法,签名如下: protected void finalize() throws Throwable { } 该方法在JVM进行垃圾回收时之行, ...

  9. python简单日志统计

    业务场景:在一个目录里,有许多日志文件,里面是一条条的json数据,格式如下,为防止一个账号被多个ip使用,现在我想知道:哪些用户登录了哪些ip,和哪些ip登录了哪些用户,如果一个ip对应一个用户,就 ...

  10. 文件目录tree显示,python

    #/usr/bin/python import os def travelTree(currentPath, count=0): if not os.path.exists(currentPath): ...