java通过word模板生成导出word
#生成word方法类
public class BokeWordUtils {
/**
* 根据模板生成新word文档
* 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
*
* @param inputUrl 模板存放地址
* @param outputUrl 新文档存放地址
* @param textMap 需要替换的信息集合
* @param tableList 需要插入的表格信息集合
*/
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.trim()));
//解析替换文本段落对象
BokeWordUtils.changeText(document, textMap);
//解析替换表格对象
BokeWordUtils.changeTable(document, textMap, tableList);
//生成新的word
File file = new File(outputUrl);
FileOutputStream stream = new FileOutputStream(file);
document.write(stream);
stream.close();
System.out.println("成功生成!");
} catch (IOException e) {
e.printStackTrace();
changeFlag = false;
}
return changeFlag;
}
/**
* 根据模板生成新word文档
* 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
*
* @param inputStream 模板存放地址
* @param outputUrl 新文档存放地址
* @param textMap 需要替换的信息集合
* @param tableList 需要插入的表格信息集合
*/
public static boolean changWord(InputStream inputStream, String outputUrl,
Map<String, String> textMap, List<String[]> tableList) {
//模板转换默认成功
boolean changeFlag = true;
try {
//获取docx解析对象
XWPFDocument document = new XWPFDocument(inputStream);
//解析替换文本段落对象
BokeWordUtils.changeText(document, textMap);
//解析替换表格对象
BokeWordUtils.changeTable(document, textMap, tableList);
//生成新的word
File file = new File(outputUrl);
FileOutputStream stream = new FileOutputStream(file);
document.write(stream);
stream.close();
inputStream.close();
System.out.println("成功生成!");
} catch (IOException 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();
for (XWPFParagraph paragraph : paragraphs) {
//判断此段落时候需要进行替换
String text = paragraph.getText();
if (checkText(text)) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
//替换模板原来位置
// run.setText(changeValue(run.toString(), textMap),0);
String textValue = changeValue(run.toString(), textMap);
run.setText(textValue, 0);
}
}
}
}
/**
* 替换表格对象方法
*
* @param document docx解析对象
* @param textMap 需要替换的信息集合
* @param tableList 需要插入的表格信息集合
*/
public static void changeTable(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);
if (table.getRows().size() > 1) {
//判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
if (checkText(table.getText())) {
List<XWPFTableRow> rows = table.getRows();
//遍历表格,并替换模板
eachTable(rows, textMap);
} else {
// System.out.println("插入"+table.getText());
insertTable(table, tableList);
}
}
}
}
/**
* 遍历表格
*
* @param rows 表格行对象
* @param textMap 需要替换的信息集合
*/
public static void eachTable(List<XWPFTableRow> rows, Map<String, String> textMap) {
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
//判断单元格是否需要替换
if (checkText(cell.getText())) {
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
run.setText(changeValue(run.toString(), textMap), 0);
}
}
}
}
}
}
/**
* 为表格插入数据,行数不够添加新行
*
* @param table 需要插入数据的表格
* @param tableList 插入数据集合
*/
public static void insertTable(XWPFTable table, List<String[]> tableList) {
//创建行,根据需要插入的数据添加新行,不处理表头
for (int i = 1; i < tableList.size(); i++) {
XWPFTableRow row = table.createRow();
}
//遍历表格插入数据
List<XWPFTableRow> rows = table.getRows();
for (int i = 1; i < rows.size(); i++) {
XWPFTableRow newRow = table.getRow(i);
List<XWPFTableCell> cells = newRow.getTableCells();
for (int j = 0; j < cells.size(); j++) {
XWPFTableCell cell = cells.get(j);
cell.setText(tableList.get(i - 1)[j]);
}
}
}
/**
* 判断文本中时候包含$
*
* @param text 文本
* @return 包含返回true, 不包含返回false
*/
public static boolean checkText(String text) {
boolean check = false;
if (text.indexOf("$") != -1) {
check = true;
}
return check;
}
/**
* 匹配传入信息集合与模板
*
* @param value 模板需要替换的区域
* @param textMap 传入信息集合
* @return 模板需要替换区域信息集合对应值
*/
public static String changeValue(String value, Map<String, String> textMap) {
Set<Entry<String, String>> textSets = textMap.entrySet();
for (Entry<String, String> textSet : textSets) {
//匹配模板与替换值 格式${key}
String key = "${" + textSet.getKey() + "}";
if (value.indexOf(key) != -1) {
// value = textSet.getValue();//全部参数替换
value = value.replace(key, textSet.getValue());//仅替换参数
}
}
//模板未匹配到区域替换为空
if (checkText(value)) {
value = "";
}
return value;
}
/**
* 合并docx文件
*
* @param srcDocxs 需要合并的目标docx文件
* @param destDocx 合并后的docx输出文件
*/
public static void mergeDoc(List<String> srcDocxs, String destDocx) {
OutputStream dest = null;
List<OPCPackage> opcpList = new ArrayList<OPCPackage>();
int length = null == srcDocxs ? 0 : srcDocxs.size();
/**
* 循环获取每个docx文件的OPCPackage对象
*/
for (int i = 0; i < length; i++) {
String doc = srcDocxs.get(i);
OPCPackage srcPackage = null;
try {
srcPackage = OPCPackage.open(doc);
} catch (Exception e) {
e.printStackTrace();
}
if (null != srcPackage) {
opcpList.add(srcPackage);
}
}
int opcpSize = opcpList.size();
//获取的OPCPackage对象大于0时,执行合并操作
if (opcpSize > 0) {
try {
dest = new FileOutputStream(destDocx);
XWPFDocument src1Document = new XWPFDocument(opcpList.get(0));
CTBody src1Body = src1Document.getDocument().getBody();
//OPCPackage大于1的部分执行合并操作
if (opcpSize > 1) {
for (int i = 1; i < opcpSize; i++) {
OPCPackage src2Package = opcpList.get(i);
XWPFDocument src2Document = new XWPFDocument(src2Package);
CTBody src2Body = src2Document.getDocument().getBody();
appendBody(src1Body, src2Body);
}
}
//将合并的文档写入目标文件中
src1Document.write(dest);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
IOUtils.closeQuietly(dest);
}
}
}
/**
* 合并文档内容
*
* @param src 目标文档
* @param append 要合并的文档
* @throws Exception
*/
private static void appendBody(CTBody src, CTBody append) throws Exception {
XmlOptions optionsOuter = new XmlOptions();
optionsOuter.setSaveOuter();
String appendString = append.xmlText(optionsOuter);
//替换word中得空行、根据自己需求来选择需不需要
//word文档其实是由xml文件合成得,一下替换得是作者对应得xml文件中得空行标签
appendString = appendString.replaceAll("<w:p><w:pPr><w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"24\\\"/></w:rPr></w:pPr></w:p>","");
appendString = appendString.replaceAll("<w:p><w:pPr xsi:nil=\\\"true\\\" xmlns:xsi=\\\"xsi\\\"/></w:p>","");
appendString = appendString.replaceAll("<w:p><w:pPr><w:ind w:firstLineChars=\\\"200\\\" w:firstLine=\\\"600\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"30\\\"/><w:szCs w:val=\\\"30\\\"/></w:rPr></w:pPr></w:p>","");
appendString = appendString.replaceAll("<w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/>","");;
String srcString = src.xmlText();
srcString = srcString.replaceAll("<w:p><w:pPr><w:ind w:firstLineChars=\\\"200\\\" w:firstLine=\\\"600\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"30\\\"/><w:szCs w:val=\\\"30\\\"/></w:rPr></w:pPr></w:p>","");
srcString = srcString.replaceAll("<w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/>","");
srcString = srcString.replaceAll("<w:p><w:pPr><w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"24\\\"/></w:rPr></w:pPr></w:p>","");
srcString = srcString.replaceAll("<w:p><w:pPr xsi:nil=\\\"true\\\" xmlns:xsi=\\\"xsi\\\"/></w:p>","");
String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
String mainPart = srcString.substring(srcString.indexOf(">") + 1,
srcString.lastIndexOf("<"));
String sufix = srcString.substring(srcString.lastIndexOf("<"));
String addPart = appendString.substring(appendString.indexOf(">") + 1,
appendString.lastIndexOf("<"));
CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart
+ sufix);
src.set(makeBody);
}
}
#方法调用
//获取项目内模板
InputStream url = this.getClass().getClassLoader().getResourceAsStream("xxx.docx");
//生成后的文件路径
String outPutUrl = "export/xxx.docx";
//文本填充
Map<String, String> testMap = new HashMap<String, String>();
testMap.put("name", "123");
testMap.put("age", "12");
testMap.put("sex", "女");
//表格填充
List<String[]> tableList= new ArrayList<String[]>();
tableList.add(new String[]{"1","张三","12","男"});
tableList.add(new String[]{"2","李四","33","男"});
tableList.add(new String[]{"3","王麻子","22","男"});
tableList.add(new String[]{"4","孙二娘","44","女"});
//生成
BokeWordUtils.changWord(url, outPutUrl, testMap, tableList);
#文本模板配置
#表格模板配置
#最终呈现效果