引入pom.xml
java<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency>
java
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.HashMap;
import java.util.Map;
public class CustomMergeStrategy extends AbstractMergeStrategy {
private final int[] mergeColumns; // 需要合并的列索引
private final int startRow; // 开始合并的行号
private Map<Integer, MergeRange> lastValueMap = new HashMap<>();
public CustomMergeStrategy(int[] mergeColumns, int startRow) {
this.mergeColumns = mergeColumns;
this.startRow = startRow;
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
int currentRow = cell.getRowIndex();
if (currentRow <= startRow) return;
for (int col : mergeColumns) {
if (cell.getColumnIndex() == col) {
String currentValue = cell.getStringCellValue();
MergeRange lastRange = lastValueMap.get(col);
if (lastRange != null && lastRange.value.equals(currentValue)) {
// 合并到上一个范围
sheet.addMergedRegion(new CellRangeAddress(
lastRange.startRow, currentRow, col, col
));
lastValueMap.put(col, new MergeRange(
lastRange.startRow, currentValue
));
} else {
// 新值范围开始
lastValueMap.put(col, new MergeRange(
currentRow, currentValue
));
}
break;
}
}
}
private static class MergeRange {
int startRow;
String value;
MergeRange(int startRow, String value) {
this.startRow = startRow;
this.value = value;
}
}
}
完成列头合并
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; public class ComplexHeadStrategy implements CellWriteHandler { public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) { if (head.getColumnIndex() == 0 || head.getColumnIndex() == 4) { // 第一列和第五列 Sheet sheet = writeSheetHolder.getSheet(); if (cell.getRowIndex() == 0) { // 首行 // 合并"引导车误差分析"标题 sheet.addMergedRegion(new CellRangeAddress( 0, 0, 0, 1 // 合并前两列 )); sheet.addMergedRegion(new CellRangeAddress( 0, 0, 4, 5 // 合并最后两列 )); } } } }
Demo实现
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import lombok.Data; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.IndexedColors; import java.util.ArrayList; import java.util.List; public class MergeCellExportDemo { public static void main(String[] args) { List<FlightData> dataList = new ArrayList<>(); dataList.add(new FlightData("0.12", "0.5", "B-1234", "A01", "0.08", "0.3")); dataList.add(new FlightData("0.15", "0.6", "B-5678", "B02", "0.09", "0.4")); // 自定义合并策略(合并机号列) CustomMergeStrategy mergeStrategy = new CustomMergeStrategy( new int[]{2, 3}, 1 // 合并第3、4列(机号/机位) ); // 设置表头样式 WriteCellStyle headStyle = new WriteCellStyle(); headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); WriteCellStyle contentStyle = new WriteCellStyle(); contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy(headStyle, contentStyle); EasyExcel.write("flight_report.xlsx") .head(FlightData.class) .registerWriteHandler(new ComplexHeadStrategy()) // 复杂表头处理 .registerWriteHandler(mergeStrategy) .registerWriteHandler(styleStrategy) .sheet("航班数据") .doWrite(dataList); } // 数据模型类(对应图片中的列) @Data static class FlightData { @ExcelProperty({"引导车开始", "开始_分析误差"}) private String startAnalysisError; @ExcelProperty({"引导车开始", "开始_终端误差(s)"}) private String startTerminalError; @ExcelProperty("机号") private String flightNumber; @ExcelProperty("机位") private String gate; @ExcelProperty({"引导车结束", "结束_分析误差"}) private String endAnalysisError; @ExcelProperty({"引导车结束", "结束_终端误差(s)"}) private String endTerminalError; public FlightData(String startAnalysisError, String startTerminalError, String flightNumber, String gate, String endAnalysisError, String endTerminalError) { this.startAnalysisError=startAnalysisError; this.startTerminalError=startTerminalError; this.flightNumber=flightNumber; this.gate=gate; this.endAnalysisError=endAnalysisError; this.endTerminalError=endTerminalError; } } }