UDN-企业互联网技术人气社区

板块导航

浏览  : 745
回复  : 6

[原生js] 多表头位置计算实现

[复制链接]
小辫儿的头像 楼主
发表于 2017-2-7 10:53:08 | 显示全部楼层 |阅读模式
  背景

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

  思路

  根据属性 colspan 得到单元格相对于当前行的相对位置 X ,后一行的位置等于 preVRow.X +prevRow.colspan

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

  原始表格
1.png

  根据 colspan 计算相对位置 x Y

  根据原始表格可知,当前 3X7 的表格,X 坐标的取值范围【0~6】,Y 的取值范围【0~2】,经过第一次计算,得到如下表格
1.png

  第二行,G 列位置本来应该是(5,1),结果经过第一计算,它跑到了(3,1)这个位置

  第三行,J K L 三列的位置都分别提前了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

  根据 rowspan 计算正确的 X

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

  B 在第一次计算后,在当前行的位置X=3

  与之后边的行中X=3的列分别是第二列的 G 和第三列的 K,而我们想要与之对应的 J

  这主要是因为,在第二行的F 列存在行合并,导致 J 的位置提前了。所以,如果从正向开始遍历,J这列的位置 X 始终少了一个单位。
  1. // author:Herbert
  2. // QQ:464884492
  3. function (headRows) {
  4.             var findFieldRows = void 0;
  5.             //计算同一行x的位置
  6.             headRows.forEach(function (rowCols, y) {
  7.                 var nextPosx = 0;
  8.                 rowCols.forEach(function (col, x) {
  9.                     col.pos = {};
  10.                     col.pos.x = nextPosx;
  11.                     col.pos.y = y;
  12.                     col.colspan = col.colspan || 1;
  13.                     nextPosx = nextPosx + col.colspan;
  14.                 });
  15.             });
  16.             //计算 rowspan对后边行的影响
  17.             for (var rowIndex = headRows.length - 1; rowIndex >= 0; rowIndex--) {
  18.                 var curRow = headRows[rowIndex];
  19.                 for (var cellIndex = 0; cellIndex < curRow.length; cellIndex++) {
  20.                     var curCell = curRow[cellIndex];
  21.                     console.log("正在处理的行:=》", curCell);
  22.                     curCell.rowspan = curCell.rowspan || 1;
  23.                     if (curCell.rowspan > 1) {
  24.                         //将后边行中所有与当前cell相同位置的单元格依次后移当前单元格x相等的单元格后移当前单元格clospan个单位
  25.                         //当前行影响下一行
  26.                         for (var nextRowindex = rowIndex + 1; nextRowindex < headRows.length && curCell.rowspan > nextRowindex - rowIndex; nextRowindex++) {
  27.                             //判断是否存在合并信息
  28.                             var nextRow = headRows[nextRowindex];
  29.                             for (var nextCellIndex = 0; nextCellIndex < nextRow.length; nextCellIndex++) {
  30.                                 var nextCell = nextRow[nextCellIndex];
  31.                                 if (nextCell.pos.x >= curCell.pos.x) {
  32.                                     nextCell.pos.x += curCell.colspan;
  33.                                     console.log("需要移动的列:=》", nextCell);
  34.                                 }
  35.                             }
  36.                         }
  37.                     }
  38.                 }
  39.         }
  40.     }
复制代码

  测试结果:

  rowspan 移动过程
  1. 正在处理的行:=》 { title: 'H', pos: { x: 0, y: 2 }, colspan: 1 }
  2. 正在处理的行:=》 { title: 'I', pos: { x: 1, y: 2 }, colspan: 1 }
  3. 正在处理的行:=》 { title: 'J', pos: { x: 2, y: 2 }, colspan: 1 }
  4. 正在处理的行:=》 { title: 'K', pos: { x: 3, y: 2 }, colspan: 1 }
  5. 正在处理的行:=》 { title: 'L', pos: { x: 4, y: 2 }, colspan: 1 }
  6. 正在处理的行:=》 { title: 'E', colspan: 2, pos: { x: 0, y: 1 } }
  7. 正在处理的行:=》 { title: 'F', rowspan: 2, pos: { x: 2, y: 1 }, colspan: 1 }
  8. 需要移动的列:=》 { title: 'J', pos: { x: 3, y: 2 }, colspan: 1, rowspan: 1 }
  9. 需要移动的列:=》 { title: 'K', pos: { x: 4, y: 2 }, colspan: 1, rowspan: 1 }
  10. 需要移动的列:=》 { title: 'L', pos: { x: 5, y: 2 }, colspan: 1, rowspan: 1 }
  11. 正在处理的行:=》 { title: 'G', pos: { x: 3, y: 1 }, colspan: 1 }
  12. 正在处理的行:=》 { title: 'A', colspan: 3, pos: { x: 0, y: 0 } }
  13. 正在处理的行:=》 { title: 'B', rowspan: 3, pos: { x: 3, y: 0 }, colspan: 1 }
  14. 需要移动的列:=》 { title: 'G', pos: { x: 4, y: 1 }, colspan: 1, rowspan: 1 }
  15. 需要移动的列:=》 { title: 'J', pos: { x: 4, y: 2 }, colspan: 1, rowspan: 1 }
  16. 需要移动的列:=》 { title: 'K', pos: { x: 5, y: 2 }, colspan: 1, rowspan: 1 }
  17. 需要移动的列:=》 { title: 'L', pos: { x: 6, y: 2 }, colspan: 1, rowspan: 1 }
  18. 正在处理的行:=》 { title: 'C', rowspan: 2, colspan: 2, pos: { x: 4, y: 0 } }
  19. 需要移动的列:=》 { title: 'G', pos: { x: 6, y: 1 }, colspan: 1, rowspan: 1 }
  20. 正在处理的行:=》 { title: 'D', pos: { x: 6, y: 0 }, colspan: 1 }
复制代码

  移动完成后效果
  1. 当前列: {"title":"A","colspan":3,"pos":{"x":0,"y":0},"rowspan":1}
  2. 当前列: {"title":"B","rowspan":3,"pos":{"x":3,"y":0},"colspan":1}
  3. 当前列: {"title":"C","rowspan":2,"colspan":2,"pos":{"x":4,"y":0}}
  4. 当前列: {"title":"D","pos":{"x":6,"y":0},"colspan":1,"rowspan":1}
  5. 当前列: {"title":"E","colspan":2,"pos":{"x":0,"y":1},"rowspan":1}
  6. 当前列: {"title":"F","rowspan":2,"pos":{"x":2,"y":1},"colspan":1}
  7. 当前列: {"title":"G","pos":{"x":6,"y":1},"colspan":1,"rowspan":1}
  8. 当前列: {"title":"H","pos":{"x":0,"y":2},"colspan":1,"rowspan":1}
  9. 当前列: {"title":"I","pos":{"x":1,"y":2},"colspan":1,"rowspan":1}
  10. 当前列: {"title":"J","pos":{"x":4,"y":2},"colspan":1,"rowspan":1}
  11. 当前列: {"title":"K","pos":{"x":5,"y":2},"colspan":1,"rowspan":1}
  12. 当前列: {"title":"L","pos":{"x":6,"y":2},"colspan":1,"rowspan":1}
复制代码

相关帖子

发表于 2017-2-7 10:53:48 | 显示全部楼层
鄙视楼下的顶帖没我快,哈哈
使用道具 举报

回复

发表于 2017-2-8 02:50:14 来自手机 | 显示全部楼层
前排支持下
使用道具 举报

回复

发表于 2017-2-8 08:08:24 | 显示全部楼层
支持下            
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部