需求说明
继上次进行分页查询后,需要将这些查询出来的数据导出成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("#"," "))!}
具体空格多少就根据需求来了。
如果有什么其他好的方法请告知,谢谢。
来源:CSDN
作者:uaucome
链接:https://blog.csdn.net/uaucome/article/details/103923519