EasyExcel如何实现单元格合并
本文主要讲解关于EasyExcel如何实现单元格合并相关内容,让我们来一起学习下吧!
作为一名光荣的crud(搬砖)工程师,导出Excel可是必备的技能树(❛‿˂̵✧),使用原生的poi导出代码既复杂又容易出bug,日常工作中更多的时使用阿里开源的EasyExcel;文档中有关合并单元格的例子不太满足日常工作的需要,本篇文章自定义了一个合并的策略,实现行内容相同的合并。
合并策略
/** * 行内容相同合并策略 */ public static class RowContentSameMergeStrategy implements RowWriteHandler { /** * 数据量,即导出数据的行数,不包含表头 */ private final int dataSize; /** * 表头数量,即导出列的数量 */ private final int headSize; /** * 数据的开始行 */ private Integer startRow; /** * 合并的高度 */ private int[][] mergeHeight; public RowContentSameMergeStrategy(int dataSize, int headSize) { this.dataSize = dataSize - 1; this.headSize = headSize; } @Override public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) { if (isHead) { return; } // 定义数据的开始行 if (startRow == null) { startRow = row.getRowNum(); } // 没到最后一行,直接返回 if (relativeRowIndex != dataSize) { return; } // 定义数据的结束行 int endRow = row.getRowNum(); // 定义二维数组记录合并的高度 mergeHeight = new int[endRow + 1][headSize + 1]; // 全部sheet已经加载完毕 // 需要进行单元格的合并 // 这里处理的是行合并,不处理列合并 // 读取每列 for (int cellIndex = 0; cellIndex < headSize; cellIndex++) { // startRowPoint=开始行指针 endRowPoint=结束行指针 preCellIndex=前一列单元格 int startRowPoint = startRow, endRowPoint = startRow, preCellIndex = cellIndex - 1; // startRowCell=开始行当前单元格的内容 String startRowCell = null; for (; endRowPoint <= endRow; endRowPoint++) { if (startRowPoint == endRowPoint) { startRowCell = writeSheetHolder.getSheet().getRow(startRowPoint).getCell(cellIndex).getStringCellValue(); continue; } if (preCellIndex >= 0 ) { // 前一个格子的高度 int preHeight = mergeHeight[startRowPoint][preCellIndex]; // 若当前格子合并的高度已经超过了前一列,直接进行重置处理 if (endRowPoint - startRowPoint + 1 > preHeight) { // 需要进行合并 if (startRowPoint != endRowPoint - 1) { merge(writeSheetHolder, startRowPoint, endRowPoint - 1, cellIndex); } // 重置两个指针,由于endPoint会固定往后走一位,所以将start调整到当前位置 startRowPoint = endRowPoint; endRowPoint = endRowPoint - 1; continue; } } // 计算当前行数据是否相同 String endCell = writeSheetHolder.getSheet().getRow(endRowPoint).getCell(cellIndex).getStringCellValue(); // 最后一行的特殊处理 // 如果相同直接合并单元格 if (endRowPoint == endRow && StringUtils.equals(startRowCell, endCell)) { merge(writeSheetHolder, startRowPoint, endRowPoint, cellIndex); continue; } // 不相同 -> 需要进行单元格的合并 if (!StringUtils.equals(startRowCell, endCell)) { // 需要进行合并 if (startRowPoint != endRowPoint - 1) { merge(writeSheetHolder, startRowPoint, endRowPoint - 1, cellIndex); } // 重置两个指针,由于endPoint会固定往后走一位,所以将start调整到当前位置 startRowPoint = endRowPoint; endRowPoint = endRowPoint - 1; } // 相同 -> 继续读取下一行 } } } private void merge(WriteSheetHolder writeSheetHolder, int startRowPoint, int endRowPoint, int cellIndex) { // 计算高度 int height = endRowPoint - startRowPoint + 1; CellRangeAddress cellRangeAddress = new CellRangeAddress( startRowPoint, endRowPoint, cellIndex, cellIndex ); // 维护高度 for (int i = startRowPoint; i <= endRowPoint; i++) { mergeHeight[i][cellIndex] = height; } writeSheetHolder.getSheet().addMergedRegionUnsafe(cellRangeAddress); } }
策略使用
public static void main(String[] args) { List<DemoData> list = new ArrayList<>(); list.add(new DemoData("us", "x", "y1", "z1")); list.add(new DemoData("us", "x", "y1", "z2")); list.add(new DemoData("us", "x", "y1", "z3")); list.add(new DemoData("jp", "x", "y2", "z1")); list.add(new DemoData("jp", "x", "y2", "z2")); list.add(new DemoData("jp", "x", "y2", "z3")); String fileName = "mergeWrite" + System.currentTimeMillis() + ".xlsx"; // 自定义合并单元格策略 // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class) .registerWriteHandler(new RowContentSameMergeStrategy(list.size(), 4)) .sheet("模板") .doWrite(list); }
以上就是关于EasyExcel如何实现单元格合并相关的全部内容,希望对你有帮助。欢迎持续关注潘子夜个人博客(www.frpkj.com),学习愉快哦!