使用EasyExcel对excel数据进行合并,

业务背景:要求同列的不同行的相同数据进行合并,部分列需要依据code进行比对然后进行合并,主要的技术栈使用EasyExcel进行合并,先把最小维度的每条数据查询出来,然后对这些数据按着合并策略进行合并。

1、先查询出所有符合要求的数据,需要把输出list放到最小单元那一层,保证每一条数据都要有数据。

public List<RiskIdentifyDatoExportToDataExcelDto> getRiskIdentifyList(UserInfo userInfo, Long id) {
    log.info("辨识风险导出数据,查询id:{}",id);
    List<RiskIdentifyDatoExportToDataExcelDto> resultList=new ArrayList<>();
    CtuRiskIdentify ctuRiskIdentify = ctuRiskIdentifyReadMapper.selectById(id);
    CtuDangerOrigin dangerOrigin = ctuDangerOriginReadMapper.selectByRiskKey(ctuRiskIdentify.getRiskKey());
    String dangerOriKey = dangerOrigin.getDangerOriKey();
    //分析对象和业态
    AnalysisObject analysisObject = analysisObjectReadMapper.selectById(ctuRiskIdentify.getAnalysisObjId());
    Business business = businessReadMapper.selectById(ctuRiskIdentify.getBusinessId());
    CtuAnalysisCategory analysisCategory = ctuAnalysisCategoryReadMapper.selectById(ctuRiskIdentify.getAnalysisCategoryId());
    //找辨识最小单元管控措施
    List<CtuDangerCase> ctuDangerCases = ctuDangerCaseReadMapper.selectByDangerKey(dangerOriKey);
    //风险等级 需评价完成后
    List<String> riskKeys=new ArrayList<>();
    riskKeys.add(ctuRiskIdentify.getRiskKey());
    List<AssessRiskLevelDTO> riskLevelDTOS = assessServiceHandler.queryDangerRiskLevel(riskKeys);
    //风险单元
    String riskUnitCode = ctuRiskIdentify.getRiskUnitCode();
    List<String> riskUnitCodes=new ArrayList<>(1);
    riskUnitCodes.add(riskUnitCode);
    List<RiskUnitLevelDto> diffLevelRiskUnitList = diffLevelRiskUnitService.getDiffLevelRiskUnit(riskUnitCodes).getData();
    for(CtuDangerCase dangerCase:ctuDangerCases){
        //查询危险致因管控措施
        List<CtuDangerCaseMethod> dangerCaseMethods=ctuDangerCaseMethodReadMapper.selectByCaseCode(dangerCase.getDangerCaseCode());
        if(!CollectionUtils.isEmpty(dangerCaseMethods)){
            for(CtuDangerCaseMethod dangerCaseMethod:dangerCaseMethods){
                RiskIdentifyDatoExportToDataExcelDto item=new RiskIdentifyDatoExportToDataExcelDto();
                item.setAnalysisObjId(ctuRiskIdentify.getAnalysisObjId());
                item.setControlMethod(dangerCaseMethod.getControlMethod());
                item.setDangerCaseCode(dangerCase.getDangerCaseCode());
                item.setDangerName(dangerOrigin.getDangerName());
                item.setDangerOriKey(dangerOriKey);
                item.setCreator(ctuRiskIdentify.getCreator());
                item.setControlDept(dangerCase.getOrgDep());
                item.setIfClock(dangerCase.getIfClock()==1?"是":"否");
                item.setDangerSourceCause(dangerCase.getDangerCaseName());
                item.setDangerSourceType(dangerOrigin.getDangerName());
                if(dangerCase.getIfClock()==1){
                    DictionaryInfo dictionaryInfo = dics.get(dangerCase.getControlRate());
                    if(Objects.isNull(dictionaryInfo)){
                        DictionaryInfo dbDic = dictionaryInfoReadMapper.selectById(dangerCase.getControlRate());
                        if(Objects.nonNull(dbDic)){
                            dics.put(Ints.tryParse(dangerCase.getControlRate()),dbDic);
                            BeanUtils.copyProperties(dbDic,dictionaryInfo);
                        }
                    }
                    item.setControlRate(dictionaryInfo.getSelectValue());
                    String startEndTime=dangerCase.getControlStartTime()+"——"+dangerCase.getControlEndTime();
                    item.setControlStartEndTime(startEndTime);
                }
                item.setControlType(dangerCase.getControlType()==1?"人工巡查":"物联智巡");
                //查询危险致因管控责任人
                QueryWrapper<CtuControlPerson> queryWrapperPerson = new QueryWrapper<>();
                queryWrapperPerson.eq("case_id",dangerCaseMethod.getDangerCaseId());
                queryWrapperPerson.eq("case_type",1);
                List<CtuControlPerson> ctuControlPeoples = ctuControlPersonReadMapper.selectList(queryWrapperPerson);
                if(!CollectionUtils.isEmpty(ctuControlPeoples)){
                    List<String> controlPeoples = ctuControlPeoples.stream().map(CtuControlPerson::getControlPerson).collect(Collectors.toList());
                    item.setControlPersons(String.join(",", controlPeoples));
                }
                if(Objects.nonNull(analysisObject)){
                    item.setAnaObjName(analysisObject.getAnaObjName());
                }
                if(Objects.nonNull(business)){
                    item.setBusinessName(business.getBusinessName());
                }
                if(Objects.nonNull(analysisCategory)){
                    item.setAnalysisCategoryName(analysisCategory.getAnaCategoryName());
                }
                String createTime = DateFormatUtils.format(ctuRiskIdentify.getCreateTime(), "yyyy-MM-dd HH:mm:ss");
                item.setCreateTime(createTime);
                if(!CollectionUtils.isEmpty(riskLevelDTOS)){
                    AssessRiskLevelDTO assessRiskLevelDTO = riskLevelDTOS.get(0);
                    item.setRiskLevel(assessRiskLevelDTO.getRiskLevel());
                }
                setRiskUnitName(diffLevelRiskUnitList,item);
                resultList.add(item);
            }
        }
    }

2、合并策略

@Slf4j
public class HierarchicalMergeStrategy implements RowWriteHandler{
    private final List<RiskIdentifyDatoExportToDataExcelDto> dataList;

    public HierarchicalMergeStrategy(List<RiskIdentifyDatoExportToDataExcelDto> dataList) {
        this.dataList = dataList;
    }

    @Override
    public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer rowIndex, Boolean isHead) {
        // 排除表头行
        if (isHead || rowIndex == 0) {
            return;
        }
        Sheet sheet = writeSheetHolder.getSheet();
        RiskIdentifyDatoExportToDataExcelDto currentData = dataList.get(rowIndex);
        RiskIdentifyDatoExportToDataExcelDto previousData = dataList.get(rowIndex - 1);
        // 对不同列的层次进行合并
        mergeColumns(sheet, rowIndex, currentData, previousData);
    }

    private void mergeColumns(Sheet sheet, int rowIndex, RiskIdentifyDatoExportToDataExcelDto currentData, RiskIdentifyDatoExportToDataExcelDto previousData) {
        //危险致因相同 合并
        if (StringUtils.isNotBlank(currentData.getDangerCaseCode()) && currentData.getDangerCaseCode().equals(previousData.getDangerCaseCode())) {
            mergeCells(sheet, rowIndex, 13,currentData.getDangerSourceCause());
        }
        //事故成因相同 合并
        if (StringUtils.isNotBlank(currentData.getAccidCaseCode()) && currentData.getAccidCaseCode().equals(previousData.getAccidCaseCode())) {
            mergeCells(sheet, rowIndex, 13,currentData.getDangerSourceCause());
        }
        // 危险源描述相同 合并
        if (StringUtils.isNotBlank(currentData.getDangerCaseCode()) && currentData.getDangerCaseCode().equals(previousData.getDangerCaseCode())&&
                currentData.getDangerOriKey().equals(previousData.getDangerOriKey())) {
            mergeCells(sheet, rowIndex, 12,currentData.getDangerSourceType());
        }
        //事故相同 合并
        if (StringUtils.isNotBlank(currentData.getAccidCaseCode()) && currentData.getAccidCaseCode().equals(previousData.getAccidCaseCode())
           && currentData.getAccidentTypeCode().equals(previousData.getAccidentTypeCode())) {
            mergeCells(sheet, rowIndex, 12,currentData.getDangerSourceType());
        }
        //危险源合并
        if(StringUtils.isNotBlank(currentData.getDangerOriKey()) && currentData.getDangerOriKey().equals(previousData.getDangerOriKey())){
            mergeCells(sheet, rowIndex, 10,currentData.getDangerName());
        }
        //分析对象合并
        if(Objects.nonNull(currentData.getAnalysisObjId()) && currentData.getAnalysisObjId().equals(previousData.getAnalysisObjId())){
            mergeCells(sheet, rowIndex, 9,currentData.getAnaObjName());
        }
        //风险单元合并
        if(StringUtils.isNotBlank(currentData.getOneUnitName())&&currentData.getOneUnitName().equals(previousData.getOneUnitName())){
            mergeCells(sheet, rowIndex, 2,currentData.getOneUnitName());
        }
        if(StringUtils.isNotBlank(currentData.getTwoUnitName())&&currentData.getTwoUnitName().equals(previousData.getTwoUnitName())){
            mergeCells(sheet, rowIndex, 3,currentData.getTwoUnitName());
        }
        if(StringUtils.isNotBlank(currentData.getThreeUnitName())&&currentData.getThreeUnitName().equals(previousData.getThreeUnitName())){
            mergeCells(sheet, rowIndex, 4,currentData.getThreeUnitName());
        }
        if(StringUtils.isNotBlank(currentData.getFourUnitName())&&currentData.getFourUnitName().equals(previousData.getFourUnitName())){
            mergeCells(sheet, rowIndex, 5,currentData.getFourUnitName());
        }
        if(StringUtils.isNotBlank(currentData.getFiveUnitName())&&currentData.getFiveUnitName().equals(previousData.getFiveUnitName())){
            mergeCells(sheet, rowIndex, 6,currentData.getFiveUnitName());
        }
        //分析对象类型和业态
        if(StringUtils.isNotBlank(currentData.getAnalysisCategoryName())&&currentData.getAnalysisCategoryName().equals(previousData.getAnalysisCategoryName())){
            mergeCells(sheet, rowIndex, 7,currentData.getAnalysisCategoryName());
        }
        if(StringUtils.isNotBlank(currentData.getBusinessName())&&currentData.getBusinessName().equals(previousData.getBusinessName())){
            mergeCells(sheet, rowIndex, 8,currentData.getBusinessName());
        }
        //上报时间上报人
        if(StringUtils.isNotBlank(currentData.getCreator())&&currentData.getCreator().equals(previousData.getCreator())){
            mergeCells(sheet, rowIndex, 0,currentData.getCreator());
        }
        if(StringUtils.isNotBlank(currentData.getCreateTime())&&currentData.getCreateTime().equals(previousData.getCreateTime())){
            mergeCells(sheet, rowIndex, 1,currentData.getCreateTime());
        }
        //风险等级
        if(StringUtils.isNotBlank(currentData.getRiskLevel()) && currentData.getRiskLevel().equals(previousData.getRiskLevel())){
            mergeCells(sheet, rowIndex, 11,currentData.getRiskLevel());
        }
    }

    private void mergeCells(Sheet sheet, int rowIndex, int columnIndex, String cellStringValue) {
        log.info("合并单元格内容,行数:{},列数:{},单元格内容:{}",rowIndex,columnIndex,cellStringValue);
        // 获取之前的合并区域并继续合并
        // 先检查是否已经有合并的区域
        int mergedRegionsCount = sheet.getNumMergedRegions();
        if (mergedRegionsCount > 0) {
            // 遍历已经存在的合并区域
            for (int i = 0; i < mergedRegionsCount; i++) {
                CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
                if (mergedRegion.getFirstColumn() == columnIndex && mergedRegion.getLastColumn() == columnIndex) {
                    // 如果当前行已经在某个合并区域内,扩展这个合并区域
                    if ((rowIndex >= mergedRegion.getFirstRow() && rowIndex <= mergedRegion.getLastRow()) ||
                            (rowIndex - 1 >= mergedRegion.getFirstRow() && rowIndex - 1 <= mergedRegion.getLastRow())) {
                        if(cellStringValue !=null && cellStringValue.equals(sheet.getRow(rowIndex-1).getCell(columnIndex).getStringCellValue())){
                            sheet.removeMergedRegion(i);
                            sheet.addMergedRegion(new CellRangeAddress(mergedRegion.getFirstRow(), rowIndex+1, columnIndex, columnIndex));
                            return;
                        }else{
                            sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex+1, columnIndex, columnIndex));
                            return;
                        }
                    }

                }
            }
        }
        // 如果没有找到现有的合并区域,则创建新的合并区域
        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex+1, columnIndex, columnIndex));
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以通过实现EasyExcel的WriteHandler接口来实现相同数据合并单元格的功能。具体步骤如下: 1. 新建一个类实现WriteHandler接口,并重写对应的方法。 2. 在实现的方法中,通过Excel的API获取到要合并的单元格的起始行、起始列、结束行、结束列。可以使用Map来记录每一种相同数据的位置信息,然后再遍历Map合并单元格。 3. 使用EasyExcel的write方法时,通过指定Handler参数,将编写好的WriteHandler实例传递进去即可。 下面是示例代码: ```java public class MergeCellWriteHandler implements WriteHandler { private Map<String, List<CellRangeAddress>> mergeMap = new HashMap<>(); @Override public void row(int i, List<Object> list) { //处理行数据,将相同的数据合并单元格 String key = list.get(0).toString(); //以第一列为key if (mergeMap.containsKey(key)) { List<CellRangeAddress> cellRangeList = mergeMap.get(key); CellRangeAddress lastCellRange = cellRangeList.get(cellRangeList.size() - 1); if (i - lastCellRange.getLastRow() == 1) { //如果上一个单元格的结尾行是当前行的上一行,则可以合并单元格 lastCellRange.setLastRow(i); } else { cellRangeList.add(new CellRangeAddress(i, i, 0, list.size() - 1)); //如果不连续,则新建一个单元格范围 } } else { List<CellRangeAddress> cellRangeList = new ArrayList<>(); cellRangeList.add(new CellRangeAddress(i, i, 0, list.size() - 1)); mergeMap.put(key, cellRangeList); } } @Override public void sheet(int i) { } @Override public void start() { } @Override public void end() { //处理完整个sheet后,将记录的单元格范围进行合并 Sheet sheet = EasyExcel.writerSheet().build().getSheet(); for (Map.Entry<String, List<CellRangeAddress>> entry : mergeMap.entrySet()) { String key = entry.getKey(); List<CellRangeAddress> cellRangeList = entry.getValue(); for (CellRangeAddress cellRange : cellRangeList) { sheet.addMergedRegion(cellRange); } } } } ``` 使用方法: ```java EasyExcel.write("test.xlsx") .sheet() .registerWriteHandler(new MergeCellWriteHandler()) .head(head) .doWrite(data); ``` 其中head和data分别是表头和数据,可以从数据库或其他数据源中获取。要实现合并单元格,需要将第一列相同的数据合并。示例中以第一列为key,记录每一种相同数据所对应的单元格范围,最后进行合并
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力终会有回报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值