easyExcel导出百万级数据,亲测实用

pom.xml添加配置

  
        
            com.alibaba
            easyexcel
            3.0.5
        

controller层,带分页的

 /**
     * 导出
     * @param response
     * @param dto 测试
     */
    @PostMapping("/exportNew")   
    public void exportNew(HttpServletResponse response, @RequestBody DqtbsHiddenDangerQueryDto dto,Pageable pageable) throws IOException {
        Long startTime = System.currentTimeMillis();
        service.export_new(response,dto,pageable);
        Long endTime = System.currentTimeMillis();
        Long elapsedTime = (endTime - startTime) / 1000;
        System.out.println("耗时:" + elapsedTime + "s");
    }

service层实现:

  /**
     * 导出_分页优化
     * @param dto
     * @return
     */
    @Override
    public void export_new(HttpServletResponse response,DqtbsHiddenDangerQueryDto dto, Pageable pageable)  throws IOException{
        int per_sheet_row_count = 500000;//每一个Sheet存放数据
        int per_write_row_count = 10000; //每次分页写入的数据量
        OutputStream outputStream =null;
        try {
            //记录总数,--自己的业务逻辑数据总数
            Integer totalCount = mapper.exportCount(dto);
            //每一个Sheet存放数据
            Integer sheetDataRows = per_sheet_row_count < totalCount ? per_sheet_row_count:totalCount;
            //每次写入的数据量,每页查询的数据
            Integer writeDataRows = per_write_row_count;
            //计算需要的Sheet数量
            Integer sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);
            //计算一般情况下每一个Sheet需要写入的次数(一般情况不包含最后一个sheet,因为最后一个sheet不确定会写入多少条数据)
            Integer oneSheetWriteCount = sheetDataRows % writeDataRows == 0 ? (sheetDataRows / writeDataRows) : (sheetDataRows / writeDataRows + 1);
            //计算最后一个sheet需要写入的次数
            Integer lastCountAll = totalCount - (sheetNum-1)*sheetDataRows;
            Integer lastSheetWriteCount = lastCountAll % writeDataRows == 0 ? (lastCountAll / writeDataRows) : (lastCountAll / writeDataRows + 1);

            outputStream = response.getOutputStream();
            //必须放到循环外,否则会刷新流
            ExcelWriter excelWriter = EasyExcel.write(outputStream).build();

            //开始分批查询分次写入
            for (int i = 0; i < sheetNum; i++) {
                //创建Sheet
                WriteSheet sheet = new WriteSheet();
                sheet.setSheetName("测试Sheet1"+i);
                sheet.setSheetNo(i);

                //循环写入次数: j的自增条件是当不是最后一个Sheet的时候写入次数为正常的每个Sheet写入的次数,如果是最后一个就需要使用计算的次数lastSheetWriteCount
                for (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {
                    //分页查询一次20w
                    int  pageNum = j + 1 + oneSheetWriteCount * i;
                    PageHelper.startPage(pageNum,writeDataRows,getOrderBy(pageable.getSort())).setReasonable(true);
                    List list = mapper.exportByPage(dto); //自己的分页查询

                    //封装导出类,DemoNew中配置需要导出的字段
                    List voList = new ArrayList<>();
                    for (Demo emp : list) {
                        DemoNew empVo = new DemoNew();
                        BeanUtils.copyProperties(emp, empVo);
                        voList.add(empVo);
                    }
                    //写到多个sheet中
                    WriteSheet writeSheet = EasyExcel.writerSheet(i, "隐患综合查询信息" + (i + 1)).head(DqtbsHiddenDangerQueryNew.class)
                            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
                    //写数据
                    excelWriter.write(voList, writeSheet);
                }
            }
            // 下载EXCEL
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止浏览器端导出excel文件名中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("信息", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            excelWriter.finish();
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (BeansException e) {
            e.printStackTrace();
        }  finally {
            if (outputStream != null) {
                outputStream.close();
            }
        }

    }

实体类DemoNew

public class DemoNew
{
    private static final long serialVersionUID = 1L;

    @ExcelIgnore
    private String          orgId          ; //id
    @ExcelIgnore
    private String          id           ; //id

   @ExcelProperty(value = "时间")
    private String          date           ; //时间
  

    @ColumnWidth(20)
   @ExcelProperty(value = "单位")
    private String          orgname                  ; //单位
}

@ExcelIgnore   忽略不用导出

@ExcelProperty(value = "单位")      导出字段名设置

前端调用:

 //导出
  exportExcel(values) {
    let this_ = this
    this_.spinningExport = true
    this.$api.export(BASE_URL + 'exportNew', values, `数据查询_${moment(new Date()).format('YYYY-MM-DD')}.xlsx`, {
      success() {
        this_.spinningExport = false
      },
      fail() {
        this_.spinningExport = false
      }
    })
  }
 

你可能感兴趣的:(SpringBoot,java)