SpringBoot后臺使用EasyExcel實現(xiàn)數(shù)據(jù)報表導出(含模板、樣式、美化)
引言
在企業(yè)級系統(tǒng)中,數(shù)據(jù)導出 Excel 是非常常見的需求。本文基于實際項目經(jīng)驗,分享如何使用 EasyExcel 實現(xiàn)復雜報表導出,包含:
支持按天/按小時導出數(shù)據(jù)
使用模板填充 Excel
支持多 Sheet、多段寫入
使用注解設(shè)置單元格樣式
實現(xiàn)月度數(shù)據(jù)聚合與格式優(yōu)化
一、數(shù)據(jù)報表導出常見場景
用戶行為日志導出(按小時、日、月粒度)
電商交易報表(時間區(qū)間、訂單、金額匯總)
運維監(jiān)控數(shù)據(jù)導出
業(yè)務(wù)經(jīng)營分析數(shù)據(jù)導出(如本文場景)
二、常用 Excel 導出方案對比
技術(shù)方案 | 特點 | 優(yōu)缺點說明 |
---|---|---|
Apache POI | 功能強大,支持復雜格式 | 復雜笨重、內(nèi)存占用高 |
JXL | 輕量級 | 不支持 Excel 2007+(.xlsx) |
EasyExcel(推薦) | 阿里開源,流式處理,速度快 | 對模板語法有一定學習成本 |
CSV 導出 | 簡單快速 | 不支持樣式、格式、合并單元格等 |
三、為什么選擇 EasyExcel?
支持 大數(shù)據(jù)量導出,寫入不容易 OOM
模板填充能力強,能與設(shè)計好的 Excel 模板結(jié)合
支持注解方式配置樣式、美化表格
支持多個 Sheet、多段寫入
API 友好,文檔完善
四、EasyExcel 使用詳解
1、基本寫法
EasyExcel.write(outputStream, MyData.class) .sheet("報表") .doWrite(dataList);
2、使用模板導出(推薦)
ExcelWriter writer = EasyExcel .write(outputStream, MyData.class) .withTemplate(templateInputStream) .build(); WriteSheet sheet = EasyExcel.writerSheet().build(); writer.fill(variableMap, sheet); // 填充 {{變量}} writer.write(dataList, sheet); // 填充數(shù)據(jù)區(qū)域 {} writer.finish();
五、樣式注解介紹
EasyExcel 提供了豐富的注解用于設(shè)置單元格樣式,無需寫 handler:
@ColumnWidth(15) @ContentStyle( fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 42, verticalAlignment = VerticalAlignmentEnum.CENTER, horizontalAlignment = HorizontalAlignmentEnum.CENTER ) @ContentFontStyle( fontName = "宋體", fontHeightInPoints = 12, bold = BooleanEnum.TRUE ) @Data public class StatisticsData { private String statTime; private String regionName; private Integer userCount; private BigDecimal amount; }
解釋:
@ContentStyle
設(shè)置單元格背景色、對齊方式等@ContentFontStyle
設(shè)置字體名稱、字號、加粗等@ColumnWidth
設(shè)置列寬
六、Excel 模板導出詳解
為什么使用模板?
使用模板導出可以:
預(yù)設(shè)表格樣式與布局
避免 Java 中繁瑣的樣式處理
支持多段數(shù)據(jù)寫入(如月份匯總)
和美術(shù)設(shè)計好的 Excel 完美結(jié)合
模板示例結(jié)構(gòu)
A列 | B列 | C列 |
---|---|---|
統(tǒng)計時間: | {{startTime}} ~ {{endTime}} | |
當前時間: | {{currentTime}} | |
月份: | {{month}} | |
日期 | 用戶數(shù) | 銷售額 |
{data} | ||
月匯總: | {monthAggregation} |
Java 填充代碼
ExcelWriter excelWriter = EasyExcel .write(response.getOutputStream(), StatisticsData.class) .withTemplate(getClass().getClassLoader().getResourceAsStream("static/day_statistics_template.xlsx")) .autoCloseStream(false) .registerWriteHandler(easyExcelUtil) .build(); Map<String, Object> map = new HashMap<>(); map.put("startTime", "2025-01-01"); map.put("endTime", "2025-01-31"); map.put("currentTime", "2025/05/04 10:00:00"); excelWriter.fill(map, writeSheet); excelWriter.write(dataList, writeSheet); // 支持多段填充 excelWriter.finish();
七、項目實戰(zhàn)關(guān)鍵代碼講解
數(shù)據(jù)導出主入口
@Override public void downloadStatistics(LocalDateTime minTime, LocalDateTime maxTime) throws IOException { // 校驗時間范圍 if (LocalDateTimeUtil.between(minTime, maxTime, ChronoUnit.DAYS) > 365) { throw new ForbiddenOperationException("查詢時間區(qū)間不能超過一年"); } HttpServletResponse response = ResponseUtils.getResponse(); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); response.setHeader(BODY_PROCESSED, "1"); try { if (LocalDateTimeUtil.beginOfDay(maxTime).equals(minTime)) { downloadHourStatisticsData(response, minTime); // 按小時導出 } else { downloadDayStatisticsData(response, minTime, maxTime); // 按天導出 } } catch (Exception e) { response.reset(); response.setContentType("application/json"); response.getWriter().println(JSON.toJSONString(Map.of( "status", "failure", "message", "下載失敗: " + e.getMessage() ))); } }
按月分組聚合邏輯
private List<ExcelMonthData> cutDataListByMonth(List<StatisticsData> statisticsDataList) { LocalDateTime minTime = LocalDateTimeUtil.parse(statisticsDataList.get(0).getStatTime(), DatePattern.PURE_DATE_PATTERN); LocalDateTime maxTime = LocalDateTimeUtil.parse(statisticsDataList.get(statisticsDataList.size() - 1).getStatTime(), DatePattern.PURE_DATE_PATTERN); Map<String, List<StatisticsData>> collect = statisticsDataList.stream() .collect(Collectors.groupingBy(s -> s.getStatTime().substring(0, 6))); List<ExcelMonthData> result = new ArrayList<>(); while (!minTime.isAfter(maxTime)) { String monthKey = LocalDateTimeUtil.format(minTime, "yyyyMM"); List<StatisticsData> monthList = collect.getOrDefault(monthKey, new ArrayList<>()); monthList.forEach(s -> s.setStatTime(excelDateFormatter(s.getStatTime()))); AggregationStatisticsData monthSummary = getAggregationStatisticsData(monthList, "月統(tǒng)計"); ExcelMonthData data = new ExcelMonthData(); data.setMonth(minTime.getMonthValue() + "月"); data.setStatisticsDataList(monthList); data.setMonthAggregation(monthSummary); result.add(data); minTime = minTime.plusMonths(1); } return result; }
八、總結(jié)與建議
優(yōu)勢 | 建議 |
---|---|
EasyExcel 寫入快、內(nèi)存占用低 | 強烈建議使用模板填充,提升開發(fā)效率 |
支持注解設(shè)置樣式、美化單元格 | 可結(jié)合注解 + WriteHandler 靈活使用 |
模板導出適合企業(yè)復雜格式報表 | 模板和樣式提前設(shè)計好,開發(fā)更輕松 |
以上就是SpringBoot后臺使用EasyExcel實現(xiàn)數(shù)據(jù)報表導出(含模板、樣式、美化)的詳細內(nèi)容,更多關(guān)于SpringBoot EasyExcel數(shù)據(jù)報表導出的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何利用postman完成JSON串的發(fā)送功能(springboot)
這篇文章主要介紹了如何利用postman完成JSON串的發(fā)送功能(springboot),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07Java的Hibernate框架中用于操作數(shù)據(jù)庫的HQL語句講解
這篇文章主要介紹了Java的Hibernate框架中用于操作數(shù)據(jù)庫的HQL語句講解,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2016-01-01java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法
這篇文章主要為大家詳細介紹了java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07java使用ZipInputStream實現(xiàn)讀取和寫入zip文件
zip文檔可以以壓縮格式存儲一個或多個文件,本文主要為大家詳細介紹了java如何使用ZipInputStream讀取Zip文檔與寫入,需要的小伙伴可以參考下2023-11-11Springboot 接收POST、json、文本數(shù)據(jù)的方法 附示例
這篇文章主要介紹了Springboot 接收POST、json、文本數(shù)據(jù)實踐,如果把 json 作為參數(shù)傳遞,我們可以使用 @requestbody 接收參數(shù),將數(shù)據(jù)直接轉(zhuǎn)換成對象,本文通過示例代碼介紹的非常詳細,需要的朋友可以參考下2023-10-10