> 需求是这样滴(>_
在报表系统中,涉及“HTML的TD单元格的合并”恐怕为数不少。
比如,从DB查得数据并经过后台的整理后,可能是这样的:
Table1
JOBTOTAL SALINDEXEMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO
1
ANALYST
6000
1
7788
SCOTT
ANALYST
7566
4/19/1987
3000.00
20
1
ANALYST
6000
2
7902
FORD
ANALYST
7566
12/3/1981
3000.00
20
2
CLERK
4150
3
7934
MILLER
CLERK
7782
1/23/1982
1300.00
10
2
CLERK
4150
4
7900
JAMES
CLERK
7698
12/3/1981
950.00
30
2
CLERK
4150
5
7369
SMITH
CLERK
7902
12/17/1980
800.00
20
2
CLERK
4150
6
7876
ADAMS
CLERK
7788
5/23/1987
1100.00
20
3
MANAGER
8275
7
7698
BLAKE
MANAGER
7839
5/1/1981
2850.00
30
3
MANAGER
8275
8
7566
JONES
MANAGER
7839
4/2/1981
2975.00
20
3
MANAGER
8275
9
7782
CLARK
MANAGER
7839
6/9/1981
2450.00
10
4
PRESIDENT
5000
10
7839
KING
PRESIDENT
11/17/1981
5000.00
10
5
SALESMAN
5600
11
7844
TURNER
SALESMAN
7698
9/8/1981
1500.00
0.00
30
5
SALESMAN
5600
12
7654
MARTIN
SALESMAN
7698
9/28/1981
1250.00
1400.00
30
5
SALESMAN
5600
13
7521
WARD
SALESMAN
7698
2/22/1981
1250.00
500.00
30
5
SALESMAN
5600
14
7499
ALLEN
SALESMAN
7698
2/20/1981
1600.00
300.00
30
为了让用户更清晰地查看报表,结果可能需要是这样的(各职位的薪水总额及分布明细):
Table2
JOBTOTAL SALINDEXEMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO
1
ANALYST
6000
1
7788
SCOTT
ANALYST
7566
4/19/1987
3000.00
20
2
7902
FORD
ANALYST
7566
12/3/1981
3000.00
20
2
CLERK
4150
3
7934
MILLER
CLERK
7782
1/23/1982
1300.00
10
4
7900
JAMES
CLERK
7698
12/3/1981
950.00
30
5
7369
SMITH
CLERK
7902
12/17/1980
800.00
20
6
7876
ADAMS
CLERK
7788
5/23/1987
1100.00
20
3
MANAGER
8275
7
7698
BLAKE
MANAGER
7839
5/1/1981
2850.00
30
8
7566
JONES
MANAGER
7839
4/2/1981
2975.00
20
9
7782
CLARK
MANAGER
7839
6/9/1981
2450.00
10
4
PRESIDENT
5000
10
7839
KING
PRESIDENT
11/17/1981
5000.00
10
5
SALESMAN
5600
11
7844
TURNER
SALESMAN
7698
9/8/1981
1500.00
0.00
30
12
7654
MARTIN
SALESMAN
7698
9/28/1981
1250.00
1400.00
30
13
7521
WARD
SALESMAN
7698
2/22/1981
1250.00
500.00
30
14
7499
ALLEN
SALESMAN
7698
2/20/1981
1600.00
300.00
30
这就需要我们对单元格进行相应的合并。
一般来说,有两种处理方法,
在编写HTML时已设置单元格的合并;
在编写HTML时未作合并处理,后期由Javascript完成单元格合并工作。
本文讲的是第2种情况。
合并单元格的步骤
比如,我要把上表Table1中数值为ANALYST的两个单元格合并。
JOB
ANALYST
ANALYST
我们首先需要将第二个ANALYST的单元格删除掉
然后设置第一个ANALYST的单元格的rowSpan属性为2(表示“跨越2行”)
> 写得不好的公用方法
之前写了一个公用Javascript方法,用以合并相邻间文本相同的单元格。
这个方法写得不好,有明显的Bug。对已做过合并的Table,这个方法有可能导致合并单元格错误。
主要的原因在于,对于合并过单元格的表格,那么被合并的行就会相应的少一个TD,而此方法依旧按未合并过单元格的情况来获取TD对象。
比如,获取第二列的所有单元格,此程序用“获取全部TR中的第二个TD”来实现,这在未合并过单元格的Table是正确的,但对于合并过单元格的Table,则未必,因为被合并的行相应地少一个单元格。
此处将代码贴出,希望大家引以为鉴。
functionmergeCell(tableObj, col) {var $tab =$(tableObj);var $trs = $tab.find("tr");varoldval;varfirstTD;var counter = 0;
$trs.each(function(index) {if (!oldval && !firstTD) {
oldval= $(this).find("td:eq(" + col + ")").text();
firstTD= $(this).find("td:eq(" + col + ")").get(0);
counter= 0;
counter++;
}else{if ($(this).find("td:eq(" + col + ")").text() ==oldval) {
$(this).find("td:eq(" + col + ")").remove();
counter++;
}else{
$(firstTD).attr("rowSpan", counter);
oldval= $(this).find("td:eq(" + col + ")").text();
firstTD= $(this).find("td:eq(" + col + ")").get(0);
counter= 0;
counter++;
}
}if (index >= $trs.length - 1) {
$(firstTD).attr("rowSpan", counter);
}
});
}
mergeCell
页面DEMO如下(HTML代码,较长):
$().ready(function() {
mergeCell($("#list_table").get(0),1);
mergeCell($("#list_table").get(0),2);
});functionmergeCell(tableObj, col) {var$tab=$(tableObj);var$trs=$tab.find("tr");varoldval;varfirstTD;varcounter= 0;
$trs.each(function(index) {if(!oldval&& !firstTD) {
oldval=$(this).find("td:eq(" +col+ ")").text();
firstTD=$(this).find("td:eq(" +col+ ")").get(0);
counter= 0;
counter++;
}else{if($(this).find("td:eq(" +col+ ")").text()==oldval) {
$(this).find("td:eq(" +col+ ")").remove();
counter++;
}else{
$(firstTD).attr("rowSpan", counter);
oldval=$(this).find("td:eq(" +col+ ")").text();
firstTD=$(this).find("td:eq(" +col+ ")").get(0);
counter= 0;
counter++;
}
}if(index>=$trs.length- 1) {
$(firstTD).attr("rowSpan", counter);
}
});
}
JOBTOTAL SALINDEXEMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO1ANALYST600017788SCOTTANALYST75664/19/19873000.00 201ANALYST600027902FORDANALYST756612/3/19813000.00 202CLERK415037934MILLERCLERK77821/23/19821300.00 102CLERK415047900JAMESCLERK769812/3/1981950.00 302CLERK415057369SMITHCLERK790212/17/1980800.00 202CLERK415067876ADAMSCLERK77885/23/19871100.00 203MANAGER827577698BLAKEMANAGER78395/1/19812850.00 303MANAGER827587566JONESMANAGER78394/2/19812975.00 203MANAGER827597782CLARKMANAGER78396/9/19812450.00 104PRESIDENT5000107839KINGPRESIDENT 11/17/19815000.00 104SUPER PRESIDENT5000107839KINGPRESIDENT 11/17/19815000.00 105SALESMAN5600117844TURNERSALESMAN76989/8/19811500.000.00305SALESMAN5600127654MARTINSALESMAN76989/28/19811250.001400.00305SALESMAN5600137521WARDSALESMAN76982/22/19811250.00500.00305SALESMAN5600147499ALLENSALESMAN76982/20/19811600.00300.0030WrongMergeTD.html
> 写得不好怎么办?卷土重来呗
于是,重新写了两个公用方法来合并单元格。
一个是合并相邻值相同的单元格;
另外一个是合并指定序号的单元格,比如2-5,6-8,是“合并第2个至第5个单元格、第6个和至第8个单元格”。
这俩方法将“获取需要合并的TD元素”的动作交由方法调用者,只负责对入参单元格作对应的合并。
JS
/**
* Meger cells with same text
* @param $tds TDs jquery object
* @param type row/col*/
functionmergeCell4SameText($tds, type) {varoldval;varfirstTD;var counter = 0;
$tds.each(function(index) {if (index == 0) {
oldval= $(this).text();
firstTD= $(this).get(0);
counter= 0;
counter++;
}else{if ($(this).text() ==oldval) {
$(this).remove();
counter++;
}else{if (type == 'col') {
$(firstTD).attr("rowSpan", counter);
}else if (type == 'row') {
$(firstTD).attr("colSpan", counter);
}
oldval= $(this).text();
firstTD= $(this).get(0);
counter= 0;
counter++;
}
}if (index >= $tds.length - 1) {if (type == 'col') {
$(firstTD).attr("rowSpan", counter);
}else if (type == 'row') {
$(firstTD).attr("colSpan", counter);
}
}
});
}/**
* Meger cells by the parameters "index"
* @param $tds TDs jquery object
* @param type row/col
* @param index for example, 0-1,2-5,6-8,10-13*/
functionmergeCellByIndex($tds, type, index) {var indexArrs = index.split(',');varfromTo;varfrom;varto;for (var i inindexArrs) {
fromTo=indexArrs[i];
from= new Number(fromTo.split('-')[0]);
to= new Number(fromTo.split('-')[1]);for (var j = 1 + from; j <= to; j++) {
$($tds.get(j)).remove();
}if (type == 'col') {
$($tds.get(from)).attr("rowSpan", to - from + 1);
}else if (type == 'row') {
$($tds.get(from)).attr("colSpan", to - from + 1);
}
}
}
tdmerger
调用的页面(HTML代码,较长):
$().ready(function() {
$col1tds=$("table tr td:nth-child(1)");
$col2tds=$("table tr td:nth-child(2)");
$col3tds=$("table tr td:nth-child(3)");
mergeCellByIndex($col1tds,'col','0-1,2-5,6-8,10-13');
mergeCellByIndex($col2tds,'col','0-1,2-5,6-8,10-13');
mergeCellByIndex($col3tds,'col','0-1,2-5,6-8,10-13');/*$row2tds = $("table tr:eq(2) td");
mergeCellByIndex($row2tds, 'row', '6-11');*/});
JOBTOTAL SALINDEXEMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO1ANALYST600017788SCOTTANALYST75664/19/19873000.00 201ANALYST600027902FORDANALYST756612/3/19813000.00 202CLERK415037934MILLERCLERK77821/23/19821300.00 102CLERK415047900JAMESCLERK769812/3/1981950.00 302CLERK415057369SMITHCLERK790212/17/1980800.00 202CLERK415067876ADAMSCLERK77885/23/19871100.00 203MANAGER827577698BLAKEMANAGER78395/1/19812850.00 303MANAGER827587566JONESMANAGER78394/2/19812975.00 203MANAGER827597782CLARKMANAGER78396/9/19812450.00 104PRESIDENT5000107839KINGPRESIDENT 11/17/19815000.00 105SALESMAN5600117844TURNERSALESMAN76989/8/19811500.000.00305SALESMAN5600127654MARTINSALESMAN76989/28/19811250.001400.00305SALESMAN5600137521WARDSALESMAN76982/22/19811250.00500.00305SALESMAN5600147499ALLENSALESMAN76982/20/19811600.00300.0030mergeTD
对于合并单元格,这两种方式都不太满意,可是,也想不到更好的方法对此操作作封装。
如果童靴有更好的方法,请指点!!