发表于2018-06-052019-01-01 作者 wind
/*
* Copyright (c) 2017 西安才多信息技术有限责任公司。
* 项目名称:dev
* 文件名称:DocxTemplateUtils.java
* 日期:17-10-11 下午2:18
* 作者:yangyan
*
*/
package com.deyatong.common.util;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* WORD DOCX 文件变量替换输出工具类
*/
public class DocxTemplateUtils {
Logger logger = LoggerFactory.getLogger(getClass());
/**
* 变量替换符号的正则,用来找到 ${xxx} 这样的内容,并实现替换
*/
Pattern compile = Pattern.compile("(\\$\\{([^\\}]*)\\})");
private final Map<String, ?> params; //数据填充对象
InputStream is; //读入模板文件的流
XWPFDocument doc; //内存中构建的文档对象
/**
* 使用文件路径和变量集合创建
*
* @param templateDocxFile
* @param params
*/
public DocxTemplateUtils(String templateDocxFile, Map<String, ?> params) {
this.params = params;
try {
is = new FileInputStream(templateDocxFile);
doc = new XWPFDocument(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 使用文件和和变量集合创建
*
* @param templateDocxFile
* @param params
*/
public DocxTemplateUtils(File templateDocxFile, Map<String, ?> params) {
this.params = params;
try {
is = new FileInputStream(templateDocxFile);
doc = new XWPFDocument(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 使用模板读入的流和变量集合创建
*
* @param templateDocxFileInputStream
* @param params
*/
public DocxTemplateUtils(InputStream templateDocxFileInputStream, Map<String, ?> params) {
this.params = params;
try {
is = templateDocxFileInputStream;
doc = new XWPFDocument(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 此类为poi操作word模板的工具类
**/
public XWPFDocument getDoc() {
return doc;
}
/**
* 替换所有段落中的变量
*/
public void replaceInPara() {
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
this.replaceInPara(para);
}
}
/**
* 替换传入段落里面的变量
*
* @param para 要替换的段落
*/
private void replaceInPara(XWPFParagraph para) {
String paragraphText = para.getParagraphText();
int start = paragraphText.indexOf("${");
int end = paragraphText.indexOf("}");
if (start == -1 && end == -1) { //段落中没有变量直接跳过
logger.warn("没开始,没结束,直接跳过:" + paragraphText);
return;
}
boolean isStart = false;
boolean isEnd = false;
StringBuilder varName = null;
List<XWPFRun> runs;
Matcher matcher;
runs = para.getRuns(); //不同的文字片段可能有不同的样式
logger.info("整段:" + paragraphText);
// for (int i = 0; i < runs.size(); i++) {
// XWPFRun run = runs.get(i);
// String runText = run.toString().trim();
// System.out.println(runText);
// }
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString().trim();
logger.debug(">>>处理文字片段:" + runText);
String tail = "";
if (runText.trim().length() == 0) {
continue;
}
if (varName == null) {
varName = new StringBuilder();
}
int s = runText.indexOf("${");
if (s > -1) { //有开始
int n = runText.indexOf("}", s);
if (n != -1) { //有结束
varName.append(runText.substring(s, n + 1));
isEnd = true;
if (runText.indexOf("${", n) != -1) { //一行内是否有第二个变量开启
isStart = true;
}
tail = runText.substring(n + 1);
} else { //没结束
isStart = true;
isEnd = false;
varName.append(runText.substring(s));
run.setText("", 0);
}
} else { //没开始
if (isStart) { //之前开始了
int n = runText.indexOf("}");
if (n == -1) { //没结束
varName.append(runText);
run.setText("", 0);
} else { //结束
isStart = false;
varName.append(runText.substring(0, n + 1));
if (runText.indexOf("${", n) != -1) { //一行内是否有第二个变量开启
isStart = true;
tail = runText.substring(n + 1);
}
isEnd = true;
}
}
}
if (isEnd) {
String s1 = varName.toString();
logger.warn("拼接结果:" + s1);
Object o = params.get(s1);
String value = o == null ? "" : o.toString();
run.setText(value + tail, 0);
varName = null;
isEnd = false;
}
// if (s == -1) { //如果没有开始标记后面的就不用执行了
// break;
// }
//文字替换处理
matcher = compile.matcher(runText);
while (matcher.find()) {
String group = matcher.group(1);
logger.debug("----找到变量:" + group + String.format(",文字片段内位置:(%s-%s)", matcher.start(), matcher.end()));
Object o = params.get(group);
String replacement = "";
if (o != null) {
if (o instanceof List) {
//替换的内容
logger.debug("----变量替换成为:" + StringUtils.join(o));
run.setText("", 0);
List list = (List) o;
for (Object o1 : list) {
run.addCarriageReturn();
run.setText(o1.toString());
}
break;
} else {
replacement = o.toString();
//替换的内容
runText = matcher.replaceFirst(replacement);
logger.debug("----变量替换成为:" + replacement);
run.setText(runText, 0);
logger.debug(">>>片段替换成为:" + runText);
}
}
}
}
}
/**
* 替换表格里面的变量
*/
public void replaceInTable() {
Iterator<XWPFTable> iterator = doc.getTablesIterator();
XWPFTable table;
List<XWPFTableRow> rows;
List<XWPFTableCell> cells;
List<XWPFParagraph> paras;
while (iterator.hasNext()) {
table = iterator.next();
rows = table.getRows();
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
paras = cell.getParagraphs();
for (XWPFParagraph para : paras) {
this.replaceInPara(para);
}
}
}
}
}
/**
* 关闭输入流
*/
public void closeInputStream() {
if (is != null) {
try {
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 关闭输出流
*
* @param os
*/
public void closeOutputStream(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void addTablesRows(List<List<String>> data, int tableIndex, int rowIndex) {
List<XWPFTable> list = doc.getTables();
System.out.println("----" + list.size());
XWPFTable xt = list.get(tableIndex);
if (rowIndex < 0 || (rowIndex + 1) > xt.getNumberOfRows()) {
rowIndex = xt.getNumberOfRows() - 1;
}
XWPFTableRow row1 = xt.getRow(rowIndex + 1);
if (row1 == null) {
row1 = xt.createRow();
addTablesRows(data, tableIndex, rowIndex);
return;
}
for (int i = 0; i < data.size(); i++) {
XWPFTableRow row2 = xt.getRow(rowIndex + i);
if (row2 == null) {
row2 = xt.createRow();
}
List<XWPFTableCell> cells = row2.getTableCells();
List<String> clist = data.get(i);
for (int k = 0; k < clist.size(); k++) {
XWPFTableCell cell = row2.getCell(k);
cell.setText(clist.get(k));
}
}
}
}