Spring Boot 集成 EasyExcel 导出 Excel 文件【复杂表头】

[复制链接]
发表于 2025-10-23 04:12:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
媒介:
Excel 导出在项目开发中是一个非经常见的业务场景,通过 Java 相干的类库可以轻松实现 Excel 的读写利用,常见的类库有 Apache POI、EasyPoi 和 EasyExcel,本篇我们要分享的是利用 EasyExcel 完成复杂表头的 Excel 导出,渴望可以资助到有须要的朋侪。
模拟业务场景
假设有一个 Excel 的导出需求,表头如下:

对于这种比力复杂的表头假如实用 Apache POI 来实现会比力的贫困,这里我们利用 EasyExcel 来实现,将会比力简单。
Spring Boot 集成 EasyExcel
Spring Boot 集成 EasyExcel 着实就是引入依靠即可利用,pom.xml 引入依靠如下:
  1. <dependency>
  2.         <groupId>com.alibaba</groupId>
  3.         <artifactId>easyexcel</artifactId>
  4.         <version>3.2.1</version>
  5. </dependency>
复制代码
EasyExcel Github 地点
EasyExcel 在 Github 上有 33K Stars,是阿里巴巴开源的,但很遗憾,迩来公布停更了,未来将渐渐进入维护模式,将继承修复 Bug,但不再自动新增功能,据相识,EasyExcel 作者玉箫客岁已经从阿里去职,迩来他公布启动 EasyExcel-Plus 项目,称这个新版本将在原有的根本上进一步提升性能和扩展功能。
创建 VO 类
在字段名上加上 @ExcelProperty 注解就可以实现上面我们这种较为复杂的 Excel 表头,创建实体类如下:
  1. package com.my.study.pojo.vo;
  2. import com.alibaba.excel.annotation.ExcelProperty;
  3. import com.alibaba.excel.annotation.write.style.ColumnWidth;
  4. import io.swagger.annotations.ApiModelProperty;
  5. import lombok.Data;
  6. /**
  7. * @ClassName: InterviewInformationVO
  8. * @Author: Author
  9. * @Date: 2024/11/13 19:31
  10. * @Description:
  11. */
  12. @Data
  13. @ColumnWidth(20)
  14. public class InterviewInformationVO {
  15.     @ApiModelProperty("姓名")
  16.     @ExcelProperty(index = 0, value = {"面试记录表", "姓名"})
  17.     @ColumnWidth(15)
  18.     private String name;
  19.     @ApiModelProperty("年龄")
  20.     @ExcelProperty(index = 1, value = {"面试记录表", "基本信息", "年龄"})
  21.     @ColumnWidth(15)
  22.     private int age;
  23.     @ApiModelProperty("性别")
  24.     @ExcelProperty(index = 2, value = {"面试记录表", "基本信息", "性别"})
  25.     @ColumnWidth(15)
  26.     private String sex;
  27.     @ApiModelProperty("籍贯")
  28.     @ExcelProperty(index = 3, value = {"面试记录表", "基本信息", "籍贯"})
  29.     @ColumnWidth(15)
  30.     private String nativePlace;
  31.     @ApiModelProperty("自我评价")
  32.     @ExcelProperty(index = 4, value = {"面试记录表", "自我评价"})
  33.     @ColumnWidth(15)
  34.     private String selfEvaluation;
  35.     @ApiModelProperty("沟通能力分")
  36.     @ExcelProperty(index = 5, value = {"面试记录表", "一轮面试","面试官A","沟通能力分"})
  37.     @ColumnWidth(15)
  38.     private int cmmunicationAkillsScore1A;
  39.     @ApiModelProperty("专业能力分")
  40.     @ExcelProperty(index = 6, value = {"面试记录表", "一轮面试","面试官A","专业能力分"})
  41.     @ColumnWidth(15)
  42.     private int professionalAbilityScore1A;
  43.     @ApiModelProperty("沟通能力分")
  44.     @ExcelProperty(index = 7, value = {"面试记录表", "一轮面试","面试官B","沟通能力分"})
  45.     @ColumnWidth(15)
  46.     private int cmmunicationAkillsScore1B;
  47.     @ApiModelProperty("专业能力分")
  48.     @ExcelProperty(index = 8, value = {"面试记录表", "一轮面试","面试官B","专业能力分"})
  49.     @ColumnWidth(15)
  50.     private int professionalAbilityScore1B;
  51.     @ApiModelProperty("沟通能力分")
  52.     @ExcelProperty(index = 9, value = {"面试记录表", "二轮面试","面试官A","沟通能力分"})
  53.     @ColumnWidth(15)
  54.     private int cmmunicationAkillsScore2A;
  55.     @ApiModelProperty("专业能力分")
  56.     @ExcelProperty(index = 10, value = {"面试记录表", "二轮面试","面试官A","专业能力分"})
  57.     @ColumnWidth(15)
  58.     private int professionalAbilityScore2A;
  59.     @ApiModelProperty("沟通能力分")
  60.     @ExcelProperty(index = 11, value = {"面试记录表", "二轮面试","面试官B","沟通能力分"})
  61.     @ColumnWidth(15)
  62.     private int cmmunicationAkillsScore2B;
  63.     @ApiModelProperty("专业能力分")
  64.     @ExcelProperty(index = 12, value = {"面试记录表", "二轮面试","面试官B","专业能力分"})
  65.     @ColumnWidth(15)
  66.     private int professionalAbilityScore2B;
  67. }
