EasyExcel合并单元格(同列相同数据合并)

在这里插入图片描述

合并后效果如下:
在这里插入图片描述
合并策略代码:

public class CustomMergeStrategy extends AbstractMergeStrategy {

	/**
	 * 分组,每几行合并一次
	 */
	private List<List<Integer>> mergeColDataGroupCountList;

	/**
	 * 目标合并列index
	 */
	private List<Integer> targetColumnIndex;
	/**
	 * 	需要开始合并单元格的首行index
 	 */
	private Integer rowIndex;

	/**
	 * 	mergeColDataList为待合并目标列的值
 	 */
	public CustomMergeStrategy(List<List<String>> mergeColDataList, List<Integer> targetColumnIndex) {
		this.mergeColDataGroupCountList = getGroupCountList(mergeColDataList);
		this.targetColumnIndex = targetColumnIndex;
	}


	@Override
	protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {

		if (null == rowIndex) {
			rowIndex = cell.getRowIndex();
		}
		// 仅从首行以及目标列的单元格开始合并,忽略其他
		if (cell.getRowIndex() == rowIndex && targetColumnIndex.contains(cell.getColumnIndex())) {
			//找到对应的需要合并的列
			AtomicInteger i = new AtomicInteger(0);
			Optional<Integer> first = targetColumnIndex.stream().filter(col -> {
				i.getAndIncrement();
				return col == cell.getColumnIndex();
			}).findFirst();
			mergeGroupColumn(sheet, first.get());
		}
	}

	private void mergeGroupColumn(Sheet sheet, Integer index) {
		int rowCount = rowIndex;
		for (Integer count : mergeColDataGroupCountList.get(index)) {
			if (count == 1) {
				rowCount += count;
				continue;
			}
			// 合并单元格
			CellRangeAddress cellRangeAddress = new CellRangeAddress(rowCount, rowCount + count - 1,
					targetColumnIndex.get(index), targetColumnIndex.get(index));
			sheet.addMergedRegionUnsafe(cellRangeAddress);
			rowCount += count;
		}
	}

	/**
	 * 	该方法将目标列根据值是否相同连续可合并,存储可合并的行数
 	 */
	private List<List<Integer>> getGroupCountList(List<List<String>> exportDataList) {
		if (CollUtil.isEmpty(exportDataList)) {
			return new ArrayList<>();
		}
		List<List<Integer>> groupCountListList = new ArrayList<>();
		exportDataList.forEach(dataList->{
			List<Integer> groupCountList = new ArrayList<>();
			int count = 1;
			for (int i = 1; i < dataList.size(); i++) {
				if (dataList.get(i).equals(dataList.get(i - 1))) {
					count++;
				} else {
					groupCountList.add(count);
					count = 1;
				}
			}
			// 处理完最后一条后
			groupCountList.add(count);
			groupCountListList.add(groupCountList);
		});
		return groupCountListList;
	}
}

使用:
step1:mergeColDataList——将准备插入Excel的数据中的“序号(num)”和“运营公司(operateDeptName)”两个字段收集起来,放到二维List中。
step2:mergeColIndexList——构造要合并的列index集合。

//序号列和运营公司列需要合并单元格
		List<List<String>> mergeColDataList = Stream.of(data.stream().map(BridgeTypeLengthExcel::getNum).collect(Collectors.toList()),
				data.stream().map(BridgeTypeLengthExcel::getOperateDeptName).collect(Collectors.toList())).collect(Collectors.toList());
		//第一列(index=0)和第二列(index=1)
		List<Integer> mergeColIndexList = Stream.of(0, 1).collect(Collectors.toList());
		//内部finish的时候会自动关闭流
		EasyExcel.write(response.getOutputStream(), BridgeTypeLengthExcel.class)
				.registerWriteHandler(
						new CustomMergeStrategy(
								mergeColDataList, mergeColIndexList
						)
				)
				.sheet("统计")
				.doWrite(data);

主体代码来自网络,按自己业务修改,支持多列相同数据合并。

  • 7
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
使用 easyexcel 进行相同数据合并单元格的步骤如下: 1. 定义一个集合来存储相同数据的行下标。 2. 遍历表格的每一行,将相同数据的行下标存入集合中。 3. 定义一个 Map<Integer, List<Integer>>,其中 key 表示相同数据在哪一,value 表示相同数据的行下标集合。 4. 遍历集合,将相同数据的行下标根据其在哪一进行分类。 5. 遍历 Map,对于每一个 key,获取 value 并将其转化为数组。 6. 使用 easyexcel 提供的 `SheetUtil.merge()` 方法进行相同数据合并单元格,该方法需要传入起始行、结束行、起始、结束。 7. 将合并后的表格输出到文件或者输出流中。 下面是具体的代码实现: ```java ExcelReader reader = EasyExcel.read(fileName).build(); List<List<Object>> rows = reader.read(0); List<Integer> sameDataRows = new ArrayList<>(); Map<Integer, List<Integer>> sameDataMap = new HashMap<>(); // 遍历表格的每一行 for (int i = 0; i < rows.size(); i++) { List<Object> row = rows.get(i); Object data = row.get(columnIndex); // 判断当前行是否与上一行的数据相同 if (i > 0 && Objects.equals(data, rows.get(i-1).get(columnIndex))) { sameDataRows.add(i); } else { if (!sameDataRows.isEmpty()) { // 将相同数据的行下标根据其在哪一进行分类 int colIndex = sameDataRows.get(0); sameDataMap.computeIfAbsent(colIndex, k -> new ArrayList<>()).addAll(sameDataRows); sameDataRows.clear(); } sameDataRows.add(i); } } if (!sameDataRows.isEmpty()) { int colIndex = sameDataRows.get(0); sameDataMap.computeIfAbsent(colIndex, k -> new ArrayList<>()).addAll(sameDataRows); } // 对于每一个 key,获取 value 并将其转化为数组,然后进行单元格合并 Sheet sheet = new Sheet(1, 0); for (Map.Entry<Integer, List<Integer>> entry : sameDataMap.entrySet()) { Integer colIndex = entry.getKey(); List<Integer> rowIndices = entry.getValue(); Integer[] rowIndexArray = rowIndices.toArray(new Integer[0]); SheetUtil.merge(sheet, rowIndexArray[0], rowIndexArray[rowIndexArray.length-1], colIndex, colIndex); } ExcelWriter writer = EasyExcel.write(out).build(); writer.write(rows, sheet); writer.finish(); ``` 其中,`fileName` 表示需要读取的 Excel 文件名,`columnIndex` 表示需要进行合并索引,`out` 表示输出流,可以是文件输出流或者网络输出流等。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值