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

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lmb55/article/details/64519658

最近工作中遇到一个需求:根据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();
            }
        }
	}
}
展开阅读全文

没有更多推荐了,返回首页