一、文章介绍

需求:

①某单位有多个部门,要求导出一个word文档,每个部门生成如下申报表格

②干工程的一个小伙伴因为换领导,要把40个月*30天的日报的内容从旧模板更换成新的模板

两个的基本思路一样,获得数据,塞到模板里,都可以使用使用freemarker,在这里记录一下主要内容。

二、操作步骤

1.引入maven依赖

<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.20</version>
</dependency>

2.编写工具类

其中

exportMillCertificateWord是以浏览器下载的方式生成文件

exportSaveMillCertificateWord是导出到本地的方式生成文件

public class FreeMarkerWord {private static Configuration configuration = null;  //获取模板文件的服务器位置  //private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";  private static final String templateFolder = "H:/model";  static {  configuration = new Configuration();  configuration.setDefaultEncoding("utf-8");  try {  //根据位置加载模板configuration.setDirectoryForTemplateLoading(new File(templateFolder));  } catch (IOException e) {  e.printStackTrace();  }  }  private FreeMarkerWord() {  throw new AssertionError();  }  //浏览器下载方式 map:数据;title:生成的文件名称;ftlFile:模板文件名称;public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map,String title,String ftlFile) throws IOException {  //根据文件名在模板文件夹路径中找到模板Template freemarkerTemplate = configuration.getTemplate(ftlFile);  File file = null;  InputStream fin = null;  ServletOutputStream out = null;  try {  // 调用工具类的createDoc方法生成Word文档file = createDoc(map,freemarkerTemplate);  fin = new FileInputStream(file);  response.setCharacterEncoding("utf-8");  response.setContentType("application/msword");  String fileName = title+MyUtils.getTimestampNow() + ".doc";//Content-Disposition 设置浏览器以下载的方式处理该文件名  response.setHeader("Content-Disposition", "attachment;filename="  .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));out = response.getOutputStream();  byte[] buffer = new byte[512];// 缓冲区int bytesToRead = -1;  // 通过循环将读入的Word文件的内容输出到浏览器中  while((bytesToRead = fin.read(buffer)) != -1) {  out.write(buffer, 0, bytesToRead);  }  } finally {  if(fin != null) fin.close();  if(out != null) out.close();  if(file != null) file.delete(); // 删除临时文件  }  }//导出导本地方式public static void exportSaveMillCertificateWord(Map map,String title,String ftlFile) throws IOException {  //根据文件名在模板文件夹路径中找到模板Template freemarkerTemplate = configuration.getTemplate(ftlFile);  File file = null;  InputStream fin = null;  FileOutputStream fos = null;//导出的文件.docString newTitle = ("H:/newFile/"+title).substring(0,("H:/newFile/"+title).length()-1);try {  //根据模板生成临时文件file = createDoc(map,freemarkerTemplate);//读取生成的文件fin = new FileInputStream(file);int tempByte;byte[] buffer = new byte[512];//缓冲区fos = new FileOutputStream(newTitle);//将读取的内容放到缓冲区并且写到新文件中去while((tempByte = fin.read(buffer))!=-1){fos.write(buffer,0,tempByte);//数组,开始位置,长度}} finally {  if(fin != null) fin.close();  if(fos != null) fos.close();  if(file != null) file.delete(); // 删除临时文件  }  } //创建word文档private static File createDoc(Map<?, ?> dataMap, Template template) {  String name =  "sellPlan.doc";  File f = new File(name);  Template t = template;  try {  // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开  Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");  t.process(dataMap, w);  w.close();  } catch (Exception ex) {  ex.printStackTrace();  throw new RuntimeException(ex);  }  return f;  }
}

3.获取需要写入的内容

通过查询数据库方式获取数据,简单写一下map的拼装,在模板中key匹配的位置,塞入对应的value值,循环的结构用list,在word文档中循环输出。

//业务要求:一个word文件中,每个部门为单独的【标题】+【table】
List<HashMap> resultList =  new ArrayList<HashMap>();
for(循环其中一个table的所有行){//行的其他的数据(sql查询封装好的,否则跟下面的目标名称一样,put每个字段)resultOneOne.put("goalList", goalList);//行的【目标名称】resultOneOne.put("targetName", map2.get("name"));targetList.add(resultOneOne);
}
//每个部门的标题
resultOne.put("title", year + "年度" +map.get("text")+ "单位业务职能目标完成情况申报表");
//每个部门的table
resultOne.put("targetList", targetList);
//所有部门的集合
resultList.add(resultOne);

通过读取word文档的方式获取数据,封装到list中,最后循环list生成list.size()个文件。


