SpringBoot后臺(tái)使用EasyExcel實(shí)現(xiàn)數(shù)據(jù)報(bào)表導(dǎo)出(含模板、樣式、美化)
引言
在企業(yè)級(jí)系統(tǒng)中,數(shù)據(jù)導(dǎo)出 Excel 是非常常見(jiàn)的需求。本文基于實(shí)際項(xiàng)目經(jīng)驗(yàn),分享如何使用 EasyExcel 實(shí)現(xiàn)復(fù)雜報(bào)表導(dǎo)出,包含:
支持按天/按小時(shí)導(dǎo)出數(shù)據(jù)
使用模板填充 Excel
支持多 Sheet、多段寫(xiě)入
使用注解設(shè)置單元格樣式
實(shí)現(xiàn)月度數(shù)據(jù)聚合與格式優(yōu)化
一、數(shù)據(jù)報(bào)表導(dǎo)出常見(jiàn)場(chǎng)景
用戶行為日志導(dǎo)出(按小時(shí)、日、月粒度)
電商交易報(bào)表(時(shí)間區(qū)間、訂單、金額匯總)
運(yùn)維監(jiān)控?cái)?shù)據(jù)導(dǎo)出
業(yè)務(wù)經(jīng)營(yíng)分析數(shù)據(jù)導(dǎo)出(如本文場(chǎng)景)
二、常用 Excel 導(dǎo)出方案對(duì)比
技術(shù)方案 | 特點(diǎn) | 優(yōu)缺點(diǎn)說(shuō)明 |
---|---|---|
Apache POI | 功能強(qiáng)大,支持復(fù)雜格式 | 復(fù)雜笨重、內(nèi)存占用高 |
JXL | 輕量級(jí) | 不支持 Excel 2007+(.xlsx) |
EasyExcel(推薦) | 阿里開(kāi)源,流式處理,速度快 | 對(duì)模板語(yǔ)法有一定學(xué)習(xí)成本 |
CSV 導(dǎo)出 | 簡(jiǎn)單快速 | 不支持樣式、格式、合并單元格等 |
三、為什么選擇 EasyExcel?
支持 大數(shù)據(jù)量導(dǎo)出,寫(xiě)入不容易 OOM
模板填充能力強(qiáng),能與設(shè)計(jì)好的 Excel 模板結(jié)合
支持注解方式配置樣式、美化表格
支持多個(gè) Sheet、多段寫(xiě)入
API 友好,文檔完善
四、EasyExcel 使用詳解
1、基本寫(xiě)法
EasyExcel.write(outputStream, MyData.class) .sheet("報(bào)表") .doWrite(dataList);
2、使用模板導(dǎo)出(推薦)
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è)置單元格樣式,無(wú)需寫(xiě) 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è)置單元格背景色、對(duì)齊方式等@ContentFontStyle
設(shè)置字體名稱、字號(hào)、加粗等@ColumnWidth
設(shè)置列寬
六、Excel 模板導(dǎo)出詳解
為什么使用模板?
使用模板導(dǎo)出可以:
預(yù)設(shè)表格樣式與布局
避免 Java 中繁瑣的樣式處理
支持多段數(shù)據(jù)寫(xiě)入(如月份匯總)
和美術(shù)設(shè)計(jì)好的 Excel 完美結(jié)合
模板示例結(jié)構(gòu)
A列 | B列 | C列 |
---|---|---|
統(tǒng)計(jì)時(shí)間: | {{startTime}} ~ {{endTime}} | |
當(dāng)前時(shí)間: | {{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();
七、項(xiàng)目實(shí)戰(zhàn)關(guān)鍵代碼講解
數(shù)據(jù)導(dǎo)出主入口
@Override public void downloadStatistics(LocalDateTime minTime, LocalDateTime maxTime) throws IOException { // 校驗(yàn)時(shí)間范圍 if (LocalDateTimeUtil.between(minTime, maxTime, ChronoUnit.DAYS) > 365) { throw new ForbiddenOperationException("查詢時(shí)間區(qū)間不能超過(guò)一年"); } 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); // 按小時(shí)導(dǎo)出 } else { downloadDayStatisticsData(response, minTime, maxTime); // 按天導(dǎo)出 } } 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)計(jì)"); 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)勢(shì) | 建議 |
---|---|
EasyExcel 寫(xiě)入快、內(nèi)存占用低 | 強(qiáng)烈建議使用模板填充,提升開(kāi)發(fā)效率 |
支持注解設(shè)置樣式、美化單元格 | 可結(jié)合注解 + WriteHandler 靈活使用 |
模板導(dǎo)出適合企業(yè)復(fù)雜格式報(bào)表 | 模板和樣式提前設(shè)計(jì)好,開(kāi)發(fā)更輕松 |
以上就是SpringBoot后臺(tái)使用EasyExcel實(shí)現(xiàn)數(shù)據(jù)報(bào)表導(dǎo)出(含模板、樣式、美化)的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot EasyExcel數(shù)據(jù)報(bào)表導(dǎo)出的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot種如何使用?EasyExcel?實(shí)現(xiàn)自定義表頭導(dǎo)出并實(shí)現(xiàn)數(shù)據(jù)格式化轉(zhuǎn)換
- SpringBoot整合EasyExcel實(shí)現(xiàn)大規(guī)模數(shù)據(jù)的并行導(dǎo)出與壓縮下載
- SpringBoot利用EasyExcel實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)
- 使用VUE+SpringBoot+EasyExcel?整合導(dǎo)入導(dǎo)出數(shù)據(jù)的教程詳解
- SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出數(shù)據(jù)
相關(guān)文章
如何利用postman完成JSON串的發(fā)送功能(springboot)
這篇文章主要介紹了如何利用postman完成JSON串的發(fā)送功能(springboot),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Java的Hibernate框架中用于操作數(shù)據(jù)庫(kù)的HQL語(yǔ)句講解
這篇文章主要介紹了Java的Hibernate框架中用于操作數(shù)據(jù)庫(kù)的HQL語(yǔ)句講解,Hibernate是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下2016-01-01java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法
這篇文章主要為大家詳細(xì)介紹了java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07java使用ZipInputStream實(shí)現(xiàn)讀取和寫(xiě)入zip文件
zip文檔可以以壓縮格式存儲(chǔ)一個(gè)或多個(gè)文件,本文主要為大家詳細(xì)介紹了java如何使用ZipInputStream讀取Zip文檔與寫(xiě)入,需要的小伙伴可以參考下2023-11-11Springboot 接收POST、json、文本數(shù)據(jù)的方法 附示例
這篇文章主要介紹了Springboot 接收POST、json、文本數(shù)據(jù)實(shí)踐,如果把 json 作為參數(shù)傳遞,我們可以使用 @requestbody 接收參數(shù),將數(shù)據(jù)直接轉(zhuǎn)換成對(duì)象,本文通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10逆轉(zhuǎn)交替合并兩個(gè)鏈表的解析與實(shí)現(xiàn)
本篇文章主要介紹了將兩個(gè)鏈表逆轉(zhuǎn)交替合并的實(shí)現(xiàn)思路與方法,需要的朋友可以參考下2015-07-07springboot實(shí)現(xiàn)登錄功能的完整步驟
這篇文章主要給大家介紹了關(guān)于springboot實(shí)現(xiàn)登錄功能的完整步驟,在web應(yīng)用程序中,用戶登錄權(quán)限驗(yàn)證是非常重要的一個(gè)步驟,文中通過(guò)代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09