用js怎么实现像excel那样,选中多个单元格,然后点击合并选中的就合并,还可以撤销合并

qq_862792055 2015-08-15 11:25:18
谁做过这样的效果或有什么源码,插件什么的,谢谢
...全文
830 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
詩晓凝 2017-09-11
  • 打赏
  • 举报
回复
bug出现了
qq_32085095 2016-06-15
  • 打赏
  • 举报
回复
6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
qq_862792055 2015-12-23
  • 打赏
  • 举报
回复
大牛
earn666 2015-08-16
  • 打赏
  • 举报
回复 3
经过一天的努力,我实现了你的需求。 若发现 bug 请说明如何操作才会出现。 实现的难点是要考虑用户操作的随意性。 源代码如下。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="GBK" />
	<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
	<title>单元格之合并及拆分</title>

	<!-- External CSS -->
	<link href="http://lib.sinaapp.com/js/jquery-ui/1.9.2/themes/base/jquery-ui.css" rel="stylesheet">
	<link href="http://lib.sinaapp.com/js/jquery-ui/1.9.2/themes/base/jquery.ui.selectable.css" rel="stylesheet">

	<!-- In-document CSS -->
	<style>
		/* <![CDATA[ */
		#t {width: 90%;}
		#t td.ui-selecting { background: #FECA40; }
		#t td.ui-selected  { background: #F39814; color: white; }
		#t td {
			height: 18px;
			padding: 0.4em;
			font-size: 1.4em;
		}
		#feedback { font-size: 1.4em; }
		/* ]]> */
	</style>

	<!-- External JavaScript -->
	<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
	<script src="http://lib.sinaapp.com/js/jquery-ui/1.9.2/jquery-ui.min.js"></script>

	<!-- In-document JavaScript -->
	<script>
		// <![CDATA[
		$(function(){
			// 显示已选单元格编号
			function ShowSelected()
			{
					var result = $("#select-result").empty();
					var isEmpty = true;
					var tds = $("th,td", $("#t"));
					tds.filter(".ui-selected").each(function(){
						result.append("#" + (tds.index(this) + 1) + " ");
						isEmpty = false;
					});
					if (isEmpty) result.append("无");
			}
			
			// 使表格可选
			$("#t").selectable({stop: ShowSelected});
			
			// 合并单元格按钮
			$("#btnMerge").click(function(){
				var $t = $("#t");
				
				if ($("table", $t).length > 0) {
					alert("不支持嵌套表格!");
					return;
				}
				
				var sigDel = "sign4delete";  // 删除标记,用作类名
				var sigSel = "ui-selected";  // 选中标记,用作类名
				
				// 补充单元格以便后继正确计算坐标
				$("th,td", $t).each(function(){
					// 坐标要实时计算,因会实时补充
					var ridx = $("tr", $t).index($(this).parent("tr"));
					var cidx = $(this).parent().children("th,td").index(this);
					var rowspan = Number($(this).attr("rowspan")) || 1;
					var colspan = Number($(this).attr("colspan")) || 1;
					var isSel = $(this).hasClass(sigSel);
					// 非选单元格拆出的单元格要加删除标记
					
					if (rowspan <= 1 && colspan <= 1)
						return;
					// 跨格开插
					$("tr", $t).each(function(){
						var idx = $("tr", $t).index(this);
						var arr, $td = $("<td>").addClass(isSel ? sigSel : sigDel);
						
						if (idx == ridx) {
							// 本行在 [cidx] 后插入 colspan-1 个
							
							arr = $();  // 准备待插单元格
							for (var i=0; i < colspan-1; i++)
								arr = arr.add($td.clone());
							// 插入
							$("th,td", this).eq(cidx).after(arr);
							
						} else if (ridx < idx && idx < ridx + rowspan) {
							// 以下行在 [cidx] 前插入 colspan 个
							
							arr = $();  // 准备待插单元格
							for (var i=0; i < colspan; i++)
								arr = arr.add($td.clone());
							// 插入
							if (cidx > 0 && $("th,td", this).eq(cidx - 1).length > 0)
								$("th,td", this).eq(cidx - 1).after(arr);
							else if ($("th,td", this).eq(cidx).length > 0)
								$("th,td", this).eq(cidx).before(arr);
							else
								$(this).prepend(arr);
						}
					});
				});
				
				var rmin = 10000, cmin = 10000;
				var rmax = 0    , cmax = 0    ;
				var rnum        , cnum        ;
				// 计算起始和跨距
				$("th,td", $t).filter("." + sigSel).each(function(){
					var ridx = $("tr", $t).index($(this).parent("tr"));
					rmin = ridx < rmin ? ridx : rmin;
					rmax = ridx > rmax ? ridx : rmax;
					var cidx = $(this).parent().children("th,td").index(this);
					cmin = cidx < cmin ? cidx : cmin;
					cmax = cidx > cmax ? cidx : cmax;
				});
				rnum = rmax - rmin + 1;
				cnum = cmax - cmin + 1;
				
				// 合并单元格
				$("th,td", $t).each(function(){
					var ridx = $("tr", $t).index($(this).parent("tr"));
					var cidx = $(this).parent().children("th,td").index(this);
					// 标记单元格待删
					if (rmin <= ridx && ridx <= rmax
					 && cmin <= cidx && cidx <= cmax)
						$(this).addClass(sigDel);
					// 处理被选左上角单元格
					if (ridx == rmin && cidx == cmin)
						$(this).removeClass(sigDel).attr({rowspan: rnum, colspan: cnum});
					// 清理残余
					if ($(this).attr("rowspan") == 1) $(this).removeAttr("rowspan");
					if ($(this).attr("colspan") == 1) $(this).removeAttr("colspan");
				}).remove("." + sigDel);
				// 移除标记单元格
				
				ShowSelected();  // 更新选择结果文字
			});
			
			// 拆分单元格按钮
			$("#btnSplit").click(function(){
				var $t = $("#t");
				
				if ($("table", $t).length > 0) {
					alert("不支持嵌套表格!");
					return;
				}
				
				var sigDel = "sign4delete";  // 删除标记,类名,自定义
				var sigSel = "ui-selected";  // 选中标记,类名,jQuery UI 定义
				
				// 补充单元格以便后继正确计算坐标
				$("th,td", $t).each(function(){
					// 坐标要实时计算,因会实时补充
					var ridx = $("tr", $t).index($(this).parent("tr"));
					var cidx = $(this).parent().children("th,td").index(this);
					var rowspan = Number($(this).attr("rowspan")) || 1;
					var colspan = Number($(this).attr("colspan")) || 1;
					var isSel = $(this).hasClass(sigSel);
					// 非选单元格拆出的单元格要加删除标记
					
					if (rowspan <= 1 && colspan <= 1)
						return;
					
					if (isSel)
						$(this).removeAttr("colspan").removeAttr("rowspan");
					
					// 跨格开插
					$("tr", $t).each(function(){
						var idx = $("tr", $t).index(this);
						var arr, $td = $("<td>");
						
						if (!isSel)
							$td.addClass(sigDel);
						
						if (idx == ridx) {
							// 本行在 [cidx] 后插入 colspan-1 个
							
							arr = $();  // 准备待插单元格
							for (var i=0; i < colspan-1; i++)
								arr = arr.add($td.clone());
							
							$("th,td", this).eq(cidx).after(arr);
							
						} else if (ridx < idx && idx < ridx + rowspan) {
							// 以下行在 [cidx] 前插入 colspan 个
							
							arr = $();  // 准备待插单元格
							for (var i=0; i < colspan; i++)
								arr = arr.add($td.clone());
							
							if (cidx > 0 && $("th,td", this).eq(cidx - 1).length > 0)
								$("th,td", this).eq(cidx - 1).after(arr);
							else if ($("th,td", this).eq(cidx).length > 0)
								$("th,td", this).eq(cidx).before(arr);
							else
								$(this).prepend(arr);
						}
					});
				});
				
				// 重新获取以取到删者并删之
				$("th,td", $t).remove("." + sigDel);
				
				ShowSelected();  // 更新选择结果文字
			});
		});
		// ]]>
	</script>
