您的位置:首页 > 运维架构 > Apache

【Apache POI】Java Web根据模板导出word文件

2017-03-21 21:40 387 查看
最近工作中遇到一个需求:根据word模板文档导出word文件。

查阅了一些资料,发现Apache POI可以实现文档读写的功能,于是就研究了一下,总结如下:

Apache-POI在线Javadoc:http://tool.oschina.net/apidocs/apidoc?api=apache-POI
官方网站:http://poi.apache.org/
POI详细介绍:
Apache POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。目前POI已经有了Ruby版本。结构:

HSSF - 提供读写Microsoft Excel XLS格式档案的功能。

XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。

HWPF - 提供读写Microsoft Word DOC97格式档案的功能。

XWPF - 提供读写Microsoft Word DOC2003格式档案的功能。

HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

HDGF - 提供读Microsoft Visio格式档案的功能。

HPBF - 提供读Microsoft Publisher格式档案的功能。

HSMF - 提供读Microsoft Outlook格式档案的功能。

Java Web根据模板导出word文件

基本实现原理:
1、首先,将模板中需要用到的参数组装为一个Map集合;
2、然后读取模板文档,使用POI API解析文档输入流;
3、将Map集合中的内容写入模板文档。
功能使用了springMVC的相关功能,点击导出按钮,调用前台JS,JS代码根据springMVC的注解功能实现对后台导出方法的调用,controller控制类如下:

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import com.lmb.word.util.XwpfUtil;

/**
* Java Web根据模板导出word文件(spring MVC controller实现)
* @author lmb
* @date 2017-3-14
*
*/
public class ExportControl {

private static final Logger logger = Logger.getLogger(ExportControl.class);

/**
* 导出word
* @param param
* @param request
* @param response
*/
public void exportWord(String param,HttpServletRequest request,HttpServletResponse response){
logger.debug("导出word文件开始>>>>>>>>>>>>>");
Map<String,Object> params = packageObject();
/*params格式如下:
{
${interfacetype11}=ecsClient, ${time1}=2017/03/14 14:36:15,${code2}=4114030153,  ${interfacetype10}=ecsClient, ${percentagecode10}=6.43%, ${percentagecode11}=17.74%,
${text9}=返回欠费不能办理, ${percentagecode8}=67.71%, ${mainpercentage1}=98.57%, ${code1}=2107000024, ${svcname8}=GUSERBRAND,  ${text8}=2G用户主产品不在省份上报的列表中,
${start1}=2017-03-13 ,  ${svcname9}=GUSERBRAND, ${percentagecode2}=18.06%, ${text10}=用户状态不处于有效期,  ${percentagecode1}=78.39%, ${text2}=4114030153,
${interfacename1}=cu.tran.fusionflowquery, ${svctext1}=3G流量包查询, ${svctext2}=3G流量包查询,  ${svctext8}=用户品牌查询,${svctext9}=用户品牌查询,${svctext10}=用户品牌查询, ${svctext11}=用户品牌查询,
${text11}=4114030153, ${interfacetype8}=ecsClient,  ${svcname11}=GUSERBRAND, ${end1}=2017-03-13 ,  ${interfacename10}=cu.tran.fusionflowquery, ${interfacetype9}=ecsClient,   ${svcname10}=GUSERBRAND, ${text1}=2G用户主产品不在省份上报的列表中, ${interfacename2}=cu.tran.fusionflowquery, ${interfacename11}=cu.tran.fusionflowquery,
${code8}=2107000024, ${namelist1}=  1、3G流量包查询:24.26%  2、用户品牌查询:37.52%,
${date1}=2017-03-13 ,  ${code9}=2114000061, ${code11}=4114030153,  ${svcname1}=G3GFLUX, ${code10}=2114000066,  ${svcname2}=G3GFLUX, ${interfacetype1}=ecsClient,
${percentagecode9}=4.12%, ${interfacetype2}=ecsClient,  ${interfacename9}=cu.tran.fusionflowquery,
${indexprovince1}=陕西,  ${interfacename8}=cu.tran.fusionflowquery
}
*/
XwpfUtil xwpfUtil = new XwpfUtil();
//读入word模板
InputStream is = getClass().getClassLoader().getResourceAsStream("wordTemplate.docx");
xwpfUtil.exportWord(params,is,request,response,xwpfUtil);
logger.debug("导出word文件完成>>>>>>>>>>>>>");
}

/**
* 组装word文档中需要显示数据的集合
* @return
*/
public Map<String, Object> packageObject() {
Map<String,Object> params = new HashMap<String,Object>();
params.put("${date1}", "");//数据查询时间
params.put("${time1}", "");//生成文件时间
params.put("${indexprovince1}", "");//省份
//报告时间范围
params.put("${mainpercentage1}", "");//省份成功率
params.put("${start1}", "");//开始时间
params.put("${end1}", "");
params.put("${namelist1}", "");
// ……
return params;
}
}
控制器中用到的导出方法工具类:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

