20240805每日后端----------百万级Excel导出工具类,支持使用字典工具类翻译

public class EasyExcelUtil<T,P> {
  private static final Logger log = LoggerFactory.getLogger(EasyExcelUtil.class);
  public Class<T> clazz;

  public Class<P> paramsClazz;

  public EasyExcelUtil(Class<T> clazz, Class<P> paramsClazz) {
        this.clazz = clazz;
        this.paramsClazz = paramsClazz;
  }


  //导出大数据量(百万级)逻辑代码
  public void exportData(HttpServletResponse response, Integer totalCount, String fileName, SelectMethod<P> selectMethod,P params) {
    {
      OutputStream outputStream = null;
      try {
        long startTime = System.currentTimeMillis();
        outputStream = response.getOutputStream();
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        //设置头居中
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        //设置内容
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //设置 水平居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        //内容策略
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        ExcelWriter writer = EasyExcelFactory.write(outputStream, clazz)
                .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
                .registerWriteHandler(new CustomSheetWriteHandler())
                .registerWriteHandler(horizontalCellStyleStrategy) // 注册自定义策略
                .registerWriteHandler(new ExcelWidthStyleStrategyHandler()) // 自适应宽度
                .build();
        //每一个Sheet存放100w条数据
        int sheetDataRows = 1000000;
        //数据量大于10万,每次写入的数据量20w,否则每次写入的数据量5w
        int writeDataRows = totalCount > 100000 ? 200000 : 50000;

        //计算需要的Sheet数量
        int sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);
        //计算一般情况下每一个Sheet需要写入的次数(一般情况不包含最后一个sheet,因为最后一个sheet不确定会写入多少条数据)
        int oneSheetWriteCount = sheetDataRows / writeDataRows;
        //计算最后一个sheet需要写入的次数
        int lastSheetWriteCount = totalCount % sheetDataRows == 0 ? oneSheetWriteCount : (totalCount % sheetDataRows % writeDataRows == 0 ? (totalCount % sheetDataRows / writeDataRows) : (totalCount % sheetDataRows / writeDataRows + 1));

        //开始分批查询分次写入
        //注意这次的循环就需要进行嵌套循环了,外层循环是Sheet数目,内层循环是写入次数
        for (int i = 0; i < sheetNum; i++) {
          //创建Sheet
          WriteSheet writeSheet = EasyExcelFactory.writerSheet(sheetNum-1, "第" + (sheetNum)+"页")
                  .head(clazz)
                  .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                  .build();
          //循环写入次数: j的自增条件是当不是最后一个Sheet的时候写入次数为正常的每个Sheet写入的次数,如果是最后一个就需要使用计算的次数lastSheetWriteCount
          for (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {
            //分页查询
            PageMethod.startPage(j + 1 + oneSheetWriteCount * i, writeDataRows);
            Object result = selectMethod.list(params);
            writer.write((Collection<?>) result, writeSheet);
          }
        }
        response.reset();
        // 下载EXCEL
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        response.setContentType("application/octet-stream; charset=UTF-8");
        writer.finish();
        outputStream.flush();
        //导出时间结束
        long endTime = System.currentTimeMillis();
        log.info("导出所用时间:" + (endTime - startTime) / 1000 + "秒");
      } catch (IOException e) {
        log.error("导出Excel异常{}", e.getMessage());
        throw new CustomException("导出Excel失败,请联系网站管理员!");
      } finally {
        if (outputStream != null) {
          try {
            outputStream.close();
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值