</head>

<body>

	<table id="t" border>
		<tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
		<tr><td>A</td><td>B</td><td>C</td><td>D</td></tr>
		<tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
		<tr><td>5</td><td>6</td><td>7</td><td>8</td></tr>
	</table>

	<p id="feedback">
	你选择的是:<span id="select-result">无</span>。
	</p>

	<button id="btnMerge">合并选中单元格</button>
	<button id="btnSplit">拆分选中单元格</button>
</body>
</html>
earn666 2015-08-15
  • 打赏
  • 举报
回复
原生JS比较难实现,你可以考虑用库,我给个思路。 我们要考虑,哪个的单元格?怎么个选法?如何合并?其中的数据如何处理?合并之后再选再合并该如何? 反之拆分如何进行。 这涉及到比较复杂的控制,至少目前没见有人做过,可见实际需求也不多。 在 jQuery UI 中有个 Selectable 模块,它的作用时,就好像我们在桌面用左键画出一个矩形,圈选图标一样,桌面图标是变高亮,而它是给被选中元素赋予一个 ui-selected 类,这样一来,我们就知道哪个单元格被选了,然后你找出被选之左上角至右下角之单元格,计算出跨距,除左上角的保留外,余者删除(小心二次合并,不能只删被选者),给左上角单元格加上 colspan 和 rowspan 属性,这就是不考虑数据的情况合并了。拆分为其逆过程,比较麻烦的是补充单元格,要细心耐心。

87,995

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