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

【Apache POI】Java Web根据模板导出word文件相关推荐

  1. POI根据模板导出word文件,以及word转PDF,PDF转图片再插入PDF中(防止PDF被修改)

    POI操作word和PDF POI根据模板导出word文件 word转PDF PDF转图片再插入PDF中(防止PDF被修改) POI根据模板导出word文件 一.制作word模版,${xxxx}是一会 ...

  2. Springboot--使用POI,根据word模板导出word文件

    需求:根据一个word模板,在程序中替换模板中的参数,然后根据这个模板导出word文件. 引入POI对word操作的依赖: <dependency><groupId>org.a ...

  3. java利用poi模板导出word文件

    注意:  doc文件的读取,需要导入poi-scratchpad包: docx文件读取,需要导入poi-ooxml包: 一.引入pom <dependency><groupId> ...

  4. java通过ftl模板导出word最详细教程

    百度云链接 链接: https://pan.baidu.com/s/1OEzvsFSqAelstDtu2mo5xw 提取码: fdhq https://pan.baidu.com/s/1OEzvsFS ...

  5. 利用word的freemarker模板导出word文件

    前端请求 var url = window.webApi.business.exportYearWord; jQuery('<form action="' + url + '" ...

  6. freemarker html 换行,java使用freemarker模板导出word,合并单元格,单元格内换行

    之前使用[XWPFDocument][]动态写入word,XWPFDocument不支持2003,word2003需要用HWPFDocument,HWPFDocument对于动态生成行效果不是很好,所 ...

  7. java使用freemarker模板导出word,合并单元格,单元格内换行

    之前使用XWPFDocument动态写入word,XWPFDocument不支持2003,word2003需要用HWPFDocument,HWPFDocument对于动态生成行效果不是很好,所以使用f ...

  8. Java web/springboot上传word/doc/docx文档(含图片)与HTML富文本导入/导出互相转换解析!附项目源码

    测试效果 先看下效果 文档内容如下: 上传 上传docx文档 查看解析内容 <html><head><style>p{margin-top:0pt;margin-b ...

  9. sql2java-excel(二):基于apache poi实现数据库表的导出的spring web支持

    sql2java是我几年年开始写的一个sql2java是一个轻量级数据库(SQL)访问代码(java)生成器.这几年一直在根据工作需要维护升级,最近的项目中需要对数据库的记录提供导出excel的功能. ...

最新文章

  1. 模拟二:STEMA 考试选择题模拟练习试卷(中级组) 及答案 + 解题后期更新
  2. 【Leetcode】大神总结的链表常见面试问题
  3. javascript高级程序设计 学习笔记 第五章 上
  4. .NET Core微服务 权限系统+工作流(二)工作流系统
  5. python db文件_python中查看.db文件中表格的名字及表格中的字段操作
  6. 【干货】私域电商崛起:2021见实私域流量白皮书高清6月版.pdf(附下载链接)...
  7. 将Docker image push 到azure
  8. Java基础语法一 数据类型运算符
  9. tomcat,httpd 日志格式说明
  10. 项目需求讨论--可能是用InputFilter来做的最好的金额限制
  11. TM1640数码管控制器移植STM32HAL库
  12. 中国不是没有根服务器吗?《流浪地球2》的根服务器怎么在北京?
  13. Java服务端集成环信im即时通讯
  14. 2.1.3 毫米波雷达
  15. 距离感应器下的休眠唤醒机制实现
  16. charles抓手机端的包(android手机)
  17. 2022年5月11日-12日 复盘计划
  18. python 实现根据问题在文章中找到答案
  19. 不伤眼睛的电脑背景颜色
  20. ID选择器和类选择器的合理使用

热门文章

  1. mongodb副本集架构搭建
  2. Android 开发技能图谱
  3. sqlserver游标概念与实例
  4. android contentDescription的使用
  5. android 走马灯效果
  6. MySql—索引原理
  7. Doug Cutting—访谈录
  8. git初使用(本地创建后第一次提交到git)
  9. HDU 6264 Super-palindrome
  10. bzoj1588营业额统计