easyExcel动态合并单元格

//注意点 判断合并的列值最好在第一列

 /**
     * @param: downloadPath
     * @param: templateStr
     * @param: map
     * @param: mergeColumns 需要合并的列
     * @param: mergeRowIndex 从第几行开始合并
     * @param: column 判断合并的列值
     * @return void
     **/
    public static  void dynamicDataDownloadFile(String downloadPath, String templateStr, Map<String, Object> map, int[] mergeColumns, int mergeRowIndex,Integer dataColumnBy) {
        // 模板文件路径
        String templatePath = RuoYiConfig.getUploadPath()+File.separator+templateStr;
        ExcelWriter excelWriter = EasyExcelFactory.write(downloadPath).withTemplate(templatePath).registerWriteHandler(new ExcelFillCellMergeStrategy(dataColumnBy,mergeRowIndex,mergeColumns)).build();
        WriteSheet writeSheet = EasyExcelFactory.writerSheet(0).build();
        FillConfig fillConfig = FillConfig.builder().build();
        Map<String,Object> fillData = map;
        // 列表型填充
        int i = 1;
        // list型数据填充结束标识,true代表结束
        boolean flag = false;
        // 多个list标识,true代表有多个
        boolean listFlag = false;
        // 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存  此处默认为true,兼容历史代码
        boolean forceFlag = (boolean) fillData.getOrDefault("forceFlag", true);
        // 纵向列表,表名集合
        String listName = "list" + i;
        if (!listFlag && fillData.containsKey("list2")) {
            listFlag = true;
            // 多表时,也要配置,以防数据重叠
            forceFlag = true;
        }
        Object list0 = fillData.get(listName);
        if (Objects.isNull(list0)) {
            flag = true;
        }
        List<Map<String, Object>> list = (List<Map<String, Object>>) list0;
        if (forceFlag) {
            fillConfig.setForceNewRow(Boolean.TRUE);
        }
        fillConfig.setDirection(WriteDirectionEnum.VERTICAL);
        excelWriter.fill(fillData, fillConfig, writeSheet);
        excelWriter.fill(list, fillConfig, writeSheet);
        
        // 单元格型填充
        Object map3 = fillData.get("map");
        if (Objects.nonNull(map3)) {
            excelWriter.fill(map3, writeSheet);
        }
        excelWriter.finish();
    }




import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
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.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.List;
import java.util.Objects;

/**
 * @title: ExcelFillCellMergeStrategy
 * @projectName asbproject
 */
public class ExcelFillCellMergeStrategy implements CellWriteHandler {
    /** 需要进行单元格合并的列数组 **/
      private int[] mergeColumnIndex;
     /** 单元格合并从第几行开始 **/
      private int mergeRowIndex;
      
      private Integer mergeDataByIndex;
      public ExcelFillCellMergeStrategy() {
          
      }
    
      public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
         this.mergeRowIndex = mergeRowIndex;
         this.mergeColumnIndex = mergeColumnIndex;
     }
      public ExcelFillCellMergeStrategy(Integer mergeDataByIndex,int mergeRowIndex, int[] mergeColumnIndex) {
         this.mergeRowIndex = mergeRowIndex;
         this.mergeColumnIndex = mergeColumnIndex;
         this.mergeDataByIndex = mergeDataByIndex;
     }
    
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        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, mergeDataByIndex);
                    break;
                }
            }
        }
    }
    
    /**
     * 当前单元格向上合并
     *
     * @param writeSheetHolder
     * @param cell
     *            当前单元格
     * @param curRowIndex
     *            当前行
     * @param curColIndex
     *            当前列
     */
    /**
     * 当前单元格向上合并
     *
     * @param writeSheetHolder
     * @param cell
     *            当前单元格
     * @param curRowIndex
     *            当前行
     * @param curColIndex
     *            当前列
     */
    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex, int mergeDataByIndex) {
        Object curData =
                cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        Row preRow = cell.getSheet().getRow(curRowIndex - 1);
        Row curRow = cell.getSheet().getRow(curRowIndex );
        if (preRow == null) {
            // 当获取不到上一行数据时,使用缓存sheet中数据
            preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);
        }
        if (curRow == null) {
            // 当获取不到本行数据时,使用缓存sheet中数据
            curRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex );
        }
        Cell preCell = preRow.getCell(curColIndex);
        Object preData =
                preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
        // 将当前单元格数据与上一个单元格数据比较(20221122 当合并数据的逻辑发生改变---根据某一列的数据相同来决定是否合并)
        Boolean dataBool = Objects.nonNull(mergeDataByIndex) ? equalsPreData(preRow,curRow,mergeDataByIndex) : preData.equals(curData);
        if (dataBool) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> 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);
            }
        }
    }
    
    private Boolean equalsPreData(Row preRow, Row curRow, int mergeDataByIndex) {
        Cell preCell = preRow.getCell(mergeDataByIndex);
        Cell curCell = curRow.getCell(mergeDataByIndex);
        if (null == preCell || null == curCell) {
            return false;
        }
        Object preData =
                preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
        Object curData =
                curCell.getCellTypeEnum() == CellType.STRING ? curCell.getStringCellValue() : curCell.getNumericCellValue();
        return preData.equals(curData);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值