合并单元格多层数据导出
思维脑图
代码实现
/**
* 导出所有信息
*
* @param request 请求体
*/
@Override
public void getWilliamExportList(WilliamReqVo request, HttpServletResponse response) throws Exception {
List<SysDictData> dataByType = dictDataService.getDictDataByType("status");
Map<String, String> calendarStatus = dataByType.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
List<WilliamAllExportVo> list = baseMapper.getWilliamExportData(request);
if (CollectionUtils.isNotEmpty(list)) {
list.forEach(s -> s.setStatus(calendarStatus.get(s.getStatus())));
}
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("某某表" + DateUtil.format(new Date(), SysConstants.DATE_FORMAT), "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
ExcelWriterBuilder writerBuilder = EasyExcel.write(response.getOutputStream(), WilliamAllExportVo.class);
//合并策略
addMergeStrategy(list, writerBuilder);
writerBuilder.sheet("信息表").doWrite(list);
}
/**
* 合并策略
*
* @param list 数据集
* @param writerBuilder excel写对象
*/
private static void addMergeStrategy(List<WilliamAllExportVo> list, ExcelWriterBuilder writerBuilder) {
// 第一级,选定键值进行分层准备
Map<String, List<WilliamAllExportVo>> collect = list.stream().collect(Collectors.groupingBy(s -> s.getProjectSn() + s.getMonth()));
Map<String, List<WilliamAllExportVo>> collect2 = list.stream().collect(Collectors.groupingBy(s -> s.getProjectSn() + s.getMonth() + s.getTitle()));
//第一层合并单元格处理
for (int i = 1; i < list.size(); ) {
WilliamAllExportVo exportVo = list.get(i);
//计算集合长度,确定有多少行
int size = collect.get(exportVo.getProjectSn() + exportVo.getMonth()).size();
//按照分层合并范围的属性,设置j的数值
for (int j = 0; j < 10; j++) {
OnceAbsoluteMergeStrategy strategy = new OnceAbsoluteMergeStrategy(i, i + size - 1, j, j);
writerBuilder.registerWriteHandler(strategy);
}
i = i + size;
}
//第二层合并单元格处理,
for (int i = 1; i < list.size(); ) {
WilliamAllExportVo exportVo = list.get(i);
int size = collect2.get(exportVo.getProjectSn() + exportVo.getMonth() + exportVo.getTitle()).size();
for (int j = 10; j < 14; j++) {
OnceAbsoluteMergeStrategy strategy = new OnceAbsoluteMergeStrategy(i, i + size - 1, j, j);
writerBuilder.registerWriteHandler(strategy);
}
i = i + size;
}
}
逻辑分析
1. 数据准备与状态映射
首先,通过dictDataService.getDictDataByType(“status”)获取字典数据,这通常用于将数据库中的状态码(如数字或简短字符串)转换为更加友好的展示标签。之后,使用Java 8的Stream API将这些数据转换成一个Map,键为状态值,值为状态标签,便于后续替换列表中项目的状态字段。
List<SysDictData> dataByType = dictDataService.getDictDataByType("project_calendar_status");
Map<String, String> calendarStatus = dataByType.stream()
.collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
接着,调用baseMapper.getWilliamExportData(request)获取项目日历导出数据列表,然后遍历列表,使用前面构建的状态映射替换项目状态字段的代码值为描述文本。
2. 设置响应头及内容类型
让HTTP响应能够以Excel文件的形式下载。首先,设置了响应的内容类型为Excel的OpenXML格式,然后通过URLEncoder.encode方法对文件名进行编码,以防止中文乱码,并使用特定的Content-Disposition头部来指示浏览器以附件形式下载文件,并给出文件名。
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("某某表" + DateUtil.format(new Date(), SysConstants.DATE_FORMAT), "UTF-8")
.replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
3. 使用EasyExcel导出数据
EasyExcel是一个用于简化Excel操作的Java库,它允许开发者以更简洁的方式读写Excel文件。在这里,通过EasyExcel.write(response.getOutputStream(), WilliamAllExportVo.class)初始化一个Excel写入器,然后调用addMergeStrategy方法注册合并单元格的策略,最后在指定的工作表中写入数据。
4. 单元格合并策略
addMergeStrategy方法实现了Excel表格中单元格的合并策略。这里的逻辑是首先按照编号(projectSn)和月份(month)进行第一级分组,然后在同一组内再按照标题(title)进行第二级分组,分别对不同列范围内的连续行进行合并。
对于第一级分组(第1至第9列),合并所有属于同一项目、同一月份的行。
对于第二级分组(第10至第13列),在第一级的基础上,进一步根据标题合并。
使用了OnceAbsoluteMergeStrategy
类,该类为EasyExcel提供的单元格合并策略之一,参数分别为起始行号、结束行号、起始列号、结束列号,指定了合并的具体范围。
知识点总结
- 数据映射:利用Map和Stream API进行数据转换,提高代码的可读性和效率。
- HTTP响应处理:设置正确的响应头以实现文件下载,以及解决中文乱码问题。
- EasyExcel库:简化Excel文件的生成和读取过程,提升开发效率。
- 单元格合并:通过自定义策略实现Excel中数据的分组和单元格合并,提升报表的可读性。