使用 EasyExcel 封装通用 Excel 导出工具类

在企业应用中,经常需要把后台数据导出成 Excel 文件供用户下载。在我们的项目中,涉及"成品"、"材料"等模块的数据导出。本文将分享如何使用 EasyExcel 封装一个通用的 Excel 导出工具类 ExcelExportUtil,支持单个 Sheet 和多 Sheet 导出。

1. 背景问题

在没有封装工具类之前,导出 Excel 的代码通常是这样的:

复制代码
@PostMapping("/export/{orderNumber}")
private void exportModal2BillHead(@PathVariable String orderNumber, HttpServletResponse response) throws IOException {
    List<Modal2BillHeadVO> list = modal2BillHeadService.getQueryOrderInfo(orderNumber);

    // 转换为导出 VO
    List<Modal2BillExportVO> exportList = list.stream().map(v -> {
        Modal2BillExportVO vo = new Modal2BillExportVO();
        vo.setMaterialStockOutId(String.valueOf(v.getMaterialStockOutId()));
        vo.setDoCno(v.getDoCno());
        vo.setCreatedOn(String.valueOf(v.getCreatedOn()));
        vo.setCreatedBy(v.getCreatedBy());
        vo.setOrderNumber(v.getOrderNumber());
        vo.setItemCode(v.getItemCode());
        vo.setItemName(v.getItemName());
        vo.setItemSpecs(v.getItemSpecs());
        vo.setStoreUomoty(v.getStoreUomoty());
        vo.setCostUomoty(v.getCostUomoty());
        vo.setUom(v.getUom());
        vo.setWhName(v.getWhName());
        vo.setDoctype(v.getDoctype());
        vo.setTransferFormType(v.getTransferFormType());
        vo.setPurchasePrice(v.getPurchasePrice());
        return vo;
    }).collect(Collectors.toList());

    // Excel 导出逻辑
    String fileName = "材料提库导出";
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
    response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");

    ServletOutputStream out = response.getOutputStream();
    EasyExcel.write(out, Modal2BillExportVO.class)
            .sheet("成品提库")
            .doWrite(exportList == null ? new ArrayList<>() : exportList);

    out.flush();
    out.close();
}

❌ 缺点:

  1. 每个导出都要重复写响应头、流操作。

  2. 代码臃肿,可维护性差。

  3. 不方便支持多 Sheet 或通用导出。

2. 封装工具类:ExcelExportUtil

为了提高可复用性,我们封装了一个通用工具类,核心设计思想:

  • 单个 Sheet 导出:快速导出单个 Excel。

  • 多 Sheet 导出:在一个 Excel 文件中包含多个 Sheet 标签页。

  • 泛型支持 :通过 <T> 泛型,可以导出任意带 @ExcelProperty 注解的实体类。

    public class ExcelExportUtil {

    复制代码
      // 单个 Sheet 导出
      public static <T> void export(HttpServletResponse response, String fileName, Class<T> clazz, List<T> dataList) {
          try {
              setResponseHeader(response, fileName);
              ServletOutputStream out = response.getOutputStream();
              EasyExcel.write(out, clazz)
                      .sheet(fileName)
                      .doWrite(dataList == null ? new ArrayList<>() : dataList);
              out.flush();
              out.close();
          } catch (Exception e) {
              throw new RuntimeException("Excel 导出失败:" + e.getMessage(), e);
          }
      }
    
      // 多 Sheet 导出
      public static void exportMultiSheet(HttpServletResponse response, String fileName, Map<String, SheetData<?>> sheets) {
          try {
              setResponseHeader(response, fileName);
              try (ServletOutputStream out = response.getOutputStream();
                   ExcelWriter writer = EasyExcel.write(out).build()) {
    
                  int sheetNo = 0;
                  for (Map.Entry<String, SheetData<?>> entry : sheets.entrySet()) {
                      String sheetName = entry.getKey();
                      SheetData<?> sheetData = entry.getValue();
    
                      WriteSheet writeSheet = EasyExcel.writerSheet(sheetNo, sheetName)
                              .head(sheetData.getClazz())
                              .build();
    
                      writer.write(sheetData.getData() == null ? new ArrayList<>() : sheetData.getData(), writeSheet);
                      sheetNo++;
                  }
              }
          } catch (Exception e) {
              throw new RuntimeException("Excel 多 Sheet 导出失败:" + e.getMessage(), e);
          }
      }
    
      // 设置响应头
      private static void setResponseHeader(HttpServletResponse response, String fileName) throws Exception {
          response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
          response.setCharacterEncoding("utf-8");
          String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
          response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
      }
    
      // 多 Sheet 封装类
      public static class SheetData<T> {
          private Class<T> clazz;
          private List<T> data;
    
          public SheetData(Class<T> clazz, List<T> data) {
              this.clazz = clazz;
              this.data = data;
          }
    
          public Class<T> getClazz() { return clazz; }
          public List<T> getData() { return data; }
      }

    }

3. 控制器使用示例(我只是为了方便代码量少直接写到contact层了)

✅ 优点:

  1. 代码简洁:控制器只负责数据处理,不关心 Excel 流操作。

  2. 复用性高:任何 VO/DTO 都可以直接导出。

  3. 支持多 Sheet :将来需要在同一个 Excel 文件中导出多张表时,只需调用 exportMultiSheet 即可。

4. 总结

通过 ExcelExportUtil 工具类,我们可以:

  • 轻松实现单个 Sheet 导出。

  • 支持多 Sheet 导出,实现复杂报表的汇总。

  • 封装响应头和流操作,减少重复代码,提高可维护性。

💡 Tip:如果将来需要"每个表单生成独立 Excel",只需多次调用 export 方法即可。

相关推荐
hPw0eKIqD18 小时前
使用二次封装的Excel COM 组件操作Excel\WPS ET中的区域、行和列
excel·wps
冰心孤城1 天前
Excel: xls与xlsx格式转换排坑指南
java·前端·excel
金豆呀1 天前
WPS批量提取Word文档内容生成固定格式Excel表格
word·excel·wps
Access开发易登软件1 天前
Access 怎么做前后端分离?用 Web API 读写 SQL Server
前端·数据库·人工智能·microsoft·excel·access
红莲凪是2 天前
使用二次封装的Excel COM 组件操作Excel\WPS ET IExcelRange 高级应用
python·excel·wps
用户298698530142 天前
如何使用免费工具在线将 Excel 转换为 XML 格式
人工智能·后端·excel
开开心心就好2 天前
内存清理工具定时自动清理开机自启动
java·开发语言·elasticsearch·ocr·excel·音视频·big data
开开心心就好2 天前
电脑内存优化工具一键释放内存超简单
java·开发语言·macos·arcgis·ocr·excel·音视频
随手工具-Excel, pdf, SQL2 天前
没有 SSMS 导入向导?Excel/CSV 一键生成 SQL Server INSERT 脚本
excel·sql server·在线工具·insert·测试数据·ssms·t-sql
SunnyDays10113 天前
Python 将 Excel(XLS/XLSX)转换为 JSON:导出工作簿、工作表、单元格区域与自定义 JSON 结构
python·json·excel·excel 转 json·导出 excel 到 json·xlsx 转 json·xls 转 json