使用 freemark 實現 報表匯出
阿新 • • 發佈:2018-11-19
使用 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 打卡會報一個警告。。。有解決方案的兄弟 麻煩告訴我一聲