easyexcel 版本:3.0.5
自定义单元格合并WriterHandler
import com.alibaba.excel.metadata.Head;import com.alibaba.excel.write.handler.CellWriteHandler;import com.alibaba.excel.write.merge.AbstractMergeStrategy;import org.apache.commons.collections4.CollectionUtils;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.CellType;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.util.CellRangeAddress;import java.util.HashSet;import java.util.List;import java.util.Objects;import java.util.Set;/*** @author mori* @date 2022/3/9*/public class CellMergeWriterHandler {public static CellWriteHandler getCellMergeWriterHandler(CellMergeEnum cellMergeEnum) {if (CellMergeEnum.ROW.equals(cellMergeEnum)) {return new RowMergeWriterHandler();}if (CellMergeEnum.COLUMN.equals(cellMergeEnum)) {return new ColumnMergeWriterHandler();}return null;}public static CellWriteHandler getRowMergeWriterHandler(List<Integer> rows) {return getCellWriteHandler(CellMergeEnum.ROW, rows);}public static CellWriteHandler getColumnMergeWriterHandler(List<Integer> cols) {return getCellWriteHandler(CellMergeEnum.COLUMN, cols);}public static CellWriteHandler getCellWriteHandler(CellMergeEnum cellMergeEnum, List<Integer> columnsOrRows) {if (CellMergeEnum.ROW.equals(cellMergeEnum)) {return new RowMergeWriterHandler(new HashSet<>(columnsOrRows));}if (CellMergeEnum.COLUMN.equals(cellMergeEnum)) {return new ColumnMergeWriterHandler(new HashSet<>(columnsOrRows));}return null;}public static class ColumnMergeWriterHandler extends AbstractMergeStrategy {private Set<Integer> mergeCols;public ColumnMergeWriterHandler() {}public ColumnMergeWriterHandler(Set<Integer> mergeCols) {this.mergeCols = mergeCols;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {if (CollectionUtils.isNotEmpty(this.mergeCols) && !this.mergeCols.contains(cell.getColumnIndex())) {return;}mergeCell(cell.getSheet(), cell, CellMergeEnum.COLUMN);}}public static class RowMergeWriterHandler extends AbstractMergeStrategy {private Set<Integer> mergeCols;public RowMergeWriterHandler() {}public RowMergeWriterHandler(Set<Integer> mergeCols) {this.mergeCols = mergeCols;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {if (CollectionUtils.isNotEmpty(mergeCols) && !mergeCols.contains(cell.getColumnIndex())) {return;}mergeCell(cell.getSheet(), cell, CellMergeEnum.ROW);}}private static void mergeCell(Sheet sheet, Cell cell, CellMergeEnum cellMergeEnum) {if (Objects.isNull(cell)) {return;}int rowIndex = cell.getRowIndex(), colIndex = cell.getColumnIndex();Row preRow = null;Cell preCell = null;if (CellMergeEnum.ROW.equals(cellMergeEnum)) {if (rowIndex == 0) {return;}preRow = sheet.getRow(rowIndex - 1);if (Objects.isNull(preRow)) {return;}preCell = preRow.getCell(colIndex);}if (CellMergeEnum.COLUMN.equals(cellMergeEnum)) {if (colIndex == 0) {return;}preRow = cell.getRow();preCell = preRow.getCell(colIndex - 1);}if (Objects.isNull(preCell)) {return;}Object preCellValue = getCellValue(preCell), curCellValue = getCellValue(cell);if (Objects.isNull(preCellValue) || Objects.isNull(curCellValue) || !preCellValue.equals(curCellValue)) {return;}merge(sheet, preCell, cell);}private static void merge(Sheet sheet, Cell preCell, Cell curCell) {List<CellRangeAddress> list = sheet.getMergedRegions();if (CollectionUtils.isEmpty(list)) {sheet.addMergedRegionUnsafe(new CellRangeAddress(preCell.getRowIndex(), curCell.getRowIndex(), preCell.getColumnIndex(), curCell.getColumnIndex()));return;}for (int i = 0; i < list.size(); i++) {CellRangeAddress cellRangeAddress = list.get(i);if (cellRangeAddress.containsRow(preCell.getRowIndex()) && cellRangeAddress.containsColumn(preCell.getColumnIndex())) {int firstRowIndex = cellRangeAddress.getFirstRow(), firstColIndex = cellRangeAddress.getFirstColumn();sheet.removeMergedRegion(i);sheet.addMergedRegionUnsafe(new CellRangeAddress(firstRowIndex, curCell.getRowIndex(), firstColIndex, curCell.getColumnIndex()));return;}}sheet.addMergedRegionUnsafe(new CellRangeAddress(preCell.getRowIndex(), curCell.getRowIndex(), preCell.getColumnIndex(), curCell.getColumnIndex()));}protected static Object getCellValue(Cell cell) {if (Objects.isNull(cell)) {return null;}CellType cellTypeEnum = cell.getCellType();switch (cellTypeEnum) {case STRING:return cell.getStringCellValue();case BOOLEAN:return cell.getBooleanCellValue();case NUMERIC:return cell.getNumericCellValue();default:return null;}}public enum CellMergeEnum {/*** row*/ROW,/*** column*/COLUMN;}}
测试代码:
@Testpublic void testTemplate() {String templateFileName = "./src/test/resources/test_simple_list.xlsx";String fileName = "./reports/listFill" + System.currentTimeMillis() + ".xlsx";ByteArrayOutputStream out = new ByteArrayOutputStream();ExcelWriter excelWriter = EasyExcel.write(out).withTemplate(templateFileName).registerWriteHandler(CellMergeWriterHandler.getRowMergeWriterHandler(Arrays.asList(0, 1))).autoCloseStream(Boolean.FALSE).build();WriteSheet writeSheet = EasyExcel.writerSheet(0).build();// 直接写入数据FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();excelWriter.fill(dataMap(), fillConfig, writeSheet);excelWriter.finish();File file = new File(fileName);try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {fileOutputStream.write(out.toByteArray());fileOutputStream.flush();} catch (Exception e) {e.printStackTrace();}}private List<Map<String, Object>> dataMap() {List<Map<String, Object>> list = ListUtils.newArrayList();for (int i = 0; i < 5; i++) {Map<String, Object> object = new HashMap<>();list.add(object);if (i % 3 == 0) {object.put("name", "张三3");object.put("number", null);} else {object.put("number", 5.2);object.put("name", "张三");}}return list;}
模板:
运行效果:
A列和B列相同数值行合并。
