EasyExcel横向扩展动态表头导出

本文介绍了一种基于Excel的计划运算结果导出方法,包括动态表头生成、表格数据匹配等核心步骤。通过使用EasyExcel等工具实现了车间、生产线等信息的导出,并确保了数据的准确性和完整性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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方法是一个排序方法

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值