复制代码
留意看我利用在段上的注解 @ExcelProperty(index = 5, value = {“口试记录表”, “一轮口试”,“口试官A”,“沟通本领分”}),这简单的一行就实现了表头的归并处理处罚。
导出代码
导出我们选择利用输出流的方式直接返回,固然也可以导出到指定位置,代码如下:
  1. package com.my.study.controller;
  2. import cn.hutool.core.date.DateUtil;
  3. import com.alibaba.excel.EasyExcel;
  4. import com.my.study.pojo.vo.InterviewInformationVO;
  5. import io.swagger.annotations.Api;
  6. import io.swagger.annotations.ApiOperation;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.web.bind.annotation.PostMapping;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RestController;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.File;
  13. import java.io.IOException;
  14. import java.net.URLEncoder;
  15. import java.util.ArrayList;
  16. import java.util.Date;
  17. import java.util.List;
  18. /**
  19. * @ClassName: MyExcelController
  20. * @Author: Author
  21. * @Date: 2024/11/13 19:19
  22. * @Description:
  23. */
  24. @RestController
  25. @RequestMapping("/excel")
  26. @Api(tags = {"【Excel 导出控制层】"})
  27. @Slf4j
  28. public class MyExcelController {
  29.     @PostMapping("/export")
  30.     public void export(HttpServletResponse response) {
  31.         try {
  32.             List<InterviewInformationVO> exportList = new ArrayList<>();
  33.             buildInterviewInformation(exportList);
  34.             // 文件名中文名需要转义
  35.             String fileName = URLEncoder.encode("面试记录表-" + DateUtil.format(new Date(), "yyyyMMddHHmmss"), "UTF-8");
  36.             response.setContentType("application/x-download;charset=utf-8");
  37.             response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
  38.             EasyExcel.write(response.getOutputStream(), InterviewInformationVO.class).sheet("sheet1").doWrite(exportList);
  39.         } catch (IOException e) {
  40.             log.error("面试记录表导出失败,失败原因:{}", e.getMessage());
  41.             e.printStackTrace();
  42.         }
  43.     }
  44.     public void buildInterviewInformation(List<InterviewInformationVO> exportList) {
  45.         InterviewInformationVO interviewInformationVO = new InterviewInformationVO();
  46.         interviewInformationVO.setName("张三");
  47.         interviewInformationVO.setAge(25);
  48.         interviewInformationVO.setSex("男");
  49.         interviewInformationVO.setNativePlace("湖北");
  50.         interviewInformationVO.setSelfEvaluation("我是一个工作狂");
  51.         interviewInformationVO.setCmmunicationAkillsScore1A(90);
  52.         interviewInformationVO.setCmmunicationAkillsScore1B(85);
  53.         interviewInformationVO.setProfessionalAbilityScore1A(90);
  54.         interviewInformationVO.setProfessionalAbilityScore1B(90);
  55.         interviewInformationVO.setCmmunicationAkillsScore1A(85);
  56.         interviewInformationVO.setCmmunicationAkillsScore1B(80);
  57.         interviewInformationVO.setProfessionalAbilityScore1A(75);
  58.         interviewInformationVO.setProfessionalAbilityScore1B(80);
  59.         exportList.add(interviewInformationVO);
  60.     }
  61.        
  62. }
复制代码
触发导出,效果如下:

