基于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;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值