基于注解、反射實(shí)現(xiàn)Excel導(dǎo)出動態(tài)合并" />
<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 10412字,需瀏覽 21分鐘

           ·

          2021-10-01 02:52

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

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

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

          合并后的效果

          二、首先創(chuàng)建注解類。
          作用:加載導(dǎo)出字段上,order 表示分組次數(shù)。0表示一次分組,1表示二次分組,依次類推
          isflag 表示分組策略,如果為true,則用來這個字段作為當(dāng)前合并的依據(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)導(dǎo)出、導(dǎo)入實(shí)現(xiàn)如果不懂請查看官方文檔
          https://www.yuque.com/easyexcel/doc/easyexcel

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

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

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

          詳細(xì)見代碼

          /**
               * 生成合并策略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("導(dǎo)出時發(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ù)進(jìn)行合并操作

           @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
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色老板成人无码版在线播放 | 91麻豆精品 | www在线 | 国产亚洲 久一区二区草榴AV | 五月丁香六月激情 |