基于注解、反射實現(xiàn)Excel導出動態(tài)合并" />
    1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Java實操 -> 基于注解、反射實現(xiàn)Excel導出動態(tài)合并

        共 10412字,需瀏覽 21分鐘

         ·

        2021-10-01 02:52

        點擊上方藍色字體,選擇“標星公眾號”

        優(yōu)質(zhì)文章,第一時間送達

        一、效果演示及相關(guān)說明
        由于項目信息不能泄露,這里采用測試數(shù)據(jù),下面的測試數(shù)據(jù)是手動輸入的,僅用來輔助說明下面的解釋
        測試數(shù)據(jù)原始效果

        合并后的效果

        二、首先創(chuàng)建注解類。
        作用:加載導出字段上,order 表示分組次數(shù)。0表示一次分組,1表示二次分組,依次類推
        isflag 表示分組策略,如果為true,則用來這個字段作為當前合并的依據(jù),所以和該字段order相同的字段都會合并

        import java.lang.annotation.ElementType;
        import java.lang.annotation.Retention;
        import java.lang.annotation.RetentionPolicy;
        import java.lang.annotation.Target;

        /**
         * @author hhb
         * @date :2021/9/16 13:58
         */
        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface MergeFlag {
            int order() default 0;

            boolean isflag() default false;
        }

        三、自定義合并策略
        這里使用的是alibabaEasyExcel的Excel處理框架,相關(guān)導出、導入實現(xiàn)如果不懂請查看官方文檔
        https://www.yuque.com/easyexcel/doc/easyexcel

        根據(jù)官方提供的單次合并策略OnceAbsoluteMergeStrategy可知,實現(xiàn)合并的核心代碼如下

         CellRangeAddress cellRangeAddress = new CellRangeAddress(this.firstRowIndex, this.lastRowIndex, this.firstColumnIndex, this.lastColumnIndex);
                writeSheetHolder.getSheet().addMergedRegionUnsafe(cellRangeAddress);

        所以我們接下來需要想辦法先知道那些數(shù)據(jù)是需要合并的,所以我們要預處理導出的數(shù)據(jù).
        然后根據(jù)數(shù)據(jù)上面的注解解析出一個合并map,map的key是 order,value是一個對象,包含通過反射得到的Field[]數(shù)組的index索引、合并標識。

        詳細見代碼

        /**
             * 生成合并策略Map
             * @param dataList
             * @return
             */
            private  void generateMergeMap(List dataList,Class<?> type){
                //解析分組依據(jù)
                List<MergeFlagDTO> mergeFlagDTOList = this.analyzeData(type);
                Object preObj=null;
                for (int i=0;i<dataList.size();i++){
                    //獲取合并表示
                    Object currObj=dataList.get(i);
                    if (null!=preObj){
                        //處理數(shù)據(jù)
                        try {
                            this.handData(0,mergeFlagDTOList,currObj,preObj,i);
                        } catch (IllegalAccessException e) {
                            throw new BadRequestAlertException("導出時發(fā)生解析錯誤!");
                        }
                    }
                    preObj=currObj;
                }
            }

        /**
             * 解析數(shù)據(jù)
             * @param type
             * @return
             */
            private List<MergeFlagDTO> analyzeData(Class<?> type) {
                Map<Integer, MergeFlagDTO> mergeOrderMap=new HashMap<>();
                Field[] fields = type.getDeclaredFields();
                //獲取注解列表
                for (int i=0;i<fields.length;i++){
                    MergeFlag mergeFlag = fields[i].getAnnotation(MergeFlag.class);
                    if (null!=mergeFlag){
                        //加入索引
                        MergeFlagDTO dto =mergeOrderMap.get(mergeFlag.order())==null?new MergeFlagDTO():mergeOrderMap.get(mergeFlag.order());
                        dto.getMergeIndexs().add(i);
                        dto.setOrder(mergeFlag.order());
                        if (mergeFlag.isflag()){
                            dto.setField(fields[i]);
                        }
                        mergeOrderMap.put(mergeFlag.order(),dto);
                    }
                }
                return new ArrayList<>(mergeOrderMap.values()).stream().filter(item -> null != item.getField()).sorted(Comparator.comparing(MergeFlagDTO::getOrder)).collect(Collectors.toList());
            }

         /**
             * 處理數(shù)據(jù)
             * @param start
             * @param mergeFlagDTOList
             * @param currObj
             * @param preObj
             * @param index
             * @throws IllegalAccessException
             */
            private void handData(int start,  List<MergeFlagDTO> mergeFlagDTOList, Object currObj, Object preObj, int index) throws IllegalAccessException {
                if (start<mergeFlagDTOList.size()){
                    MergeFlagDTO dto = mergeFlagDTOList.get(start);
                    Field field = dto.getField();
                    field.setAccessible(true);
                    Object currValue = field.get(currObj);
                    Object preValue = field.get(preObj);
                    if (currValue.equals(preValue)) {
                        this.fillMergeMap(dto.getMergeIndexs(),index);
                        //繼續(xù)遞歸
                        this.handData(start+1,mergeFlagDTOList,currObj,preObj,index);
                    }
                }
            }

            /**
             * 填充合并map
             * @param key
             * @param index
             */
            private void fillMergeMap(Integer key, Integer index){
                List<RowRangeDTO> rangeDTOS = mergeMap.get(key)==null?new ArrayList<>():mergeMap.get(key);
                //判斷是否需要新加
                boolean needAdd=true;
                //遍歷
                for (RowRangeDTO rangeDTO:rangeDTOS){
                    if (rangeDTO.getEndIndex().equals(index)){
                        rangeDTO.setEndIndex(index+1);
                        needAdd=false;
                    }
                }
                //如果沒有匹配上的就說明需要
                if (needAdd){
                    rangeDTOS.add(new RowRangeDTO(index,index+1));
                }
                mergeMap.put(key,rangeDTOS);
            }

        最后根據(jù)合并map對數(shù)據(jù)進行合并操作

         @Override
            protected void merge(Sheet sheet, Cell cell, Head head, Integer integer){
                //每一個cell只合并一次
                if (cell.getRowIndex()==1&&cell.getColumnIndex()==0){
                    mergeMap.keySet().forEach(key-> mergeMap.get(key).forEach(rowRangeDTO -> sheet.addMergedRegionUnsafe(new CellRangeAddress(rowRangeDTO.getStartIndex(),rowRangeDTO.getEndIndex(),key,key))));
                }
            }


          作者 |  櫻島麻衣Ss

        來源 |  cnblogs.com/ydmysm/p/merge_excel.html


        加鋒哥微信: java3459  
        圍觀鋒哥朋友圈,每天推送Java干貨!

        瀏覽 105
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            熟妇一区二区 | 紧窄粉嫩被粗大撑开 | 天天干天天摸 | 夜夜躁婷婷一区二区三区 | 黄色操逼视频免费 | 秋霞电影院午夜仑片 | 一道本一区二区视频 | 试看操逼片 | 探花国产在线 | 色婷婷5月 |