基于easypoi实现自定义模板导出excel
項目中需要做一個統計報表功能,實現各種Excel報表數據導出。要求表頭能夠動態配置,表數據通過存儲過程實現,也要求能夠動態配置。
技術選型:
由于之前在項目中使用過easypoi,相對于原生apache poi,能夠用很少的代碼寫出Excel導入、導出功能,且API清晰好理解。因此優先選擇了使用easypoi,驗證功能需求能否實現。easypoi是基于apache poi開發,在此基礎上進行了封裝和擴展,特別復雜的功能就需要使用基礎poi來開發了。
開發指南:https://opensource.afterturn.cn/doc/easypoi.html
實現思路:
由于配置的報表多是復雜多級表頭,而easypoi對于動態表頭生成只支持兩級,簡單來說就是表頭最多兩行,所以這種方式就只能放棄。改選用配置動態模板的方式,先做好模板,然后配置到數據表里。
實現步驟:
Maven pom中引入jar包
ReportController類: 如下代碼僅顯示主要步驟:
@RequestMapping("/exportExcel.html")@ResponseBodypublic void exportExcel(HttpServletResponse response, HttpSession session) {// 獲取報表配置 ReportResultVo主要存儲了 標題行數、模板路徑位置、導出文件名稱等ReportResultVo config = reportService.getReportConfig(id);TemplateExportParams params = new TemplateExportParams();// 標題開始行params.setHeadingStartRow(0);// 標題行數params.setHeadingRows(config.getHeadRowNum());// 設置sheetName,若不設置該參數,則使用得原本得sheet名稱params.setSheetName("數據統計");// 獲取報表內容 // 因為表數據是根據存儲過程來實現的,不同的報表有不同的配置,// 所以使用Map<String,Object>格式來接收List<Map<String, Object>> reportBodyList = reportService.getReportBodyData(...);Map<String, Object> data = new HashMap<String, Object>();data.put("list", reportBodyList);// 獲取模板文件路徑// 這里有個很坑的地方,就是easypoi的API只能接收文件路徑,無法讀取文件流String filePath = 服務器上的某個路徑或者項目中的某個路徑// 設置模板路徑params.setTemplateUrl(filePath);// 獲取workbookWorkbook workbook = ExcelExportUtil.exportExcel(params, data);// exportFileName代表導出的文件名稱ReportUtils.export(response, workbook, exportFileName);ReportUtils類:
// Excel 導出 通過瀏覽器下載的形式public static void export(HttpServletResponse response, Workbook workbook, String fileName) throws IOException {response.setHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"), "iso8859-1"));response.setContentType("application/vnd.ms-excel;charset=UTF-8");response.setHeader("Pragma", "no-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);BufferedOutputStream bufferedOutPut = new BufferedOutputStream(response.getOutputStream());workbook.write(bufferedOutPut);bufferedOutPut.flush();bufferedOutPut.close();}模板樣式:
模板以{{$fe:list 開頭,以}}結尾,代表變遍歷數據的意思,每個字段前面的t.前綴是easypoi指定的默認值。
獲取的報表內容字段名稱要與模板里的字段一一對應
List<Map<String, Object>> reportBodyList = new ArrayList<>();Map<String,Object> values = new HashMap<String,Object>();values.put(c1,總計);values.put(c2,10);values.put(c3,5);values.put(c4,8);values.put(c5,5);values.put(c6,8);values.put(c7,6);values.put(c8,3);reportBodyList.add(values);導出的Excel結果如下:
到目前為止,已經可以實現需求了,但是實現的不夠好,尤其是上面提到的easypoi無法讀取文件流,只能從本地路徑上獲取文件模板,極大的限制了程序的靈活性。而生產環境中的項目大多都會使用文件存儲服務器,比如fastdfs,而不是把模板上傳到web服務器上的某個路徑下。
還有別的解決辦法嗎?實在無法實現需求的話就只能使用apache poi了,但是這種方式改動太大,雖然可以靈活定制excel樣式,但是實現要復雜的多。思考良久后,決定使用臨時文件的方式解決這個問題。
實現思路:
從fastdfs中獲取文件流后,寫到本地臨時目錄,然后讓easypoi從本地臨時目錄里讀取模板文件,最后再刪除臨時文件。
關鍵代碼如下:
@RequestMapping("/exportExcel.html")@ResponseBodypublic void exportExcel(HttpServletResponse response, HttpSession session) {......try{// 從fastDfs上獲取文件流 (fileStorage.readFile自己封裝的API)InputStream inputStream = fileStorage.readFile(filepath); // 模板臨時目錄String rootPath = session.getServletContext().getRealPath(“template_temp/”);// 臨時文件路徑名String filePath = rootPath + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + filename;tempFile = new File(filePath);// 保存到臨時文件ReportUtils.saveTempFile(inputStream, tempFile);// 設置模板路徑params.setTemplateUrl(filePath);// 獲取workbookWorkbook workbook = ExcelExportUtil.exportExcel(params, data);// exportFileName代表導出的文件名稱ReportUtils.export(response, workbook, exportFileName);} catch (Exception e) {throw new GeneralException(ErrorCode.REPORT_EXPORT_EXCEPTION);} finally {// 刪除臨時文件if (tempFile.exists()) {tempFile.delete();}}}ReportUtils類:
// 保存到臨時目錄 public static void saveTempFile(InputStream inputStream, File tempFile) throws IOException {if(!tempFile.getParentFile().exists()){ //如果文件的目錄不存在tempFile.getParentFile().mkdirs(); //創建目錄}OutputStream os = new FileOutputStream(tempFile);byte[] b = new byte[2048];int length;while ((length = inputStream.read(b)) > 0) {os.write(b, 0, length);}os.flush();os.close();inputStream.close(); }至此,代碼實現較好的滿足了動態配置的需要,如果大家有更好的方法,歡迎提出!
------------本文結束感謝您的閱讀------------
總結
以上是生活随笔為你收集整理的基于easypoi实现自定义模板导出excel的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 端计算(9)-android openc
- 下一篇: springboot整合Mybatis提