版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35704236/article/details/79942728
使用 freemark 实现 报表导出
1 准备 excel 模板
1.1 创建 excel 并且输入一点测试数据,然后以 xml 格式另存为
1.2 打开 xml 找到
前后省略 n 多东西
.....
<Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="2" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="13.5">
<Row>
<Cell>
<Data ss:Type="String">标题1</Data>
</Cell>
</Row>
<Row>
<Cell>
<Data ss:Type="String">内容1</Data>
</Cell>
</Row>
</Table>
.....
- 1.3 用 freemark 的语法改造后的样子
<Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="2" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="13.5">
<Row>
<Cell>
<Data ss:Type="String">标题1</Data>
</Cell>
</Row>
<Row>
<#list datas as data>
<Cell>
<Data ss:Type="String">${data.get("xxx")!''}</Data>
</Cell>
</#list>
</Row>
</Table>
2 Controller 写法
- 2.1 将查询的来的list 用hashMap封装一下
List datalist = 自己的业务逻辑查出来的 list
Map<String, Object> resultMap = new HashMap<>(1);
resultMap.put("datas", datalist);
String fileName = "xx表.xls";
new ReportExportHelper().doExport(resultMap, fileName, exportReportConfig, overdueTemplateName, response);
- 2.2 当 Controller 调用 ReportExportHelper 的 doExport 就完成报表导出了, 你没看错就这么简单。
3 相关工具类
3.0 ExportReportConfig
package cn.istarfinancial.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 报表导出配置类
*
* @Author: huangwenjun
* @Description:
* @Date: Created in 11:25 2018/4/14
**/
@Component
@ConfigurationProperties(prefix = "report")
public class ExportReportConfig {
/**
* 模板根目录
*/
private String templateRootPath;
/**
* 用于存放临时文件的目录
*/
private String tempReport;
public String getTemplateRootPath() {
return templateRootPath;
}
public void setTemplateRootPath(String templateRootPath) {
this.templateRootPath = templateRootPath;
}
public String getTempReport() {
return tempReport;
}
public void setTempReport(String tempReport) {
this.tempReport = tempReport;
}
}
3.1 ReportExportHelper
package cn.istarfinancial.utils;
import cn.istarfinancial.config.ExportReportConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.Map;
/**
* 报表导出帮助者
*
* @Author: huangwenjun
* @Description:
* @Date: Created in 14:59 2018/4/14
**/
public class ReportExportHelper {
private Logger logger = LoggerFactory.getLogger(ReportExportHelper.class);
/**
* 执行报表导出
*
* 导出流程 1 查询数据,然后再服务器上生成报表
* 2 将包表写回
*
* @param resultMap
* @param fileName
*/
public void doExport(Map<String, Object> resultMap, String fileName, ExportReportConfig exportReportConfig, String templateName, HttpServletResponse response) {
try {
boolean success = TemplateParseUtil.parse(exportReportConfig.getTemplateRootPath(), templateName, exportReportConfig.getTempReport() + "//" + fileName, resultMap);
if (success) {
// 模板生成成功
boolean downloaded = FileTransUtil.download(response, fileName, exportReportConfig.getTempReport() + "\\" + fileName);
if (downloaded) {
new File(exportReportConfig.getTempReport() + "//" + fileName).delete();
}
}
} catch (Exception e) {
logger.error("模板导出出错");
}
}
}
3.2 TemplateParseUtil
package cn.istarfinancial.utils;
import freemarker.template.TemplateException;
/**
* 模板解析实体类
*/
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
/**
* @Author: huangwenjun
* @Description:
* @Date: Created in 9:30 2018/4/14
**/
public class TemplateParseUtil {
/**
* 解析模板生成Excel
*
* @param templateDir 模板目录
* @param templateName 模板名称
* @param excelPath 生成的Excel文件路径
* @param data 数据参数
* @throws IOException
* @throws TemplateException
*/
public static boolean parse(String templateDir, String templateName, String excelPath, Map<String, Object> data) throws IOException, TemplateException {
//初始化工作
Configuration cfg = new Configuration();
//设置默认编码格式为UTF-8
cfg.setDefaultEncoding("UTF-8");
//全局数字格式
cfg.setNumberFormat("0.00");
//设置模板文件位置
cfg.setDirectoryForTemplateLoading(new File(templateDir));
cfg.setObjectWrapper(new DefaultObjectWrapper());
//加载模板
Template template = cfg.getTemplate(templateName, "utf-8");
try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(excelPath), "UTF-8")) {
//填充数据至Excel
template.process(data, writer);
writer.flush();
}
return true;
}
public static void main(String[] args) throws IOException, TemplateException {
List<String> str = new ArrayList<>();
for(int i = 1 ; i <= 3;i ++){
str.add("str:" + i);
}
//测试Excel文件生成
Map<String,Object> data = new HashMap<>();
data.put("strs", str);
String templatePath = "E:\\idea_project\\xingrong-report\\src\\main\\resources\\templates";
TemplateParseUtil.parse(templatePath, "overdue_template.ftl", templatePath + "/xmlTest.xls", data);
}
}
3.3 FileTransUtil
package cn.istarfinancial.utils;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
/**
* 文件传输工具类
*
* @Author: huangwenjun
* @Description:
* @Date: Created in 10:25 2018/4/14
**/
public class FileTransUtil {
/**
* 文件下载
* @param response
* @param fileName
* @param filePath
* @return 是否下载成功
*/
public static boolean download(HttpServletResponse response, String fileName, String filePath) throws IOException {
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream;charset=utf-8");
// 解决下载中文文件名的bug
fileName = new String(fileName.getBytes(), "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
byte[] buff = new byte[1024];
try (OutputStream os = response.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(filePath)))) {
int len = 0;
while ((len = bis.read(buff)) > 0) {
os.write(buff, 0, len);
}
} catch (IOException e) {
throw e;
}
return true;
}
}
4 坑 & 解决方案
上述解决方案在 wps 能 完美运行, 但是在低版本的 office 里面 无法正常打开, 会启动报错。
4.1 无脑快速解决方案
- 1 打卡 xml 设置 ExpandedColumnCount=”999999” 和 ExpandedRowCount=”999999”
4.2 正儿八经的排查错误
一般打开错误的话会 office 生成日志,而且告诉你问题所在
楼主的错误日志路径位于:
C:\Users\Administrator\AppData\Local\Microsoft\Windows\INetCache\Content.MSO
有些电脑可能找不到这个路径 需要设置两个地方
1 设置电脑 显示隐藏文件夹
2 取消勾选 隐藏受保护的操作系统文件
然后你就能看到各种错误日志了。。。
5 写在最后
最后还是有一个小问题无法解决, 就是低版本的 office 打卡会报一个警告。。。有解决方案的兄弟 麻烦告诉我一声