zoukankan      html  css  js  c++  java
  • 超详细多表头位置计算实现

    在处理网页中的表格导出Excel时,表格的多表头需要具体的位置。而网页中的多表头,都是采用 colspan 和 rowspan 表示。headRows 采用二维数组表示多表头。

    思路

    • 根据属性 colspan 得到单元格相对于当前行的相对位置 X ,后一行的位置等于 prevRow.X +prevRow.colspan
    • 根据属性 rowspan 计算跨行导致,纠正某些单元格被覆盖的情况,既 X 相等的单元格 ,需要向后移动当前单元格的 colspan 个单位。

    原始表格

    A(0,0)B(3,0)C(4,0)D(6,0)
    EFG
    HIJKL
    ###根据`colspan`计算相对位置 `x` `Y` 根据原始表格可知,当前**3X7**的表格,X 坐标的取值范围【0~6】,Y 的取值范围【0~2】,经过第一次计算,得到如下表格
    (0,0)A(1,0)(2,0)(3,0)B(4,0)C(5,0)(6,0)D
    (0,1)E(1,1)(2,1)F(3,1)G(4,1)(5,1)(6,1)
    (0,2)H(1,2)I(2,2)J(3,2)K(4,2)L(5,2)(6,2)
    同原始表格个对比,得到如下结果 - 第二行,G 列位置本来应该是(5,1),结果经过第一计算,它跑到了(3,1)这个位置 - 第三行,J K L 三列的位置都分别提前了2个单位。

    造成位置提前的原因,主要就是rowspan,跨列导致。

    • 第二行 G 的位置提前,受第一行 B C存在行合并
    • 第三行 J K L 位置提前,受到 第一行 B 第二行 F 存在行合并

    由此可知行合并影响的的行,受 rowspan 的跨度确定,即需要移动的单元个需满足两个条件

    1. 移动单元格 存在 rowspan 单元格的后边 cur.pos.x>=nextcur.pos.x
    2. 移动单元格 两个单元格的Y之差,小于合并行的跨度, nextcur.pos.y-cur.pos.y<cur.rowspan

    根据rowspan计算正确的 X

    知道计算逻辑后,还有一个需要注意的地方,行遍历需要从最后一行开始遍历。因为在第一行 B 这一列这种情况。

    • B 在第一次计算后,在当前行的位置X=3
    • 与之后边的行中X=3的列分别是第二列的 G 和第三列的 K,而我们想要与之对应的 J

    这主要是因为,在第二行的F 列存在行合并,导致 J 的位置提前了。所以,如果从正向开始遍历,J这列的位置 X 始终少了一个单位。

     // author:Herbert 
     // QQ:464884492
     function (headRows) {
                var findFieldRows = void 0;
                //计算同一行x的位置
                headRows.forEach(function (rowCols, y) {
                    var nextPosx = 0;
                    rowCols.forEach(function (col, x) {
                        col.pos = {};
                        col.pos.x = nextPosx;
                        col.pos.y = y;
                        col.colspan = col.colspan || 1;
                        nextPosx = nextPosx + col.colspan;
                    });
                });
                //计算 rowspan对后边行的影响
                for (var rowIndex = headRows.length - 1; rowIndex >= 0; rowIndex--) {
                    var curRow = headRows[rowIndex];
                    for (var cellIndex = 0; cellIndex < curRow.length; cellIndex++) {
                        var curCell = curRow[cellIndex];
                        console.log("正在处理的行:=》", curCell);
                        curCell.rowspan = curCell.rowspan || 1;
                        if (curCell.rowspan > 1) {
                            //将后边行中所有与当前cell相同位置的单元格依次后移当前单元格x相等的单元格后移当前单元格clospan个单位
                            //当前行影响以后(被rowspan包含)所有的行
                            for (var nextRowindex = rowIndex + 1; nextRowindex < headRows.length && curCell.rowspan > nextRowindex - rowIndex; nextRowindex++) {
                                //判断是否存在合并信息
                                var nextRow = headRows[nextRowindex];
                                for (var nextCellIndex = 0; nextCellIndex < nextRow.length; nextCellIndex++) {
                                    var nextCell = nextRow[nextCellIndex];
                                    if (nextCell.pos.x >= curCell.pos.x) {
                                        nextCell.pos.x += curCell.colspan;
                                        console.log("需要移动的列:=》", nextCell);
                                    }
                                }
                            }
                        }
                    }
            }
        }
    

    测试结果:

    1. rowspan 移动过程
      正在处理的行:=》 { title: 'H', pos: { x: 0, y: 2 }, colspan: 1 }
      正在处理的行:=》 { title: 'I', pos: { x: 1, y: 2 }, colspan: 1 }
      正在处理的行:=》 { title: 'J', pos: { x: 2, y: 2 }, colspan: 1 }
      正在处理的行:=》 { title: 'K', pos: { x: 3, y: 2 }, colspan: 1 }
      正在处理的行:=》 { title: 'L', pos: { x: 4, y: 2 }, colspan: 1 }
      正在处理的行:=》 { title: 'E', colspan: 2, pos: { x: 0, y: 1 } }
      正在处理的行:=》 { title: 'F', rowspan: 2, pos: { x: 2, y: 1 }, colspan: 1 }
      需要移动的列:=》 { title: 'J', pos: { x: 3, y: 2 }, colspan: 1, rowspan: 1 }
      需要移动的列:=》 { title: 'K', pos: { x: 4, y: 2 }, colspan: 1, rowspan: 1 }
      需要移动的列:=》 { title: 'L', pos: { x: 5, y: 2 }, colspan: 1, rowspan: 1 }
      正在处理的行:=》 { title: 'G', pos: { x: 3, y: 1 }, colspan: 1 }
      正在处理的行:=》 { title: 'A', colspan: 3, pos: { x: 0, y: 0 } }
      正在处理的行:=》 { title: 'B', rowspan: 3, pos: { x: 3, y: 0 }, colspan: 1 }
      需要移动的列:=》 { title: 'G', pos: { x: 4, y: 1 }, colspan: 1, rowspan: 1 }
      需要移动的列:=》 { title: 'J', pos: { x: 4, y: 2 }, colspan: 1, rowspan: 1 }
      需要移动的列:=》 { title: 'K', pos: { x: 5, y: 2 }, colspan: 1, rowspan: 1 }
      需要移动的列:=》 { title: 'L', pos: { x: 6, y: 2 }, colspan: 1, rowspan: 1 }
      正在处理的行:=》 { title: 'C', rowspan: 2, colspan: 2, pos: { x: 4, y: 0 } }
      需要移动的列:=》 { title: 'G', pos: { x: 6, y: 1 }, colspan: 1, rowspan: 1 }
      正在处理的行:=》 { title: 'D', pos: { x: 6, y: 0 }, colspan: 1 }
    2. 移动完成后效果
      当前列: {"title":"A","colspan":3,"pos":{"x":0,"y":0},"rowspan":1}
      当前列: {"title":"B","rowspan":3,"pos":{"x":3,"y":0},"colspan":1}
      当前列: {"title":"C","rowspan":2,"colspan":2,"pos":{"x":4,"y":0}}
      当前列: {"title":"D","pos":{"x":6,"y":0},"colspan":1,"rowspan":1}
      当前列: {"title":"E","colspan":2,"pos":{"x":0,"y":1},"rowspan":1}
      当前列: {"title":"F","rowspan":2,"pos":{"x":2,"y":1},"colspan":1}
      当前列: {"title":"G","pos":{"x":6,"y":1},"colspan":1,"rowspan":1}
      当前列: {"title":"H","pos":{"x":0,"y":2},"colspan":1,"rowspan":1}
      当前列: {"title":"I","pos":{"x":1,"y":2},"colspan":1,"rowspan":1}
      当前列: {"title":"J","pos":{"x":4,"y":2},"colspan":1,"rowspan":1}
      当前列: {"title":"K","pos":{"x":5,"y":2},"colspan":1,"rowspan":1}
      当前列: {"title":"L","pos":{"x":6,"y":2},"colspan":1,"rowspan":1}
  • 相关阅读:
    【python小随笔】单例模式设计(易懂版)
    【python小随笔】函数的初始化与私有化
    【python小随笔】List列表的常见函数与切片
    【itsdangerous】的加密解密原理(易懂版)
    【Django入坑之路】Django后台上传图片,以及前端的显示
    【插拔式】分页+bootstrap4(开源)
    luogu P1231 教辅的组成 |网络流最大匹配
    luogu P3376 【模板】网络最大流 |Dinic
    luogu P4177 [CEOI2008]order |最大权闭合子图
    luogu P4562 [JXOI2018]游戏 |组合数学
  • 原文地址:https://www.cnblogs.com/yfrs/p/mulittable.html
Copyright © 2011-2022 走看看