File dir = new File("H:/oldFile");File[] files = dir.listFiles();List<String> filNameList = new ArrayList();if (files != null) {for (int i = 0; i < files.length; i++) {String fileName = files[i].getName();filNameList.add(fileName);}}List<HashMap> contentMapList = new ArrayList<HashMap>();List<String> troubleList = new ArrayList();for(int i = 0; i < filNameList.size(); i++){String fileName = filNameList.get(i);//读取旧版文档String path = "H:/oldFile/"+fileName;String buffer = "";HashMap resultOne = new HashMap();HashMap map = new HashMap();try {if (path.endsWith("docx")) {OPCPackage opcPackage = POIXMLDocument.openPackage(path);POIXMLTextExtractor extractor = new XWPFWordExtractor(opcPackage);//获取到所有内容(没有格式)             buffer = extractor.getText();//处理内容并封装成mapString month = buffer.substring(buffer.indexOf("年")+1,buffer.indexOf("月"));map.put("month", month);extractor.close();} else {System.out.println("此文件不是word文件!");}} catch (Exception e) {//记录转换错误的文件 System.out.println("=================================================="+fileName);troubleList.add(fileName);e.printStackTrace();}

4.整理模板文件

在word中整理好格式,另存为xml格式,并保存到代码中对应的路径下,使用foxe_CHS打开并按F8格式化,对需要插入数据的内容,左侧Wbody下面是主要内容标签,右侧${}内是map的key,输出时显示的是value的内容,<#list>循环的标签,类似于for循环,例子中第一层循环标识:每个部门循环生成【标题】+【table】,第二层循环表示每个【table】中循环的条目;_index类似于for循环中的下表,<w:vMerge/>表示合并单元格等等

5.运行程序,完成功能

调用工具类的方法,FreeMarkerWord.exportMillCertificateWord(request,response,map,title,modelFile);

map:为上面拼装的数据;title:生成的目标文件名称;ftlFile:模板文件名称;

三、注意事项

在实际开发中遇到的几个小问题

1、数据中包含<>标签,会解析错误,插入<#escape x as x?html> 使其作为文本输出,可以将特殊字符转移。大小比较符号使用lt、lte、gt和gte来替代<、<=、>和>= 也可以使用括号<#if (x>y)> 可以用于比较数字和日期

Freemarker操作word文档相关推荐

  1. 使用freemarker操作word文档

    首先使用word文档写好使用的模板,然后另存为xml格式,然后对xml对想要动态生成的进行编辑(在看别人的问文档的时候说直接在word模板中把动态生成的内容用类似${user_name}的字段替换,u ...

  2. spring使用freemarker生成word文档包含表格、图片(循环插入)

    spring使用freemarker生成word文档包含表格.图片(循环插入) 效果图 因为测试数据是重复的,所以显示都是重复的数据,替换导入map中的数据可以显示不重复的数据. 操作步骤 1,创建一 ...

  3. Java操作Word文档

    Java 生成 Word 的几种方案 参考 ​ 主要有这么一些工具可以使用 Jacob.Apache POI.Java2word.iText,还有一种方法是使用XML作为模板. ​ 使用 XML 的思 ...

  4. poi操作word文档总结

    POI分段落生成纯Word动态模板并导入数据 导出数据,可以用word另存为xml格式的ftl文件,变量用${变量名}表示,然后在类中通过 freemarker去替换变量. 但是怎么导入word数据. ...

  5. Java使用freemarker生成word文档并转pdf文档

    Java使用freemarker生成word文档后转pdf 先来看看效果图 进入正题 项目需求: 为订单后生成对应的pdf文档,文档内包含图片. 方案一:使用freemarker和itext把html ...

  6. Java+freemarker 导出Word文档的实现(包括word for Mac 插入域的方法)-静态数据,动态表格list

    1. 准备环境 1.1 word版本:MacOS系统下的Office360 word for Mac下好多操作和win的不一样啊啊啊,差点栽在Mac word的模版设计上. win版本的word模版设 ...

  7. freemarker实现word文档模板动态生成

    携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情 1.写在前面 很多时候,我们可能需要根据一个word模板,动态生成,我们所需要得一个word文档. 那这 ...

  8. 关于FreeMarker生成word文档后转换为pdf得解决方法及常见问题

    关于FreeMarker生成word文档后转换为pdf得解决方法及常见问题 最近在做一个项目要求之前下载出的word简历直接变成pdf 格式进行展现.因为格式比较复杂,所以采用的时模板并用Freema ...

  9. (详细)如何使用Freemarker生成Word文档中的文本、图片、表格、附件?

    前言-Freemarker简单介绍 近期项目工作中需要编写大量格式相同但数据不同的Word文档,需要实现自动生成文档的效果,但是通过网上冲浪和官方文档搜索,相对来说,没有分类整理的文档,因此自己抽空简 ...

最新文章

  1. Linux中sudo配置
  2. .Net Core 2.2升级3.1的避坑指南
  3. STM32那点事(5)_ADC(下)
  4. c++求n的几次方_2.七年级数学:怎么求mn+mn的值?完全平方公式,用配方法
  5. windows下putty 连接linux远程管理
  6. pthreads v3下的worker和pool的使用
  7. python在win10怎么搭建_Win10下Python环境搭建与配置教程
  8. 弱网环境搭建方案选型
  9. 2021年ARINC818数字视频传输重磅新品–Helios
  10. PL/SQL基础题型
  11. 【 MATLAB 】mod 函数介绍
  12. ngx 之 location
  13. 扫码支付java,详解JAVA后端实现统一扫码支付:微信篇
  14. 二叉树的层次遍历 II - LeetCode
  15. 洛谷P1417:优先级与背包问题
  16. Debian下安装Lrzsz软件提供rz sz命令
  17. Vue3 初探 ref、reactive 、及改变数组的值
  18. Science综述: 微生物组是宿主新兴表型的来源
  19. Linux 下检测磁盘坏道的方式
  20. 冷笑话一则(另一则)

热门文章

  1. led的伏安特性曲线 matlab实现_光电池伏安特性测试MATLAB制图程序
  2. wx.showToast() 在真机中一闪而过
  3. Vivado安装—Xilinx design tool already exists for 2019.1,specify a different program program group entr
  4. Go 语言 app.conf配置文件
  5. 安装 nm-applet
  6. python自动翻译excel某一列_python批量将excel内容进行翻译写入功能
  7. DIV+CSS样式---网易盖楼
  8. C --cp2 类似cat工具的小程序。
  9. hdu 4489(排列组合+DP)
  10. 每日一言 api 接口