FreeMarker---通过ftl导出word

社会主义新天地 提交于 2020-01-11 06:27:37

需求说明

继上次进行分页查询后,需要将这些查询出来的数据导出成word和Excel。
导出word的方式有很多种,这边使用FreeMarker来操作。

具体实现

1.目标数据

如图
在这里插入图片描述

2.word模板

如图
在这里插入图片描述
注意:如果需要排版的好看一些,最好在word中调整好样式。

3.转换ftl

将word的样式排版好后,将word另存为xml格式,之后将该文件的扩展名改成ftl格式,放置在项目的ftl文件夹下,如图:
在这里插入图片描述

4.引入freemarker

在pom.xml中引入freemarker:

		<!-- 引入freemarker -->
		<dependency>
		    <groupId>org.freemarker</groupId>
		    <artifactId>freemarker</artifactId>
		    <version>2.3.29</version>
		</dependency>

5.代码实现

WordUtils.java

package com.yzpt.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * Description: Word导出工具类
 *
 * @author yzp
 *
 * @date 2019年9月24日
 *
 */
public class WordUtils {
	public static File wordCreate(Map<String, Object> dataMap, String fileName, String ftlName) {
		//返回的文件
		File outFile = new File(fileName);
		//创建配置实例
		Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
		//设置编码
		configuration.setDefaultEncoding("UTF-8");
		//html或ftl模板文件统一放置html或ftl包下
		configuration.setClassForTemplateLoading(WordUtils.class, "/common/ftl/");
		Template template = null;
		try {
			//获取模板
			template = configuration.getTemplate(ftlName);
			//将模板和数据模型合并生成文件
			Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
			//生成文件
			template.process(dataMap, out);
			//关闭流
			out.flush();
			out.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return outFile;
	}
	
	public static void outPutData(HttpServletResponse response, String ftlName, String outFileName, Map<String, Object> dataMap) {
		File file = null;
		InputStream fin = null;
		ServletOutputStream out = null;
		try {
			file = wordCreate(dataMap, outFileName, ftlName);
			fin = new FileInputStream(file);
			response.setCharacterEncoding("utf-8");
			response.setContentType("application/msword");
			response.addHeader("Content-Disposition", "attachment;filename=" + outFileName);
			out = response.getOutputStream();
			byte[] buffer = new byte[1024]; // 缓冲
			int bytesToRead = -1;
			while ((bytesToRead = fin.read(buffer)) != -1) {
				out.write(buffer, 0, bytesToRead);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(fin != null) {
				try {
					fin.close();
				}catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(file != null) {
				file.delete();
			}
		}
	}
}

6.代码调用

 /**  
     * Description: 通过word导出
     *
     * @param request
     * @param response  
     *
     */  
    @RequestMapping("/exportUserByWord")
	public void exportUserByWord(HttpServletRequest request, HttpServletResponse response) {
    	List<User> users = userService.findByList();
    	Map<String, Object> dataMap = new HashMap<String, Object>();
		String ftlName = "userList.ftl";
		String outFileName = "userList.doc";
		dataMap.put("users", users);
		//导出pdf
		WordUtils.outPutData(response, ftlName, outFileName, dataMap);
    }

7.调用结果

如图
在这里插入图片描述

8.几个坑说明一下

经常出错的2个:
1.导出word的数据不能为空,如果为空的话,需要在变量中添加"!”。
如文件名称为空的话,这样写,${fileName},会造成导出的word打不开,需要这样写,${fileName!}
2.导出word的数据不能有特殊字符,比如"《》" 、"<>"等,如果包含这些字符,需要在变量中添加“?html”。
同样,文件名称中包含特殊字符的话,也会造成导出的word打不开,需要这样写,${fileName?html},也可能文件名称也为空,这时候需要这样写${(fileName?html)!}

后面一个是近期遇到的,需要将保存在一个字段中的数据换行后缩进2个字符,比如说保存的数据是这样的:“有你的世界\n真好”,通过变量导出后的数据是换行后没有缩进2个字符,如图:
在这里插入图片描述
而需求是这样的
在这里插入图片描述
搜索也没搜到什么好方法,只能替换了。
解决方案:先将 “\n“在后台替换成“*#”,然后再ftl上这样输入
${((content?html?replace("*","<w:br/>"))?replace("#"," "))!}
具体空格多少就根据需求来了。
如果有什么其他好的方法请告知,谢谢。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!