使用EasyExcel 导出复杂的合并单元格
引入pom.xml
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency>
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;}@Overrideprotected 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);}// 数据模型类(对应图片中的列)@Datastatic 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;}} }