Word动态替换文本
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动态替换文本的更多相关文章
- C# 在word中查找及替换文本
C# 在word中查找及替换文本 在处理word文档时,很多人都会用到查找和替换功能.尤其是在处理庞大的word文档的时候,Microsoft word的查找替换功能就变得尤为重要,它不仅能让我们轻易 ...
- 利用POI 技术动态替换word模板内容
项目中需要实现一个功能,动态替换给定模板里面的内容,生成word文档提供下载功能. 中间解决了问题有: 1.页眉的文档logo图片解决,刚开始的时候,HWPFDocument 对象无法读取图片对象(已 ...
- C# 替换Word文本—— 用文档、图片、表格替换文本
编辑文档时,对一些需要修改的字符或段落可以通过查找替换的方式,快速地更改.在C# 在word中查找及替换文本一文中,主要介绍了在Word中以文本替换文本的方法,在本篇文章中,将介绍如何用一篇Word文 ...
- Java Word中的文本、图片替换功能
Word中的替换功能以查找指定文本然后替换为新的文本,可单个替换或全部替换.以下将要介绍的内容,除常见的以文本替换文本外,还将介绍使用不同对象进行替换的方法,具体可包括: 1. 指定字符串内容替换文本 ...
- Java 添加、删除、替换、格式化Word中的文本(基于Spire.Cloud.SDK for Java)
Spire.Cloud.SDK for Java提供了TextRangesApi接口可通过addTextRange()添加文本.deleteTextRange()删除文本.updateTextRang ...
- Java 程序动态替换 docx 模板中定制值的实现例子
项目系统中打印功能,导出 word 文档功能是挺常用的,本文介绍自定文档模板,程序实现模板内容中值替代的功能. 模板文件 template.docx 执行 main public static v ...
- Word 查找替换高级玩法系列之 -- 把论文中的缩写词快速变成目录下边的注释表
1. 前言 问题:Word写论文如何把文中的缩写快速转换成注释表? 原来样子: 想要的样子: 2. 步骤 使用查找替换高级用法,替换缩写顺序 选中所有文字 打开查找替换对话框,输入以下表达式: 替换后 ...
- 【实践】js 如何实现动态添加文本节点
对于我这个js 小白来说 今天鼓起勇气做起了邮箱认证这个特效 但是这次不是想说如何实现这这个特效而是想记录一下特效当中的某个部分 那就是向元素节点动态添加文本节点 百度了一下动态添加文本节点的方式 是 ...
- SSRS动态设置文本框属性
SSRS可以通过表达式动态设置文本框所有的属性,比如字体,字号,是否加粗,如下图所示: 汉字和数字英文字母占用的空间不一样,一个汉字占用两个数字和英文字母的空间,VB里有LENB取得字节数,这SSRS ...
随机推荐
- angular $q的学习笔记转帖
http://blog.segmentfault.com/bornkiller/1190000000402555 angular $q的一个不错的学习笔记
- nginx模块记录
1. ngx_http_ssl_module 让Nginx可以支持HTTPS的模块 (1)ssl on | off; #是否开启ssl功能 (2)ssl_certificate file; #当前虚拟 ...
- Highcharts 树状图(Treemap)
Highcharts 树状图(Treemap) 树状图 series 配置 设置 series 的 type 属性为 treemap ,series.type 描述了数据列类型.默认值为 " ...
- js排序算法05——快速排序
终于到了传说中的快速排序算法了,快速排序的思想和归并排序一样,都是采用分治思想,不同之处在于归并每次将数组一分为二,最后将小的数组进行比较,合并为大数组.快排是每次找一个主元,也就是基准数,按照这个基 ...
- 【转】netlink socket编程实例
[转]netlink socket编程实例 转自:http://blog.chinaunix.net/uid-14753126-id-2983915.html 关于Netlink IPC方式的介绍,请 ...
- CSS3 文本超出后显示省略号...
纯用CSS实现,主要采用代码 overflow:hidden; text-overflow:ellipsis;//这是让文本溢出后,显示成省略号. white-space:nowrap;//禁止自动换 ...
- OC-NSString
========================== 面向对象编程进阶和字符串 ========================== Δ一.类的设计模式—单例 [单例]程序允许过程中,有且仅有一块内存 ...
- OpenVPN CreateProcess Failed 问题解决
启动 OpenVPN GUI 时失败 显示如下信息 CreateProcess Failed, exe=’X:XXXXXOpenVPNbinopenvpn.exe’ cmdline=’openvpn ...
- c# 获取随机数字/字符/时间
using System; using System.Text; namespace HuaTong.General.Utility { /// <summary> /// 随机字符/数字 ...
- macOS 下安装SDKMAN 软件开发工具包管理器
SDKMAN 软件开发工具包管理器的安装非常简单,只需要打开终端,执行: $ curl -s "https://get.sdkman.io" | bash 就OK了,输出类似如下: ...