基于apache.poi操作合并多行表头

需求:

在这里插入图片描述
将上图表头合并为下图
在这里插入图片描述

技术选型:

原本框架里使用的Easyexcel,简单调查了一下并不能符合,就基于poi手撸合并逻辑呗

代码:

逻辑:
  1. createHeader: 方法入口
  2. countHeader: 统计表头信息,列宽,行高。headerIndexList存放每个格子的宽度,用于之后合并单元格
  3. fillHeader: 根据headerIndexList填充表头信息到headerList
  4. mergedRegion: 合并单元格

    //表头文字数组
    private List<List<Columns>> headerList = new ArrayList<>();

    //表头数量数组
    private List<List<Integer>> headerIndexList = new ArrayList<>();

    /**
     * 创建表头
     * @param columns
     */
    private void createHeader(List<Columns> columns){
    
    
        //创建头样式
        XSSFCellStyle cellStyle = PoiExcelStyle.getDefaultCellTitleStyle(workbook);

        //统计表头相关信息
        countHeader(columns,0);
 
        //拼表头
        if (headerIndexList.size() > 1){
    
    
            for (int i = 0;i < headerIndexList.size() - 1;i++){
    
    
                fillHeader(i,i + 1);
            }
        }

        //列宽 = 最后一行的列表长度
        colNum = headerIndexList.get(headerIndexList.size() - 1).size();
        String[] args;

        //遍历创建行
        for (int i = 0;i < headerIndexList.size();i++){
    
    
            args = new String[colNum];
            for (int j = 0,n = 0;j < headerIndexList.get(i).size();j++){
    
    
                int len = n + headerIndexList.get(i).get(j);
                while (n < len) {
    
    
                    args[n++] = headerList.get(i).get(j).getLabel();
                }
            }

            //创建行
            createRowCells((short) 600,cellStyle,args);
        }

        //合并单元格
        dp = new int[headerIndexList.size()];
        loc = new int[headerIndexList.size()];
        mergedRegion(0,colNum);
    }

    //动态一下
    //记录每行当前长度
    private int[] dp;

    //记录每行当前位置
    private int[] loc;

    /**
     * 合并表头单元格
     * @param deep
     * @param len
     */
    private void mergedRegion(int deep,int len){
    
    
        //合并同类型单元格 sheet.addMergedRegion(new CellRangeAddress(开始行, 结束行, 开始列, 结束列))
        for (int i = loc[deep];(i < headerIndexList.get(deep).size() && len > 0);i++) {
    
    
            int l = headerIndexList.get(deep).get(i);
            len -= l;
            if (l == 1 && deep == indexRow - 1){
    
    
                dp[deep]++;
                loc[deep]++;
            }else if (l == 1 && deep != indexRow - 1 && (headerList.get(deep).get(i).getChildren() == null || headerList.get(deep).get(i).getChildren().size() == 0)) {
    
    
                sheet.addMergedRegion(new CellRangeAddress(deep,indexRow - 1, dp[deep], dp[deep]));
                for (int d = deep;d < dp.length;d++){
    
    
                    dp[d]++;
                    loc[d]++;
                }
            }else if (l >= 1){
    
    
                if (l > 1) sheet.addMergedRegion(new CellRangeAddress(deep,deep , dp[deep], dp[deep] + l - 1));
                dp[deep] += l;
                loc[deep]++;
                mergedRegion(deep + 1,l);
            }
        }
    }

    /**
     * 填充头信息
     * @param p
     * @param c
     */
    private void fillHeader(int p,int c){
    
    
        for (int i = 0,j = 0;i < headerIndexList.get(p).size();i++){
    
    
            if (headerIndexList.get(p).get(i) == 1 && (headerList.get(p).get(i).getChildren() == null || headerList.get(p).get(i).getChildren().size() == 0)){
    
    
                headerIndexList.get(c).add(j,1);
                headerList.get(c).add(j++,headerList.get(p).get(i));
            }else{
    
    
                int n = headerIndexList.get(p).get(i);
                do{
    
    
                    n -= headerIndexList.get(c).get(j++);
                }while (n > 0);
            }
        }
    }

    /**
     * 统计header信息
     * @param columns
     * @param tier
     * @return
     */
    private int countHeader(List<Columns> columns,int tier){
    
    
        if (headerIndexList.size() == tier)
            headerIndexList.add(new ArrayList<>());
        if (headerList.size() == tier)
            headerList.add(new ArrayList<>());

        int num = 0;
        for (Columns item : columns){
    
    
            //存入Header label
            headerList.get(tier).add(item);
            if (item.getChildren() == null || item.getChildren().size() == 0){
    
    
                propKeys.add(item.getProperty());
                num += 1;
                headerIndexList.get(tier).add(1);
            }else {
    
    
                int result = countHeader(item.getChildren(),tier + 1);
                headerIndexList.get(tier).add(result);
                num += result;
            }
        }

        return num;
    }

猜你喜欢

转载自blog.csdn.net/qq_16253859/article/details/125799218