近期碰到一个稍微头疼的需求,将word模版中的参数替换为实际值,其中包括段落、列表(行数不够时自动递增)、页眉;本文以docx文档为例,其中代码有其他地方参考,如有冒犯,还请海涵;
模版:
![Java poi 操作word替换模版中固定参数(页眉、段落、表格)_第1张图片](http://img.e-com-net.com/image/info8/1021680d52c04cef8627b558c16760f3.jpg)
![Java poi 操作word替换模版中固定参数(页眉、段落、表格)_第2张图片](http://img.e-com-net.com/image/info8/29ac7b983a0c4efab7193add8af71cbe.jpg)
实现效果:
![Java poi 操作word替换模版中固定参数(页眉、段落、表格)_第3张图片](http://img.e-com-net.com/image/info8/152abc00e1f940f5a3da66673c33ad9c.jpg)
![Java poi 操作word替换模版中固定参数(页眉、段落、表格)_第4张图片](http://img.e-com-net.com/image/info8/639dec60fad748abbc2b54a369c23f22.jpg)
模版替换规则(可自定义):
规则:
a、类型 LIST--列表下拉;DIC--字典转为多选框;{字段名}--此为主表普通字段名;
b、格式 {#数据源名(或字典名)##字段名##类型#}
c、列表下拉 例 {#GZ##XZGX_XZGXLX_NAME##LIST##false#}--false 表示不换行,true表示换行
d、字典转为多选框 例 {#HR_ZPGL_FBZT##RCK_HHZYY##DIC##false#}
注意事项:1、本文采用poi 4.0.x,具体原因,查看API http://poi.apache.org/help/faq.html
![Java poi 操作word替换模版中固定参数(页眉、段落、表格)_第5张图片](http://img.e-com-net.com/image/info8/900b1ba37e814c10b1f464b1a81045a4.jpg)
2、模版中的{#YESORNO##YSSQB_ZSSQTY_CODE##DIC##false#} 不要直接在word上书写,要从别的地方粘贴,这样不会出现解析在多个XWPFRun中的问题
以下为代码参考:
@Override
public InputStream expFile(DynaBean template, DynaBean dataBean, Map dataSource, JSONObject returnObj) {
String fileKey="";
if(StringUtil.isNotEmpty(template.getStr("OFFICETEM_FILE"))){
fileKey=template.getStr("OFFICETEM_FILE").split("\\*")[1];
}
if(StringUtil.isEmpty(fileKey)){
returnObj.put("errorMsg","未上传模版文件!");
return null;
}
FileBO downloadFileBO=documentBusService.readFile(fileKey);
if(downloadFileBO==null){
returnObj.put("errorMsg","模版文件未找到!");
return null;
}
//文件名
String fileName = template.getStr("OFFICETEM_NAME")+ DateUtils.formatDate(new Date(),"yyyyMMdd")+".docx";
returnObj.put("fileName",fileName);
InputStream downloadFile=downloadFileBO.getFile();
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
XWPFDocument doc = new XWPFDocument(downloadFile);
//替换页眉中的变量
this.replaceHeaderOverWrite(doc,dataBean,dataSource);
//替换段落里面的变量
this.replaceInParaOverWrite(doc,dataBean,dataSource);
//替换表格里面的变量
this.replaceInTableOverWrite(doc,dataBean,dataSource);
doc.write(outputStream);
doc.close();
downloadFile.close();
//输出转输入
ByteArrayInputStream inputStream = IoUtil.toStream(outputStream.toByteArray());
return inputStream;
} catch (Exception e) {
e.printStackTrace();
returnObj.put("errorMsg","模版文件未找到!");
}
}
/***
*功能描述
* 替换页眉中的内容
* @author wenzhe.zhou
* @date 2020/5/25
* @param doc
* @param dynaBean
* @param dataSource
* @return void
*/
private void replaceHeaderOverWrite(XWPFDocument doc,DynaBean dynaBean,Map dataSource) throws Exception {
List xwpfHeaderList = doc.getHeaderList();
Iterator iterator = xwpfHeaderList.iterator();
XWPFParagraph para;
XWPFHeader xwpfHeader;
while (iterator.hasNext()) {
xwpfHeader = (XWPFHeader) iterator.next();
List xwpfParagraphList = xwpfHeader.getParagraphs();
Iterator iteratorPara = xwpfParagraphList.iterator();
while (iteratorPara.hasNext()){
para = (XWPFParagraph) iteratorPara.next();
this.replaceInParaOverWrite(para,dynaBean,dataSource);
}
}
}
/***
*功能描述
* 替换段落里面的变量
* @author wenzhe.zhou
* @date 2020/5/9
* @param doc 要替换的文档
* @param dynaBean 数据源
* @param dataSource
* @return void
*/
private void replaceInParaOverWrite(XWPFDocument doc,DynaBean dynaBean,Map dataSource) throws Exception {
Iterator iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
this.replaceInParaOverWrite(para,dynaBean,dataSource);
}
}
/**
*功能描述
* 替换段落里面的变量
* @author wenzhe.zhou
* @date 2020/5/9
* @param para
* @param dynaBean
* @param dataSource
* @return void
*/
private void replaceInParaOverWrite(XWPFParagraph para,DynaBean dynaBean,Map dataSource) throws Exception {
List runs;
Boolean matcher;
if (this.matcher(para.getParagraphText())) {
runs = para.getRuns();
for (int i=0; i valueList = substringData(runText);
String dicCode =valueList.get(0);
String paramValue = valueList.get(1);
//是否换行
Boolean isBreak = false;
if (valueList.size()>3){
isBreak= ObjectUtil.isNotEmpty(valueList.get(3))?Boolean.valueOf(valueList.get(3)):false;
}
paramValue = getRangeData( dynaBean,paramValue.trim(),dataSource);
//设置字典
this.setCheckBox(dicCode,paramValue,newRun,isBreak);
}else {
newRun.setText(runText);
}
//设置字体大小、格式
if (ObjectUtil.isNotNull(fontFamily)){
newRun.setFontFamily(fontFamily);
}
if (fontSize>=0){
newRun.setFontSize(fontSize);
}
}
}
}
}
/***
*功能描述
* 替换表格里面的变量
* @author wenzhe.zhou
* @date 2020/5/9
* @param doc
* @param dynaBean
* @param dataSource
* @return void
*/
private void replaceInTableOverWrite(XWPFDocument doc,DynaBean dynaBean,Map dataSource) throws Exception {
//模版table
Iterator iterator = doc.getTablesIterator();
XWPFTable table;
List rows;
List cells;
List paras;
//循环所有的文本进行添加定位
while (iterator.hasNext()) {
List