引言
在企业级系统中,数据导出 excel 是非常常见的需求。本文基于实际项目经验,分享如何使用 easyexcel 实现复杂报表导出,包含:
支持按天/按小时导出数据
使用模板填充 excel
支持多 sheet、多段写入
使用注解设置单元格样式
实现月度数据聚合与格式优化
一、数据报表导出常见场景
用户行为日志导出(按小时、日、月粒度)
电商交易报表(时间区间、订单、金额汇总)
运维监控数据导出
业务经营分析数据导出(如本文场景)
二、常用 excel 导出方案对比
| 技术方案 | 特点 | 优缺点说明 |
|---|---|---|
| apache poi | 功能强大,支持复杂格式 | 复杂笨重、内存占用高 |
| jxl | 轻量级 | 不支持 excel 2007+(.xlsx) |
| easyexcel(推荐) | 阿里开源,流式处理,速度快 | 对模板语法有一定学习成本 |
| csv 导出 | 简单快速 | 不支持样式、格式、合并单元格等 |
三、为什么选择 easyexcel?
支持 大数据量导出,写入不容易 oom
模板填充能力强,能与设计好的 excel 模板结合
支持注解方式配置样式、美化表格
支持多个 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); // 填充数据区域 {}
writer.finish();五、样式注解介绍
easyexcel 提供了丰富的注解用于设置单元格样式,无需写 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设置单元格背景色、对齐方式等@contentfontstyle设置字体名称、字号、加粗等@columnwidth设置列宽
六、excel 模板导出详解
为什么使用模板?
使用模板导出可以:
预设表格样式与布局
避免 java 中繁琐的样式处理
支持多段数据写入(如月份汇总)
和美术设计好的 excel 完美结合
模板示例结构

| a列 | b列 | c列 |
|---|---|---|
| 统计时间: | {{starttime}} ~ {{endtime}} | |
| 当前时间: | {{currenttime}} | |
| 月份: | {{month}} | |
| 日期 | 用户数 | 销售额 |
| {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();七、项目实战关键代码讲解
数据导出主入口
@override
public void downloadstatistics(localdatetime mintime, localdatetime maxtime) throws ioexception {
// 校验时间范围
if (localdatetimeutil.between(mintime, maxtime, chronounit.days) > 365) {
throw new forbiddenoperationexception("查询时间区间不能超过一年");
}
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, "月统计");
excelmonthdata data = new excelmonthdata();
data.setmonth(mintime.getmonthvalue() + "月");
data.setstatisticsdatalist(monthlist);
data.setmonthaggregation(monthsummary);
result.add(data);
mintime = mintime.plusmonths(1);
}
return result;
}八、总结与建议
| 优势 | 建议 |
|---|---|
| easyexcel 写入快、内存占用低 | 强烈建议使用模板填充,提升开发效率 |
| 支持注解设置样式、美化单元格 | 可结合注解 + writehandler 灵活使用 |
| 模板导出适合企业复杂格式报表 | 模板和样式提前设计好,开发更轻松 |
以上就是springboot后台使用easyexcel实现数据报表导出(含模板、样式、美化)的详细内容,更多关于springboot easyexcel数据报表导出的资料请关注代码网其它相关文章!
发表评论