一、需求来源:
最新需求需要将一组数据分多个sheet页导出,每个sheet数据为1000。然后查询了网上的一些文章,发现没有自己想要的,就只能自己去看easyPoi的api文档。最终找到了解决的方法
二、导出效果:
导出的数据如上图所示,每个sheet页有一千条数据
三、代码思路:
3.1:easypoi的api示例
/**
* 根据Map创建对应的Excel(一个excel 创建多个sheet)
*
* @param list 多个Map key title 对应表格Title key entity 对应表格对应实体 key data
* Collection 数据
* @return
*/
public static Workbook exportExcel(List<Map<String, Object>> list, ExcelType type) {
Workbook workbook = getWorkbook(type, 0);
for (Map<String, Object> map : list) {
ExcelExportService service = new ExcelExportService();
ExportParams params = (ExportParams) map.get("title");
params.setType(type);
service.createSheet(workbook,params,
(Class<?>) map.get("entity"), (Collection<?>) map.get("data"));
}
return workbook;
}
3.2:easypoi的api解析
如上图说是我们可以看到有三个参数
1. title:对应表格title
2. entity:对应表格对应实体
3. data:导出的数据
4. type:类型有两种 : HSSF 和 XSSF
对于type这个类型大概解释一下,详细需要去阅读相关文章
用JavaPOI导出Excel时,我们需要考虑到Excel版本及数据量的问题。针对不同的Excel版本,要采用不同的工具类,如果使用错了,会出现错误信息。JavaPOI导出Excel有三种形式,他们分别是1.HSSFWorkbook 2.XSSFWorkbook 3.SXSSFWorkbook。
HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls;
XSSFWorkbook:是操作Excel2007后的版本,扩展名是.xlsx;
第一种:HSSFWorkbook
poi导出excel最常用的方式;但是此种方式的局限就是导出的行数至多为65535行,超出65536条后系统就会报错。此方式因为行数不足七万行所以一般不会发生内存不足的情况(OOM)。
第二种:XSSFWorkbook
这种形式的出现是为了突破HSSFWorkbook的65535行局限。其对应的是excel2007(1048576行,16384列)扩展名为“.xlsx”,最多可以导出104万行,不过这样就伴随着一个问题---OOM内存溢出,原因是你所创建的book sheet row cell等此时是存在内存的并没有持久化。
四、代码示例:
1.首先将需要导出的字段加上@Excel注解
@Data
public class OrderExportVo {
@Excel(name = "店铺名")
private String shopName;
@Excel(name = "物流单号",width = 20)
@ApiModelProperty(value = "发货单号")
private String logisticsNo;
@Excel(name = "订单号",width = 20)
@ApiModelProperty(value = "订单号")
private String orderNum;
}
2.进行代码编写
CompletableFuture.runAsync(() -> {
//查询出所有的订单的数据
List<Order> orderList = orderService.getOrderList(user);
//将数据进行按照1000个拆分(拆分数据自己定义)
List<List<Order>> partition = Lists.partition(orderList, 1000);
// 多个sheet配置参数
List<Map<String, Object>> sheetsList = new ArrayList<>();
AtomicInteger atomicInteger = new AtomicInteger();
partition.forEach(exportList -> {
//将分割的数据赋值
List<OrderExportVo> orderExportVoList = new ArrayList<>();
for (Order order : exportList) {
OrderExportVo orderExportVo = new OrderExportVo();
BeanUtil.copyProperties(order,orderExportVo);
orderExportVoList.add(orderExportVo);
}
String sheetName = "sheet" + atomicInteger.addAndGet(1);
Map<String, Object> exportMap = Maps.newHashMap();
ExportParams exportParams = new ExportParams(null, sheetName, ExcelType.HSSF);
// 以下3个参数为API中写死的参数名 分别是sheet配置/导出类(注解定义)/数据集
exportMap.put("title", exportParams);
exportMap.put("entity", OrderExportVo.class);
exportMap.put("data", orderExportVoList);
// 加入多sheet配置列表
sheetsList.add(exportMap);
});
Workbook workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF);
String filePath = filePluginFactory.filePlugin().getFilePath(workbook);
System.out.println(filePath);
});
2.1:首先查询出自己需要的数据,然后通过工具类切割数组,分成1000个一组。
2.2:然后进行循环,将需要导出的数据进行赋值,然后将这个数据复制到对应的sheet中。
2.3:我这边采取的异步导出,最后获取到Workbook,然后上传到阿里云
四、待完善问题:
一次性查询数据量太大,所以后续需要优化成分批次查询,将每个批次查询的结果放入到对应的sheet里面;(TODO)