@GetMapping("/getZipAirSheetYearCustReportExportAll")
@ApiOperationSupport(order = 1)
public void getZipAirSheetYearCustReportExportAll(ZipAirSheetVO zipAirSheetVO, HttpServletResponse response) throws IOException {
try {
// 1. 获取数据
List<Map<String, Object>> zipAirSheetYearCustReport = zipAirSaleSheetService.getZipAirSheetYearCustReport(zipAirSheetVO);
// 确保列表不为空
if (zipAirSheetYearCustReport == null || zipAirSheetYearCustReport.isEmpty()) {
throw new RuntimeException("数据列表为空");
}
// 获取第一行数据
Map<String, Object> firstRow = zipAirSheetYearCustReport.get(0);
// 获取 allWeek 的 Object 值
Object allWeekValue = firstRow.get("allWeek");
// 检查空值
if (allWeekValue == null) {
throw new RuntimeException("allWeek 字段值为空");
}
// 检查类型是否为 List
if (!(allWeekValue instanceof List)) {
throw new ClassCastException("allWeek 字段不是 List 类型");
}
// 转换为原始 List
List<?> rawList = (List<?>) allWeekValue;
// 转换为特定泛型类型(例如 String)
List<String> allWeekList = new ArrayList<>();
for (Object item : rawList) {
if (item instanceof String) {
allWeekList.add((String) item);
} else {
// 处理类型不匹配的元素
LOGGER.warn("忽略非字符串元素: {}", item);
}
}
// 使用 allWeekList 进行后续操作
System.out.println("转换后的列表: " + allWeekList);
// 2. 定义动态表头映射(确保顺序使用 LinkedHashMap)
Map<String, String> headerMapping = new LinkedHashMap<>();
headerMapping.put("userName", "用户名称");
allWeekList.forEach(item -> {
headerMapping.put(item, item);
});
headerMapping.put("total", "合计");
// 3. 动态生成表头和数据(适配 EasyExcel)
List<List<String>> head = new ArrayList<>();
for (Map.Entry<String, String> entry : headerMapping.entrySet()) {
List<String> headColumn = new ArrayList<>();
headColumn.add(entry.getValue()); // 表头名称
head.add(headColumn);
}
// 执行转换
List<Map<String, Object>> transformedList = DataStructureConverter.convertDataStructure(zipAirSheetYearCustReport);
List<List<Object>> dataList = new ArrayList<>();
for (Map<String, Object> rowData : transformedList) {
List<Object> row = new ArrayList<>();
for (Map.Entry<String, String> entry : headerMapping.entrySet()) {
Object value = rowData.get(entry.getKey());
row.add(value != null ? value : ""); // 处理空值
}
dataList.add(row);
}
// 4. 设置响应头(文件名处理)
String unsafeFileName = "压缩空气自定义报表" + DateUtils.getCurrentDateStrByFormat(DateFormat.Y_M_D_HMS) + ".xlsx";
String safeFileName = unsafeFileName.replaceAll("[^a-zA-Z0-9.-]", "_");
String encodedFileName = URLEncoder.encode(safeFileName, StandardCharsets.UTF_8.toString());
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName + "; filename*=utf-8''" + encodedFileName);
// 2. 自定义列宽策略
AbstractColumnWidthStyleStrategy columnWidthStyleStrategy = new AbstractColumnWidthStyleStrategy() {
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
// 设置表头列宽
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 30 * 256); // 20个字符宽度
} else {
// 设置数据列宽
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 20 * 256); // 15个字符宽度
}
}
};
// 5. 使用 EasyExcel 直接写入 HTTP 响应流
EasyExcel.write(response.getOutputStream())
.head(head) // 动态表头
.registerWriteHandler(columnWidthStyleStrategy) // 设置表头样式
.sheet("压缩空气自定义报表") // Sheet 名称
.doWrite(dataList); // 动态数据
} catch (IOException e) {
LOGGER.error("导出数据异常", e);
throw new RuntimeException("导出文件失败", e);
} catch (Exception e) {
LOGGER.error("系统异常", e);
throw new RuntimeException(e);
}
}
DataStructureConverter 转换类(因为数据返回的是Map,然后转换成普通的类的返回格式,动态类)
package org.springblade.common.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class DataStructureConverter {
public static List<Map<String, Object>> convertDataStructure(List<Map<String, Object>> originalList) {
List<Map<String, Object>> transformedList = new ArrayList<>();
for (Map<String, Object> originalMap : originalList) {
// 创建新的 Map,使用 LinkedHashMap 保持字段顺序
Map<String, Object> newMap = new LinkedHashMap<>();
// 1. 复制原始 Map 中除了 "map" 的字段
for (Map.Entry<String, Object> entry : originalMap.entrySet()) {
String key = entry.getKey();
if (!"map".equals(key)) {
newMap.put(key, entry.getValue());
}
}
// 2. 提取并合并 "map" 中的键值对到新 Map
Object mapValue = originalMap.get("map");
if (mapValue instanceof Map) {
Map<?, ?> innerMap = (Map<?, ?>) mapValue;
for (Map.Entry<?, ?> innerEntry : innerMap.entrySet()) {
String innerKey = String.valueOf(innerEntry.getKey());
Object innerValue = innerEntry.getValue();
newMap.put(innerKey, innerValue);
}
} else {
// 可选:处理 "map" 字段不存在或类型错误的情况
// throw new RuntimeException("map 字段类型错误或不存在");
}
// 3. 将转换后的 Map 添加到结果列表
transformedList.add(newMap);
}
return transformedList;
}
}