ONE
已经生成的数据表格大致内容如下:
地区 | 地区 | 商品代码 | 商品名称 | 数量 | 有效期至 | 距效期(月) | 产品批号 | 规格 | 单位 | 条形码 |
---|---|---|---|---|---|---|---|---|---|---|
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 广州 | 00027 | 白花油 | |||||||
广东 | 广州 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 |
需要将前四列具有相同文本的相邻单元格进行自动合并,合并后如下:
地区 | 地区 | 商品代码 | 商品名称 | 数量 | 有效期至 | 距效期(月) | 产品批号 | 规格 | 单位 | 条形码 |
---|---|---|---|---|---|---|---|---|---|---|
广东 | 深圳 | 00028 | 红花油 | |||||||
广州 | 00027 | 白花油 | ||||||||
00028 | 红花油 | |||||||||
深圳 | ||||||||||
1、在html的head中引入jQuery
2、添加合并单元格的函数
1. //函数说明:合并指定表格(表格id为_w_table_id)指定列(列数为_w_table_colnum)的相同文本的相邻单元格
2. //参数说明:_w_table_id 为需要进行合并单元格的表格的id。如在HTMl中指定表格 id="data" ,此参数应为 #data
3. //参数说明:_w_table_colnum 为需要合并单元格的所在列。为数字,从最左边第一列为1开始算起。
4. function _w_table_rowspan(_w_table_id,_w_table_colnum){
5. _w_table_firsttd = "";
6. _w_table_currenttd = "";
7. _w_table_SpanNum = 0;
8. _w_table_Obj = $(_w_table_id + " tr td:nth-child(" + _w_table_colnum + ")");
9. _w_table_Obj.each(function(i){
10. if(i==0){
11. _w_table_firsttd = $(this);
12. _w_table_SpanNum = 1;
13. }else{
14. _w_table_currenttd = $(this);
15. if(_w_table_firsttd.text()==_w_table_currenttd.text()){
16. _w_table_SpanNum++;
17. _w_table_currenttd.hide(); //remove();
18. _w_table_firsttd.attr("rowSpan",_w_table_SpanNum);
19. }else{
20. _w_table_firsttd = $(this);
21. _w_table_SpanNum = 1;
22. }
23. }
24. });
25. }
26.
27. //函数说明:合并指定表格(表格id为_w_table_id)指定行(行数为_w_table_rownum)的相同文本的相邻单元格
28. //参数说明:_w_table_id 为需要进行合并单元格的表格id。如在HTMl中指定表格 id="data" ,此参数应为 #data
29. //参数说明:_w_table_rownum 为需要合并单元格的所在行。其参数形式请参考jQuery中nth-child的参数。
30. // 如果为数字,则从最左边第一行为1开始算起。
31. // "even" 表示偶数行
32. // "odd" 表示奇数行
33. // "3n+1" 表示的行数为1、4、7、10.
34. //参数说明:_w_table_maxcolnum 为指定行中单元格对应的最大列数,列数大于这个数值的单元格将不进行比较合并。
35. // 此参数可以为空,为空则指定行的所有单元格要进行比较合并。
36. function _w_table_colspan(_w_table_id,_w_table_rownum,_w_table_maxcolnum){
37. if(_w_table_maxcolnum == void 0){_w_table_maxcolnum=0;}
38. _w_table_firsttd = "";
39. _w_table_currenttd = "";
40. _w_table_SpanNum = 0;
41. $(_w_table_id + " tr:nth-child(" + _w_table_rownum + ")").each(function(i){
42. _w_table_Obj = $(this).children();
43. _w_table_Obj.each(function(i){
44. if(i==0){
45. _w_table_firsttd = $(this);
46. _w_table_SpanNum = 1;
47. }else if((_w_table_maxcolnum>0)&&(i>_w_table_maxcolnum)){
48. return "";
49. }else{
50. _w_table_currenttd = $(this);
51. if(_w_table_firsttd.text()==_w_table_currenttd.text()){
52. _w_table_SpanNum++;
53. _w_table_currenttd.hide(); //remove();
54. _w_table_firsttd.attr("colSpan",_w_table_SpanNum);
55. }else{
56. _w_table_firsttd = $(this);
57. _w_table_SpanNum = 1;
58. }
59. }
60. });
61. });
62. }
3、在html的head中调用合并函数合并单元格
1. <script type="text/javascript"><!--
2. $(document).ready(function(){
3. _w_table_rowspan("#spdata",4);
4. _w_table_rowspan("#spdata",3);
5. _w_table_rowspan("#spdata",2);
6. _w_table_rowspan("#spdata",1);
7. });
8. // -->
9. </script>
TWO
合并table相同单元格的jquery插件(很精简)
正好项目中有个小需求, 要求把表格指定列中内容相同的单元格进行合并,本质上涉及的就是td的rowspan属性, 数出含相同内容单元格的个数, 然后给第一个与上一行内容不同的td其rowspan属性附上正确的值即可, 为了能直观的理解, 效果如下
原表格:
col0 | col1 | col2 | col3 |
SuZhou | 11111 | 22222 | SuZhouCity |
SuZhou | 33333 | 44444 | SuZhouCity |
SuZhou | 55555 | 66666 | SuZhouCity |
ShangHai | 77777 | 88888 | ShangHaiCity |
ShangHai | uuuuu | hhhhh | ShangHaiCity |
ShangHai | ggggg | ccccc | ShangHaiCity |
GuangZhou | ttttt | eeeee | GuangZhouCity |
GuangZhou | ppppp | qqqqq | GuangZhouCity |
处理之后的样子:
col0 | col1 | col2 | col3 |
SuZhou | 11111 | 22222 | SuZhouCity |
33333 | 44444 | ||
55555 | 66666 | ||
ShangHai | 77777 | 88888 | ShangHaiCity |
uuuuu | hhhhh | ||
ggggg | ccccc | ||
GuangZhou | ttttt | eeeee | GuangZhouCity |
ppppp | qqqqq |
效果出来, 看上去比较简单, 下面先看下页面
<table id="process" cellpadding="2" cellspacing="0" border="1">
02
<thead>
03
<tr >
04
<td>col0</td>
05
<td>col1</td>
06
<td>col2</td>
07
<td>col3</td>
08
</tr>
09
</thead>
10
<tbody>
11
<tr>
12
<td>SuZhou</td>
13
<td>11111</td>
14
<td>22222</td>
15
<td>SuZhouCity</td>
16
</tr>
17
<tr>
18
<td>SuZhou</td>
19
<td>33333</td>
20
<td>44444</td>
21
<td>SuZhouCity</td>
22
</tr>
23
<tr>
24
<td>SuZhou</td>
25
<td>55555</td>
26
<td>66666</td>
27
<td>SuZhouCity</td>
28
</tr>
29
<tr>
30
<td>ShangHai</td>
31
<td>77777</td>
32
<td>88888</td>
33
<td>ShangHaiCity</td>
34
</tr>
35
<tr>
36
<td>ShangHai</td>
37
<td>uuuuu</td>
38
<td>hhhhh</td>
39
<td>ShangHaiCity</td>
40
</tr>
41
<tr>
42
<td>ShangHai</td>
43
<td>ggggg</td>
44
<td>ccccc</td>
45
<td>ShangHaiCity</td>
46
</tr>
47
<tr>
48
<td>GuangZhou</td>
49
<td>ttttt</td>
50
<td>eeeee</td>
51
<td>GuangZhouCity</td>
52
</tr>
53
<tr>
54
<td>GuangZhou</td>
55
<td>ppppp</td>
56
<td>qqqqq</td>
57
<td>GuangZhouCity</td>
58
</tr>
59
</tbody>
60
</table>
// 这里写成了一个jquery插件的形式
2
$('#process').mergeCell({
3
// 目前只有cols这么一个配置项, 用数组表示列的索引,从0开始
4
// 然后根据指定列来处理(合并)相同内容单元格
5
cols: [0, 3]
6
});
下面看看这个小插件的完整代码:
;(function($) {
// 看过jquery源码就可以发现$.fn就是$.prototype, 只是为了兼容早期版本的插件
// 才保留了jQuery.prototype这个形式
$.fn.mergeCell = function(options) {
return this.each(function() {
var cols = options.cols;
for ( var i = cols.length - 1; cols[i] != undefined; i--) {
// fixbug console调试
// console.debug(cols[i]);
mergeCell($(this), cols[i]);
}
dispose($(this));
});
};
// 如果对javascript的closure和scope概念比较清楚, 这是个插件内部使用的private方法
// 具体可以参考本人前一篇随笔里介绍的那本书
function mergeCell($table, colIndex) {
$table.data('col-content', ''); // 存放单元格内容
$table.data('col-rowspan', 1); // 存放计算的rowspan值 默认为1
$table.data('col-td', $()); // 存放发现的第一个与前一行比较结果不同td(jQuery封装过的), 默认一个"空"的jquery对象
$table.data('trNum', $('tbody tr', $table).length); // 要处理表格的总行数, 用于最后一行做特殊处理时进行判断之用
// 我们对每一行数据进行"扫面"处理 关键是定位col-td, 和其对应的rowspan
$('tbody tr', $table).each(function(index) {
// td:eq中的colIndex即列索引
var $td = $('td:eq(' + colIndex + ')', this);
// 取出单元格的当前内容
var currentContent = $td.html();
// 第一次时走此分支
if ($table.data('col-content') == '') {
$table.data('col-content', currentContent);
$table.data('col-td', $td);
} else {
// 上一行与当前行内容相同
if ($table.data('col-content') == currentContent) {
// 上一行与当前行内容相同则col-rowspan累加, 保存新值
var rowspan = $table.data('col-rowspan') + 1;
$table.data('col-rowspan', rowspan);
// 值得注意的是 如果用了$td.remove()就会对其他列的处理造成影响
$td.hide();
// 最后一行的情况比较特殊一点
// 比如最后2行 td中的内容是一样的, 那么到最后一行就应该把此时的col-td里保存的td设置rowspan
if (++index == $table.data('trNum'))
$table.data('col-td').attr('rowspan', $table.data('col-rowspan'));
} else { // 上一行与当前行内容不同
// col-rowspan默认为1, 如果统计出的col-rowspan没有变化, 不处理
if ($table.data('col-rowspan') != 1) {
$table.data('col-td').attr('rowspan', $table.data('col-rowspan'));
}
// 保存第一次出现不同内容的td, 和其内容, 重置col-rowspan
$table.data('col-td', $td);
$table.data('col-content', $td.html());
$table.data('col-rowspan', 1);
}
}
});
}
// 同样是个private函数 清理内存之用
function dispose($table) {
$table.removeData();
}
})(jQuery);
主要的说明在注释里应该都有了, 代码的确比较简单, 像有些地方还值得改进
- 处理的table内容是从tbody开始查找的, 如果没有tbody, 那应该给出个更通用化的方案
- for ( var i = cols.length - 1; cols[i] != undefined; i--)...如果表格数据量大, 处理的列也比较多, 这里不进行优化会有造成浏览器线程阻塞的风险, 可以考虑用setTimeout
- 其他什么值得改进的, 我想应该会不少的