package com.artfess.dataShare.util; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import lombok.Data; 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 javax.servlet.ServletOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; @Data public class ExcelFillCellMergeStrategy implements CellWriteHandler { /** * 合并字段的下标,如第一到五列new int[]{0,1,2,3,4} */ private int[] mergeColumnIndex; /** * 从第几行开始合并,如果表头占两行,这个数字就是2 */ private int mergeRowIndex; public ExcelFillCellMergeStrategy() { } public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) { this.mergeRowIndex = mergeRowIndex; this.mergeColumnIndex = mergeColumnIndex; } @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) { } @Override public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) { } @Override public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) { } @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List list, Cell cell, Head head, Integer integer, Boolean aBoolean) { //当前行 int curRowIndex = cell.getRowIndex(); //当前列 int curColIndex = cell.getColumnIndex(); if (curRowIndex > mergeRowIndex) { for (int i = 0; i < mergeColumnIndex.length; i++) { if (curColIndex == mergeColumnIndex[i]) { mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); break; } } } } private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并 Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :preCell.getNumericCellValue(); // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行 if (curData.equals(preData)) { Sheet sheet = writeSheetHolder.getSheet(); List mergeRegions = sheet.getMergedRegions(); boolean isMerged = false; for (int i = 0; i < mergeRegions.size() && !isMerged; i++) { CellRangeAddress cellRangeAddr = mergeRegions.get(i); // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元 if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) { sheet.removeMergedRegion(i); cellRangeAddr.setLastRow(curRowIndex); sheet.addMergedRegion(cellRangeAddr); isMerged = true; } } // 若上一个单元格未被合并,则新增合并单元 if (!isMerged) { CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex); sheet.addMergedRegion(cellRangeAddress); } } } public static void main(String[] args) { // 设置模拟表头(此处为多表头,也可以传入单表头) List> headList = new ArrayList<>(); List heads1 = new ArrayList<>(); heads1.add("总表头"); heads1.add("表头1"); headList.add(heads1); List heads2 = new ArrayList<>(); heads2.add("总表头"); heads2.add("表头2"); headList.add(heads2); List heads3 = new ArrayList<>(); heads3.add("总表头"); heads3.add("表头3"); headList.add(heads3); List heads4 = new ArrayList<>(); heads4.add("总表头"); heads4.add("表头4"); headList.add(heads4); // 设置模拟内容 List> data = new ArrayList<>(); List data1 = new ArrayList<>(); // 第1行的内容 data1.add("内容1"); data1.add("内容1-2"); data1.add("内容3"); data1.add("内容4"); List data2 = new ArrayList<>();// 第2行的内容 data2.add("内容1"); data2.add("内容2-2"); data2.add("内容3"); data2.add("内容4"); data.add(data1); data.add(data2); try { //response.setContentType("application/vnd.ms-excel"); //response.setCharacterEncoding("utf-8"); // 防止中文乱码 //String fileName = URLEncoder.encode("导入模板名称", "UTF-8"); //response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); //ServletOutputStream outputStream = response.getOutputStream(); String file="D:\\out2.xlsx"; FileOutputStream outputStream = new FileOutputStream(new File(file)); ExcelWriter writer = EasyExcel.write(outputStream).build(); WriteSheet sheet = EasyExcel.writerSheet(0).needHead(Boolean.FALSE).sheetName("sheet页名称").build(); WriteTable table = EasyExcel.writerTable(1).head(headList) // 设置只合并第1、2、3列,其余不合并 .registerWriteHandler(new ExcelFillCellMergeStrategy(1,new int[]{0,1,2})) .needHead(Boolean.TRUE).build(); writer.write(data, sheet, table); // data List data3 = new ArrayList<>();// 第2行的内容 data3.add("内容11"); data3.add("内容21-2"); data3.add("内容31"); data3.add("内容41"); data.add(data3); WriteSheet sheet1 = EasyExcel.writerSheet(1).needHead(Boolean.FALSE).sheetName("sheet页名称2").build(); WriteTable table1 = EasyExcel.writerTable(2).head(headList) // 设置只合并第1、2、3列,其余不合并 .registerWriteHandler(new ExcelFillCellMergeStrategy(1,new int[]{0,1,2})) .needHead(Boolean.TRUE).build(); writer.write(data, sheet1, table1); // data writer.finish(); } catch (IOException e) { e.printStackTrace(); } } }