超詳細多表頭位置計算實現


在處理網頁中的表格導出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)
E F G
H I J K L
###根據`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}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM