4 百万数据报表导出

4.1 需求分析

使用Apache POI完成百万数据量的Excel报表导出

4.2 解决方案

4.2.1 思路分析

基于XSSFWork导出Excel报表,是通过将所有单元格对象保存到内存中,当所有的Excel单元格全部创建完成之后一次性写入到Excel并导出。当百万数据级别的Excel导出时,随着表格的不断创建,内存中对象越来越多,直至内存溢出。Apache Poi提供了SXSSFWork对象,专门用于处理大数据量Excel报表导出。

4.2.2 原理分析

在实例化SXSSFWork这个对象时,可以指定在内存中所产生的POI导出相关对象的数量(默认100),一旦内存中的对象的个数达到这个指定值时,就将内存中的这些对象的内容写入到磁盘中(XML的文件格式),就可以将这些对象从内存中销毁,以后只要达到这个值,就会以类似的处理方式处理,直至Excel导出完成。

4.3 代码实现

在原有代码的基础上替换之前的XSSFWorkbook,使用SXSSFWorkbook完成创建过程即可

//1.构造数据
List<EmployeeReportResult> list =
userCompanyPersonalService.findByReport(companyId,month+"%");
//2.创建工作簿
SXSSFWorkbook workbook = new SXSSFWorkbook();
//3.构造sheet
String[] titles = {"编号", "姓名", "手机","最高学历", "国家地区", "护照号", "籍贯",
"生日", "属相","入职时间","离职类型","离职原因","离职时间"};
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(0);
AtomicInteger headersAi = new AtomicInteger();
for (String title : titles) {
Cell cell = row.createCell(headersAi.getAndIncrement());
cell.setCellValue(title);
}
AtomicInteger datasAi = new AtomicInteger(1);
Cell cell = null;
for(int i=0;i<10000;i++) {
for (EmployeeReportResult report : list) {
Row dataRow = sheet.createRow(datasAi.getAndIncrement());
//编号
cell = dataRow.createCell(0);
cell.setCellValue(report.getUserId());
//姓名
cell = dataRow.createCell(1);
cell.setCellValue(report.getUsername());
//手机
cell = dataRow.createCell(2);
cell.setCellValue(report.getMobile());
//最高学历
cell = dataRow.createCell(3);
cell.setCellValue(report.getTheHighestDegreeOfEducation());
//国家地区
cell = dataRow.createCell(4);
cell.setCellValue(report.getNationalArea());
//护照号
cell = dataRow.createCell(5);
cell.setCellValue(report.getPassportNo());
//籍贯
cell = dataRow.createCell(6);
cell.setCellValue(report.getNativePlace());
//生日
cell = dataRow.createCell(7);
cell.setCellValue(report.getBirthday());
//属相
cell = dataRow.createCell(8);
cell.setCellValue(report.getZodiac());
//入职时间
cell = dataRow.createCell(9);
cell.setCellValue(report.getTimeOfEntry());
//离职类型
cell = dataRow.createCell(10);
cell.setCellValue(report.getTypeOfTurnover());
//离职原因
cell = dataRow.createCell(11);
cell.setCellValue(report.getReasonsForLeaving());
//离职时间
cell = dataRow.createCell(12);
cell.setCellValue(report.getResignationTime());
}
}
String fileName = URLEncoder.encode(month+"人员信息.xlsx", "UTF-8");
response.setContentType("application/octet-stream");
response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1")));
response.setHeader("filename", fileName);
workbook.write(response.getOutputStream());

4.4 对比测试

(1)XSSFWorkbook生成百万数据报表

使用XSSFWorkbook生成Excel报表,时间较长,随着时间推移,内存占用原来越多,直至内存溢出

SaaS-百万数据报表导出_百万数据报表导出

(2)SXSSFWorkbook生成百万数据报表

使用SXSSFWorkbook生成Excel报表,内存占用比较平缓

SaaS-百万数据报表导出_taro_02