实现了我们开始说的表头效果,导出效果符合预期。
我们并没有写多少代码,就完成了看起来比力复杂的表头,这就是 EasyExcel 带来效果,当前 EasyExcel 在内存管理上也有显着的上风。
方式二实现表头
上面我们利用注解的方式实现了表头效果,下面我们利用代码的方式完成表头功能,代码如下:
  1. package com.my.study.controller;
  2. import cn.hutool.core.date.DateUtil;
  3. import com.alibaba.excel.EasyExcel;
  4. import com.my.study.pojo.vo.InterviewInformationVO;
  5. import io.swagger.annotations.Api;
  6. import io.swagger.annotations.ApiOperation;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.web.bind.annotation.PostMapping;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RestController;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.File;
  13. import java.io.IOException;
  14. import java.net.URLEncoder;
  15. import java.util.ArrayList;
  16. import java.util.Date;
  17. import java.util.List;
  18. /**
  19. * @ClassName: MyExcelController
  20. * @Author: Author
  21. * @Date: 2024/11/13 19:19
  22. * @Description:
  23. */
  24. @RestController
  25. @RequestMapping("/excel")
  26. @Api(tags = {"【Excel 导出控制层】"})
  27. @Slf4j
  28. public class MyExcelController {
  29.    @PostMapping("/export2")
  30.     public void export(HttpServletResponse response) {
  31.         try {
  32.             List<InterviewInformationVO> exportList = new ArrayList<>();
  33.             buildInterviewInformation(exportList);
  34.             // 文件名中文名需要转义
  35.             String fileName = URLEncoder.encode("面试记录表-" + DateUtil.format(new Date(), "yyyyMMddHHmmss"), "UTF-8");
  36.             response.setContentType("application/x-download;charset=utf-8");
  37.             response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
  38.             //EasyExcel.write(response.getOutputStream(), InterviewInformationVO.class).sheet("sheet1").doWrite(exportList);
  39.             EasyExcel.write(response.getOutputStream())
  40.                     // 这里放入动态头
  41.                     .head(generateExcelHead())
  42.                     .sheet()
  43.                     // 这里传入数据
  44.                     .doWrite(new ArrayList<>());
  45.             //导出到指定位置
  46.             /*EasyExcel.write("d:\interview_information.xlsx")
  47.                     // 这里放入动态头
  48.                     .head(generateExcelHead())
  49.                     .sheet()
  50.                     // 这里传入数据
  51.                     .doWrite(new ArrayList<>());*/
  52.         } catch (IOException e) {
  53.             log.error("面试记录表导出失败,失败原因:{}", e.getMessage());
  54.             e.printStackTrace();
  55.         }
  56.     }
  57.     private static List<List<String>> generateExcelHead() {
  58.         List<List<String>> result = new ArrayList<>();
  59.         List<String> head0 = new ArrayList<>();
  60.         head0.add("面试记录表");
  61.         head0.add("姓名");
  62.         result.add(head0);
  63.         List<String> head1 = new ArrayList<>();
  64.         head1.add("面试记录表");
  65.         head1.add("基本信息");
  66.         head1.add("年龄");
  67.         result.add(head1);
  68.         List<String> head2 = new ArrayList<>();
  69.         head2.add("面试记录表");
  70.         head2.add("基本信息");
  71.         head2.add("性别");
  72.         result.add(head2);
  73.         List<String> head3 = new ArrayList<>();
  74.         head3.add("面试记录表");
  75.         head3.add("基本信息");
  76.         head3.add("籍贯");
  77.         result.add(head3);
  78.         List<String> head4 = new ArrayList<>();
  79.         head4.add("面试记录表");
  80.         head4.add("自我评价");
  81.         result.add(head4);
  82.         List<String> head5 = new ArrayList<>();
  83.         head5.add("面试记录表");
  84.         head5.add("一轮面试");
  85.         head5.add("面试官A");
  86.         head5.add("沟通能力分");
  87.         result.add(head5);
  88.         List<String> head6 = new ArrayList<>();
  89.         head6.add("面试记录表");
  90.         head6.add("一轮面试");
  91.         head6.add("面试官A");
  92.         head6.add("专业能力分");
  93.         result.add(head6);
  94.         List<String> head7 = new ArrayList<>();
  95.         head7.add("面试记录表");
  96.         head7.add("一轮面试");
  97.         head7.add("面试官B");
  98.         head7.add("沟通能力分");
  99.         result.add(head7);
  100.         List<String> head8 = new ArrayList<>();
  101.         head8.add("面试记录表");
  102.         head8.add("一轮面试");
  103.         head8.add("面试官B");
  104.         head8.add("专业能力分");
  105.         result.add(head8);
  106.         List<String> head9 = new ArrayList<>();
  107.         head9.add("面试记录表");
  108.         head9.add("二轮面试");
  109.         head9.add("面试官A");
  110.         head9.add("沟通能力分");
  111.         result.add(head9);
  112.         List<String> head10 = new ArrayList<>();
  113.         head10.add("面试记录表");
  114.         head10.add("二轮面试");
  115.         head10.add("面试官A");
  116.         head10.add("专业能力分");
  117.         result.add(head10);
  118.         List<String> head11 = new ArrayList<>();
  119.         head11.add("面试记录表");
  120.         head11.add("二轮面试");
  121.         head11.add("面试官B");
  122.         head11.add("沟通能力分");
  123.         result.add(head11);
  124.         List<String> head12 = new ArrayList<>();
  125.         head12.add("面试记录表");
  126.         head12.add("二轮面试");
  127.         head12.add("面试官B");
  128.         head12.add("专业能力分");
  129.         result.add(head12);
  130.         return result;
  131.     }
  132.        
  133. }
复制代码
触发导出效果如下:

导出效果符合预期,利用代码来实现表头也很轻易,但个人更喜欢利用注解来实现。
总结:本篇简单分享利用 EasyExcel 来实现较为复杂的表头导出 Excel,感谢 EasyExcel 作者的开源,也等候 EasyExcel-Plus 的发布(预计 11月尾发布),本篇的分享渴望可以资助到有须要的朋侪。
如有不精确的地方欢迎各位指出改正。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表