###背景 在处理网页中的表格导出Excel时,表格的多表头需要具体的位置。而网页中的多表头,都是采用 colspan 和 rowspan 表示。因为我在平常开发中多使用easyui,所以我代码中的headrows是遵循easyuidatagrid的定义方式,采用二维数组表示多表头。 ###思路
- 根据属性
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 |
(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) |
造成位置提前的原因,主要就是rowspan
,跨列导致。
- 第二行 G 的位置提前,受第一行 B C存在行合并
- 第三行 J K L 位置提前,受到 第一行 B 第二行 F 存在行合并
由此可知行合并影响的的行,受 rowspan
的跨度确定,即需要移动的单元个需满足两个条件
- 移动单元格 存在
rowspan
单元格的后边cur.pos.x>=nextcur.pos.x
- 移动单元格 两个单元格的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个单位
//当前行影响下一行
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);
}
}
}
}
}
}
}
###测试结果:
-
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 }
-
移动完成后效果 当前列: {"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}