前些天接到组长分配的任务,让我这个小菜鸟实现单元格的合并。刚开始觉得很复杂,可是仔细思考过后其实还是很简单的,下面就和大家分享一下自己每次的方法和存在的缺点以及如何修改和最终的成品,希望能够对大家有些帮助。
首先合并单元格,既然是合并,肯定是要把相同的数据用一个单元格来完成。就是把这样的格式
合并成这样的
边框比较浅,图片可能不太清楚,但是能看得出来左边是三个单元格,右边是合并成了一个。
要想实现这样的效果就要有一个前提,就是相同数据应该在一起。所以后台不能直接将数据库的数据list出来(数据库数据是没有顺序的,相同数据也没有在一起)。所以我们在select *的时候需要先对数据进行排序或者分组,然后再传到前台,排序时候直接order by 字段一,字段二,字段三.... 这里面排序多个字段的含义就是在字段一相等的前提下再进行字段二的排序。所以很显然,前台要合并的数据顺序是字段一>字段二>字段三>....。将数据排序好传到前台以后,前台就要进行判断了,当数据一样时进行单元格的合并。起初合并一列单元格的时候方法如下:
function hebing1(col){var trs = $("table tr");var rows = 1;for(var i=trs.length;i>0;i--){var cur = $($(trs[i]).find("td")[col]).text();var next = $($(trs[i-1]).find("td")[col]).text();if(cur==next){rows++;$($(trs[i]).find("td")[col]).remove();} else {$($(trs[i]).find("td")[col]).attr("rowspan",rows);rows=1;}}}
这样很容易就实现了。for循环是根据你每页多少条数据,从下往上进行判断然后合并。如果从上往下合并,将代码改为
for(var i=1;i<trs.length;i++){}
之后前台就不能实现了。具体原因不清楚,应该是和下面的remove()和rowspan方法有关,奈何自己js学的太烂,并没有研究透。可能当合并多个列的时候就会出现新的问题,因为你在合并一个单元格的时候要对左边的单元格进行判断,当左边单元格数据一样的时候进行合并,不一样的时候即使右边单元格数据一样也不能进行合并。这样实现也不难,只需要多获取两个单元格进行判断就可以了。同样合并三列的时候无非又多获取两个单元格进行判断。代码如下:
function hebing2(col){var trs = $("table tr");var rows = 1;for(var i=trs.length;i>0;i--){var cur = $($(trs[i]).find("td")[col]).text();var next = $($(trs[i-1]).find("td")[col]).text();var parentId1 = $($(trs[i]).find("td")[1]).text();var parentId2 = $($(trs[i-1]).find("td")[1]).text();if(cur == next&&parentId1 == parentId2){rows++;$($(trs[i]).find("td")[col]).remove();} else {$($(trs[i]).find("td")[col]).attr("rowspan",rows);rows=1;}}}function hebing3(col){var trs = $("table tr");var rows = 1;for(var i=trs.length;i>0;i--){var cur = $($(trs[i]).find("td")[col]).text();var next = $($(trs[i-1]).find("td")[col]).text();var parentId1 = $($(trs[i]).find("td")[1]).text();var parentId2 = $($(trs[i-1]).find("td")[1]).text();var company1 = $($(trs[i]).find("td")[2]).text();var company2 = $($(trs[i-1]).find("td")[2]).text();if(cur == next&&parentId1 == parentId2&&company1 == company2){rows++;$($(trs[i]).find("td")[col]).remove();} else {$($(trs[i]).find("td")[col]).attr("rowspan",rows);rows=1;}}}function hebing4(col){var trs = $("table tr");var rows = 1;for(var i=trs.length;i>0;i--){var cur = $($(trs[i]).find("td")[col]).text();var next = $($(trs[i-1]).find("td")[col]).text();var parentId1 = $($(trs[i]).find("td")[1]).text();var parentId2 = $($(trs[i-1]).find("td")[1]).text();var company1 = $($(trs[i]).find("td")[2]).text();var company2 = $($(trs[i-1]).find("td")[2]).text();var position1 = $($(trs[i]).find("td")[3]).text();var position2 = $($(trs[i-1]).find("td")[3]).text();if(cur == next&&parentId1 == parentId2&&company1 == company2&&position1 == position2){rows++;$($(trs[i]).find("td")[col]).remove();} else {$($(trs[i]).find("td")[col]).attr("rowspan",rows);rows=1;}}}
方法名里面的234就是要合并的是第几列,以hebing4()这个方法为例,不难发现我们在进行判断的时候要判断123三列的数据是否相同,只有数据都相同了才进行合并。然后前台初始化完成后只需要调用这几个方法就行了。例如:hebing4(4); hebing3(3);hebing2(2); hebing1(1);这个括号里面的参数和方法名里面的数字意义是一样的,表示要合并的是第几列,不能省略。有人可能发现了这里是从第四列开始合并的,然后是第三列,第二列,第一列。而不是从第一列开始。这是因为如果先合并了第一列,把第一列某些单元格内容清空了,再合并后面的列的时候要获取前面列的数据进行判断,这时候就会出错误。所以要切记从右往左合并。
但是我们又发现了,这样代码很多且大部分都是重复的,而且多一列就要多写一个方法,很麻烦,于是我想到应该用嵌套循环的方法将几个方法放在一起。最后得到了下列这段代码:
//合并单元格,参数为合并的列数function hebing(col){var trs = $("table tr");var rows = 1;for(var j=col;j>0;j--){for(var i=trs.length;i>0;i--){for(var k=j;k>0;k--){var cur = $($(trs[i]).find("td")[k]).text();var next = $($(trs[i-1]).find("td")[k]).text();if(cur!=next){$($(trs[i]).find("td")[j]).attr("rowspan",rows);rows=1;break;}else if(k==1){rows++;$($(trs[i]).find("td")[j]).remove();}} } }}
这里的参数是要合并的列数,从第一列算起,中间不能间断,不能合并1和3两列。这里用到了三个循环。最外面的循环是根据列数判断要合并多少列,中间的循环是根据数据的条数进行相应次数的判断。最重要的是最里面的循环,这个循环是要看该列前面有多少列,进行多少次判断。注意K=J,J=col,但是不能写成K=col。而且什么时候用K什么时候用J一定要很清楚。使用时候直接调用这一个方法就好了,比之前的方便很多。实现的效果由于项目要保密的关系就不贴出来给大家看了。希望这个方法对大家有帮助。
说到这里可能又会有新的问题,比如如果数据很多,在进行排序时候加载数据特别慢怎么办?这里我也在思考这个问题,目前想到的解决方法是利用聚集索引直接改变数据库中数据的顺序,就不再需要order by了。关于聚集索引和非聚集索引我还分享过一个笔记,大家可以去看一下。/sun337939896/article/details/79218522
最后说一下自己的感悟:通过这一个小小的功能的实现反映出我们进行项目开发的过程,从无到有,从复杂到简单,要一步一个脚印。如果你一直想着一开始就实现最终这个方法,而忽略其中的过程,那么我相信你很难做到。如果大家急着用可以直接拿去最后的代码。如果大家和我一样处在学习成长阶段,建议从最开始的一列到多列,从多个方法到一个方法一步一步来,这个过程远比最后的结果重要很多。
注:本人尚未毕业,才疏学浅,目前能想到的方法就是这个,肯定还有很多更好的方法,大家也可以拿出来共勉。不喜勿喷。