/**
* 根据模板导出word文件工具类
* @author lmb
* @date 2017-3-14
*/
public class XwpfUtil {

private static final Logger logger = Logger.getLogger(XwpfUtil.class);

/**
* 导出word文件
* @param params
* @param is
* @param request
* @param response
* @param xwpfUtil
*/
public void exportWord(Map<String, Object> params, InputStream is,
HttpServletRequest request, HttpServletResponse response,
XwpfUtil xwpfUtil) {

XWPFDocument doc = new XWPFDocument();
xwpfUtil.replaceInPara(doc,params);
xwpfUtil.replaceInTable(doc,params);
try {
OutputStream os = response.getOutputStream();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-disposition","attachment;filename=exportWord.docx");//文件名中文不显示
//把构造好的文档写入输出流
doc.write(os);
//关闭流
xwpfUtil.close(os);
xwpfUtil.close(is);
os.flush();
os.close();
} catch (IOException e) {
logger.error("文件导出错误");
}
}

/**
* 替换word模板文档段落中的变量
* @param doc 要替换的文档
* @param params 参数
*/
public void replaceInPara(XWPFDocument doc, Map<String, Object> params) {
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while(iterator.hasNext()){
para = iterator.next();
this.replaceInPara(para,params);
}
}

/**
* 替换段落中的变量
* @param para 要替换的段落
* @param params 替换参数
*/
public void replaceInPara(XWPFParagraph para, Map<String, Object> params) {
List<XWPFRun> runs;
if (((Matcher) this.matcher(para.getParagraphText())).find()) {
runs = para.getRuns();
int start = -1;
int end = -1;
String str = "";
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString().trim();
if (StringUtils.isNotBlank(runText)&&'$' == runText.charAt(0)&&'{' == runText.charAt(1)) {
start = i;
}
if (StringUtils.isNotBlank(runText)&&(start != -1)) {
str += runText;
}
if (StringUtils.isNotBlank(runText)&&'}' == runText.charAt(runText.length() - 1)) {
if (start != -1) {
end = i;
break;
}
}
}
for (int i = start; i <= end; i++) {
para.removeRun(i);
i--;
end--;
System.out.println("remove i="+i);
}
if(StringUtils.isBlank(str)){
String temp = para.getParagraphText();
str = temp.trim().substring(temp.indexOf("${"),temp.indexOf("}")+1);
}
for (String key : params.keySet()) {
if (str.equals(key)) {
para.createRun().setText(String.valueOf(params.get(key)) );
break;
}
}
}
}

/**
* 替换word模板文档表格中的变量
* @param doc 要替换的文档
* @param params 参数
*/
public void replaceInTable(XWPFDocument doc, Map<String, Object> params) {
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, params);
}
}
}
}
}

/**
* 正则匹配字符串
* @param paragraphText
* @return
*/
public Object matcher(String str) {
Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return null;
}

/**
* 关闭输入流
* @param is
*/
public void close(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 关闭输出流
* @param is
*/
public void close(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: