1.导出需求
预生成的导出表头:车间、车间编码、生产线和生产线编码为固定表头,根据需要导出的时间范围动态生成表头xxxx年x月x日,每一个动态表头下面都有四个固定表头:订单号、物料号、交货数量和完工数量。 ·
2.Service层方法
HttpServletResponse response = SpringContextUtils.getResponse();
//合并前四列
int[] mergeColumeIndex = {0, 1, 2, 3};
// 从第一列开始合并
int mergeRowIndex = 0;
List<ApsPlanWorkItemResponse> data = this.result(request);
WinAssertUtil.isFalse(CollectionUtil.isEmpty(data), WinPlusApsErrorEnum.APS_VARIABLE_ERROR, "没有符合条件的数据");
try {
ExcelExportUtils.setResponse(response, "计划运算结果导出");
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream()).head(headList(data)).sheet("计划运算结果导出")
.registerWriteHandler(new AdaptiveColumnWidthStrategy())
.registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumeIndex))
.doWrite(dataList(data));
} catch (Exception e) {
// 重置response
ExcelExportUtils.responseReset(response, e);
}
3.动态表头生成
先生成前四列的固定表头,然后将符合导出条件的数据转换成map,保证每一天只有一条数据,用于判断需要横向扩展几个时间表头。
/**
* 表头处理
*
* @param responseList 计划结果数据
* @return 表头集合
*/
private List<List<String>> headList(List<ApsPlanWorkItemResponse> responseList) {
//初始化返回集合
List<List<String>> list = new ArrayList<>();
//生成前四列固定表头
List<String> head0 = new ArrayList<>();
head0.add("车间");
head0.add("车间");
list.add(head0);
List<String> head1 = new ArrayList<>();
head1.add("车间编码");
head1.add("车间编码");
list.add(head1);
List<String> head2 = new ArrayList<>();
head2.add("生产线");
head2.add("生产线");
list.add(head2);
List<String> head3 = new ArrayList<>();
head3.add("生产线编码");
head3.add("生产线编码");
list.add(head3);
//根据开始时间降序排序
responseList.sort(Comparator.comparing(ApsPlanWorkItemResponse::getStartTime));
//初始化时间Map
TreeMap<Long, Date> timeMap = new TreeMap<>();
responseList.forEach(item -> {
long startTime = ApsDateUtils.beginOfDay(item.getStartTime()).getTime() / 1000;
if (!timeMap.containsKey(startTime)) {
timeMap.put(startTime, item.getStartTime());
}
});
//生成需要横向扩展的表头
for (Map.Entry<Long, Date> entry : timeMap.entrySet()) {
String time = ApsDateUtils.year(entry.getValue()) + "年" + (ApsDateUtils.month(entry.getValue()) + 1) + "月"
+ ApsDateUtils
.dayOfMonth(entry.getValue()) + "日";
List<String> head4 = new ArrayList<>();
head4.add(time);
head4.add("订单号");
list.add(head4);
List<String> head5 = new ArrayList<>();
head5.add(time);
head5.add("物料号");
list.add(head5);
List<String> head6 = new ArrayList<>();
head6.add(time);
head6.add("计划数量");
list.add(head6);
List<String> head7 = new ArrayList<>();
head7.add(time);
head7.add("交货数量");
list.add(head7);
}
return list;
}
4.表格数据匹配
方法中timeMap的value主要用来查看treeMap的key顺序是否是升序
/**
* 表格数据处理
*
* @param responseList 计划结果数据
* @return 表格数据集合
*/
private List<List<String>> dataList(List<ApsPlanWorkItemResponse> responseList) {
//初始化返回集合
List<List<String>> list = new ArrayList<>();
//根据时间升序排序
responseList.sort(Comparator.comparing(ApsPlanWorkItemResponse::getStartTime));
//根据时间组装map
TreeMap<Long, Integer> timeMap = new TreeMap<>();
int i = 0;
for (ApsPlanWorkItemResponse response : responseList) {
long startTime = ApsDateUtils.beginOfDay(response.getStartTime()).getTime() / 1000;
if (timeMap.containsKey(startTime)) {
continue;
}
timeMap.put(startTime, i);
i++;
}
//根据车间+资源+订单分组
Map<String, List<ApsPlanWorkItemResponse>> map = responseList.stream().collect(Collectors.groupingBy(a ->
a.getWorkshopCode() + ApsStringPoolConstant.DASH + a.getResCode() + ApsStringPoolConstant.DASH + a
.getPlanOrderCode()
));
for (Map.Entry<String, List<ApsPlanWorkItemResponse>> entry : map.entrySet()) {
List<String> data = new ArrayList<>();
data.add(entry.getValue().get(0).getWorkshopName());
data.add(entry.getValue().get(0).getWorkshopCode());
data.add(entry.getValue().get(0).getResName());
data.add(entry.getValue().get(0).getResCode());
//根据时间生成Map
Map<Long, ApsPlanWorkItemResponse> responseMap = entry.getValue().stream()
.collect(Collectors.toMap(e -> ApsDateUtils.beginOfDay(e.getStartTime()).getTime() / 1000, a -> a));
for (Map.Entry<Long, Integer> timeEntry : timeMap.entrySet()) {
//判断该时间节点下是否有数据
if (responseMap.containsKey(timeEntry.getKey())) {
ApsPlanWorkItemResponse response = responseMap.get(timeEntry.getKey());
data.add(response.getPlanOrderCode());
data.add(response.getSkuCode());
data.add(String.valueOf(response.getPlanQty().intValue()));
data.add(response.getCompleteQty().toString());
} else {
data.add("-");
data.add("-");
data.add("0");
data.add("0");
}
}
list.add(data);
}
return dataSort(list);
}
最后返回的dataSort方法是一个排序方法