一、存在选中的单元格,不管按行还是按列拆分都将选中的单元格拆出
思路:获取选中的单元格,将原来的表格克隆一份(这样可以保证拆分出的表格与原来的表格样式一样),对克隆出来的表格进行删除未选中的单元格,需要处理跨行的单元格,将修改后的表格插入到原表格的下一个兄弟节点
拆分为
注意:如果存在跨行,修改单元格跨行数
二、跨行拆分
思路:获取光标所在行,将原来的表格A克隆一份表格B,
将表格A对该行及以下的行删除,判断是否存在跨行的单元格,需要修改跨行数;
先将跨行的单元格进行克隆记录,将表格B对该行以上的行删除(下面案例 表头不删除),同时添加跨行的单元格,需要修改跨行的行数,同时注意添加单元格的顺序;将表格B插入到表格A的下方
效果:
按行拆分后
跨行的案例
拆分后
三、跨列拆分
思路:获取光标所在列,将原来的表格A克隆一份表格B,
将表格A对该列及右边的列数删除,判断是否存在跨列的单元格,需要修改跨列数;
先将跨列的单元格进行克隆记录,将表格B对该列左边的列删除,同时添加跨行的单元格,需要修改跨列数;将表格B插入到表格A的下方
注:如果单元格占整行需要修改跨行数为1
效果:
拆分后
跨列的效果:
拆分后
代码逻辑:
代码中存在的方法或遍历需要看前面的文章:js 自定义表格的合并单元格、插入行列、删除行列_js合并单元格-优快云博客
/**
* 按列拆分单元格, 行数不变
*/
export const splitTableCol = (_this) => {
const curTable = getTable(_this.childFather)
const node = getColls(_this.childFather)
if (finalCollsArr && finalCollsArr.length>0 && finalCollsArr[0] && finalCollsArr[0].length>0 && (finalCollsArr.length>1 || finalCollsArr[0].length>1)) {
splitSelectedCell(curTable, _this)
return;
}
// 判断是否在首列
// 行转列
let newArray = list[0].map(function (col, i) {
return list.map(function (row) {
return row[i]
})
})
let num = 0;
for (let i = 0; i < newArray.length; i++) {
const arr = newArray[i];
if (arr.includes(node.id)) {
num = i;
break
}
}
if (num <= 0) {
document.getElementsByClassName('bulletFrameHandel')[0].style.display = 'block'
document.getElementsByClassName('bulletFrameHandel')[0].getElementsByClassName('tipsContent')[0].innerHTML = '不能在首列拆分表格!'
return;
}
// 前一列
let cols1 = newArray[num - 1]
// 后一列
let cols2 = newArray[num]
// 左部分列表
let agoList = []
// 右部分列表
let afterList = []
for (let i = 0; i < newArray.length; i++) {
const arr = newArray[i];
for (let j = 0; j < arr.length; j++) {
const eid = arr[j];
if (i < num) {
agoList.push(eid)
}else{
afterList.push(eid)
}
}
}
// 判断跨几列
let enjambmentIds = [];
for (let i = 0; i < cols2.length; i++) {
if (cols1[i] == cols2[i]) {
enjambmentIds.push(cols2[i])
}
}
if (enjambmentIds.length > 1) {
enjambmentIds = Array.from(new Set(enjambmentIds));
}
// {id, 左部分跨的列数, 右部分跨的列数}
let cellObjList = []
if (enjambmentIds.length > 0) {
// 判断跨了几列,拆分上下修改跨的列数
for (let i = 0; i < enjambmentIds.length; i++) {
const eId = enjambmentIds[i];
// 左部分跨的列数
let sc = 0;
// 右部分跨的列数
let ec = 0;
for (let j = 0; j < newArray.length; j++) {
if (newArray[j].includes(eId)) {
if (j < num) {
sc++;
}else{
ec++;
}
}
}
cellObjList.push({"id": eId, "sc": sc, "ec": ec});
}
}
// 原来的表格
let tagTable = curTable.parentElement
// 克隆的表格
let cloneTable = tagTable.cloneNode(true)
// 将原来的表格 删除后面的行
let sTable = tagTable.getElementsByTagName('table')[0]
// 删除 colgroup 标签中的
let colgroup = sTable.getElementsByTagName('colgroup')[0]
let cols = colgroup.getElementsByTagName('col');
let k = 0;
for (let i = 0; i < cols.length; i++) {
const element = cols[i];
if (k >= num) {
colgroup.removeChild(element);
i--;
}
k++;
}
// 获取表头,
let sThead = sTable.getElementsByTagName('thead')[0]
let sTbody;
if (sThead) {
sTbody = sThead.nextElementSibling
let sNodes = sThead.children
for (let i = 0; i < sNodes.length; i++) {
const tds = sNodes[i].children;
for (let m = 0; m < tds.length; m++) {
const el = tds[m];
// th
if (!agoList.includes(el.id)) {
// 删除
sNodes[i].removeChild(el)
m--;
}else if (enjambmentIds.length > 0 && enjambmentIds.includes(el.id)) {
// 判断是否跨行
for (let j = 0; j < cellObjList.length; j++) {
const obj = cellObjList[j];
if (obj.id === el.id) {
el.colSpan = obj.sc;
break;
}
}
}
}
}
}else{
sTbody = sTable.getElementsByTagName('tbody')[0]
}
if (sTbody) {
let sNodes = sTbody.children
for (let i = 0; i < sNodes.length; i++) {
const tds = sNodes[i].children;
for (let m = 0; m < tds.length; m++) {
const el = tds[m];
// td
if (!agoList.includes(el.id)) {
// 删除
sNodes[i].removeChild(el)
m--;
}else if (enjambmentIds.length > 0 && enjambmentIds.includes(el.id)) {
// 判断是否跨行
for (let j = 0; j < cellObjList.length; j++) {
const obj = cellObjList[j];
if (obj.id === el.id) {
el.colSpan = obj.sc;
break;
}
}
}
}
}
}
// 克隆后的表格
// 将原来的表格 删除后面的行
let cTable = cloneTable.getElementsByTagName('table')[0]
// 删除 colgroup 标签中的
colgroup = cTable.getElementsByTagName('colgroup')[0]
cols = colgroup.getElementsByTagName('col');
k = 0;
for (let i = 0; i < cols.length; i++) {
const element = cols[i];
if (k < num) {
colgroup.removeChild(element);
i--;
}
k++;
}
// 获取表头,
let cThead = cTable.getElementsByTagName('thead')[0]
let cTbody;
if (cThead) {
cTbody = cThead.nextElementSibling
let sNodes = cThead.children
for (let i = 0; i < sNodes.length; i++) {
const tds = sNodes[i].children;
for (let m = 0; m < tds.length; m++) {
const el = tds[m];
// th
if (!afterList.includes(el.id)) {
// 删除
sNodes[i].removeChild(el)
m--;
}else if (enjambmentIds.length > 0 && enjambmentIds.includes(el.id)) {
// 判断是否跨行
for (let j = 0; j < cellObjList.length; j++) {
const obj = cellObjList[j];
if (obj.id === el.id) {
el.colSpan = obj.sc;
break;
}
}
}
}
}
}else{
cTbody = cTable.getElementsByTagName('tbody')[0]
}
if (cTbody) {
// 行 tr
let sNodes = cTbody.children
for (let i = 0; i < sNodes.length; i++) {
// 单元格 td
const tds = sNodes[i].children;
for (let m = 0; m < tds.length; m++) {
const el = tds[m];
// th
if (!afterList.includes(el.id)) {
// 删除
sNodes[i].removeChild(el)
m--;
}else if (enjambmentIds.length > 0 && enjambmentIds.includes(el.id)) {
// 判断是否跨行
for (let j = 0; j < cellObjList.length; j++) {
const obj = cellObjList[j];
if (obj.id === el.id) {
el.colSpan = obj.ec;
break;
}
}
}
}
}
}
// 添加
converTagTable(cloneTable.getElementsByTagName('table')[0]);
cloneTable.setAttribute("id", `tag_${global.id}`)
global.id = global.id + 1
tagTable.insertAdjacentElement("afterend", cloneTable);
// 获取表格的单元格id分布
downTable(tagTable.getElementsByTagName('table')[0]);
// 处理跨行数,删除空行 <tr></tr>
rowEmpty(tagTable.getElementsByTagName('table')[0]);
downTable(cloneTable.getElementsByTagName('table')[0]);
rowEmpty(cloneTable.getElementsByTagName('table')[0]);
}
/**
* 按行拆分单元格,列数不变
*/
export const splitTableRow = (_this) => {
const curTable = getTable(_this.childFather)
const node = getColls(_this.childFather)
if (finalCollsArr && finalCollsArr.length>0 && finalCollsArr[0] && finalCollsArr[0].length>0 && (finalCollsArr.length>1 || finalCollsArr[0].length>1)) {
splitSelectedCell(curTable, _this)
return;
}
// 判断单元格在表头还是表体
if(!isTheadOrTbody(node)){
document.getElementsByClassName('bulletFrameHandel')[0].style.display = 'block'
document.getElementsByClassName('bulletFrameHandel')[0].getElementsByClassName('tipsContent')[0].innerHTML = '不能在表头拆分表格!'
return;
}
// 行数
let num = 0;
for (let i = 0; i < list.length; i++) {
const arr = list[i];
if (arr.includes(node.id)) {
num = i;
break
}
}
if (num === 0) {
document.getElementsByClassName('bulletFrameHandel')[0].style.display = 'block'
document.getElementsByClassName('bulletFrameHandel')[0].getElementsByClassName('tipsContent')[0].innerHTML = '不能在首行拆分表格!'
return;
}
// 判断存不存在跨行
// 跨行的单元格id
let enjambmentIds = [];
let rows1 = list[num - 1]
let rows2 = list[num]
for (let i = 0; i < rows1.length; i++) {
if (rows2[i] == rows1[i]) {
enjambmentIds.push(rows1[i])
}
}
let cellObjList = []
if (enjambmentIds.length > 1) {
enjambmentIds = Array.from(new Set(enjambmentIds));
}
if (enjambmentIds.length > 0) {
// 判断跨了几行,拆分上下修改跨的行数
for (let i = 0; i < enjambmentIds.length; i++) {
const eId = enjambmentIds[i];
// 上部分跨的行数
let sc = 0;
// 下部分跨的行数
let ec = 0;
for (let j = 0; j < list.length; j++) {
if (list[j].includes(eId)) {
if (j < num) {
sc++;
}else{
ec++;
}
}
}
cellObjList.push({"id": eId, "sc": sc, "ec": ec});
}
}
// 原来的表格
let tagTable = curTable.parentElement
// 克隆的表格
let cloneTable = tagTable.cloneNode(true)
// 将原来的表格 删除后面的行
let sTable = tagTable.getElementsByTagName('table')[0]
// 获取表头有几行,
let sThead = sTable.getElementsByTagName('thead')[0]
// 表头的行数
let s_row_num = 0;
let sTbody = null;
if (sThead) {
s_row_num = sThead.children.length;
sTbody = sThead.nextElementSibling
}else{
sTbody = sTable.getElementsByTagName('tbody')[0]
}
s_row_num -= 1;
let trs = sTbody.children;
for (let i = 0; i < trs.length; i++) {
const tr = trs[i];
s_row_num++;
if (s_row_num >= num) {
// 删除
sTbody.removeChild(tr)
i--;
}else{
let tds = tr.children
for (let j = 0; j < tds.length; j++) {
for (let k = 0; k < cellObjList.length; k++) {
const obj = cellObjList[k];
if (obj.id === tds[j].id) {
tds[j].rowSpan = obj.sc;
}
}
}
}
}
// 将克隆的删除以上的
// 将原来的表格 删除后面的行
let cTable = cloneTable.getElementsByTagName('table')[0]
// 获取表头有几行,
let cThead = cTable.getElementsByTagName('thead')[0]
let cTbody = null;
s_row_num = 0;
if (cThead) {
s_row_num = cThead.children.length;
cTbody = cThead.nextElementSibling
}else{
cTbody = cTable.getElementsByTagName('tbody')[0]
}
trs = cTbody.children;
// 需要添加的单元格{id, td}
let eTds = []
s_row_num -= 1;
for (let i = 0; i < trs.length; i++) {
const tr = trs[i];
let tds = tr.children
for (let j = 0; j < tds.length; j++) {
for (let k = 0; k < cellObjList.length; k++) {
const obj = cellObjList[k];
if (obj.id === tds[j].id) {
tds[j].rowSpan = obj.ec;
eTds.push({'id': obj.id, "td": tds[j].cloneNode(true)})
}
}
}
s_row_num++;
if (s_row_num < num) {
// 删除
cTbody.removeChild(tr)
i--;
}
}
if (enjambmentIds.length > 0) {
// 获取首行,添加跨行的单元格
let startRow = cTbody.children[0]
let tds = startRow.children
// 去重
let rows2s = Array.from(new Set(rows2));
let addCellIds = []
for (let i = 0; i < enjambmentIds.length; i++) {
let beforeId = null;
let afterId = null;
let b = false;
for (let j = 0; j < rows2s.length; j++) {
if (rows2s[j] == enjambmentIds[i]) {
b = true;
continue
}
// 如果在之前并且不在数组中
if(!b && !enjambmentIds.includes(rows2s[j])){
// 之前的id
beforeId = rows2s[j]
}else if(!enjambmentIds.includes(rows2s[j])){
afterId = rows2s[j]
break
}
}
addCellIds.push({"id": enjambmentIds[i], "beforeId": beforeId, "afterId": afterId})
}
for (let i = addCellIds.length - 1; i >= 0; i--) {
const addCellId = addCellIds[i];
let addId = addCellId.id;
// 之前的单元格id
let beforeId = addCellId.beforeId;
// 之后的单元格id
let afterId = addCellId.afterId;
let cloneTd = null;
for (let j = 0; j < eTds.length; j++) {
const eTd = eTds[j];
if (eTd.id == addId) {
cloneTd = eTd.td;
break
}
}
for (let j = 0; j < tds.length; j++) {
const add_td = tds[j];
if (beforeId && beforeId == add_td.id) {
// 之后插入
add_td.insertAdjacentElement("afterend", cloneTd);
break
}
}
}
for (let i = 0; i < addCellIds.length; i++) {
const addCellId = addCellIds[i];
let addId = addCellId.id;
// 之前的单元格id
let beforeId = addCellId.beforeId;
// 之后的单元格id
let afterId = addCellId.afterId;
let cloneTd = null;
for (let j = 0; j < eTds.length; j++) {
const eTd = eTds[j];
if (eTd.id == addId) {
cloneTd = eTd.td;
break
}
}
for (let j = 0; j < tds.length; j++) {
const add_td = tds[j];
if(!beforeId && afterId && afterId == add_td.id){
// 之前插入
startRow.insertBefore(cloneTd, add_td)
break
}
}
}
}
// 添加
converTagTable(cloneTable.getElementsByTagName('table')[0]);
cloneTable.setAttribute("id", `tag_${global.id}`)
global.id = global.id + 1
tagTable.insertAdjacentElement("afterend", cloneTable);
// 空行
downTable(tagTable.getElementsByTagName('table')[0]);
rowEmpty(tagTable.getElementsByTagName('table')[0]);
downTable(cloneTable.getElementsByTagName('table')[0]);
rowEmpty(cloneTable.getElementsByTagName('table')[0]);
}
/**
* 存在选中的单元格
* @param {*} curTable
* @param {*} _this
* @returns
*/
const splitSelectedCell = (curTable, _this) => {
if (!finalCollsArr || finalCollsArr.length <= 0 || !finalCollsArr[0] || finalCollsArr[0].length <= 0 || (finalCollsArr.length <= 1 && finalCollsArr[0].length <= 1)) {
return;
}
// 将选中的单元格复制出来;
// 添加到表格的下一个兄弟节点;
// 创建一个新的表格
let tagTable = curTable.parentElement.cloneNode(true);
// 清空内容
let idList = []
for (let i = 0; i < finalCollsArr.length; i++) {
const arr = finalCollsArr[i];
for (let j = 0; j < arr.length; j++) {
idList.push(arr[j])
let td = document.getElementById(arr[j]);
if(td){
td.innerHTML = ' '
}
}
}
deleteStyle(finalCollsArr)
let headId = finalCollsArr[0][0]
// 选中的行数
let row_num = finalCollsArr.length;
// 选中的列数
let col_num = finalCollsArr[0].length;
// 选中的首列
let headColumn = 0;
// 首行
let headRow = 0;
let b = false;
// 获取第几列
for (let i = 0; i < list.length; i++) {
const ids = list[i];
for (let j = 0; j < ids.length; j++) {
if (headId == ids[j]) {
headColumn = j;
headRow = i;
b = true;
break;
}
}
if (b) {
break;
}
}
// 尾列
let endColumn = headColumn + col_num - 1;
// 尾行
let endRow = headRow + row_num - 1;
let table = tagTable.getElementsByTagName('table')[0]
// 删除 colgroup 标签中的
let colgroup = table.getElementsByTagName('colgroup')[0]
let cols = colgroup.getElementsByTagName('col');
let k = 0;
for (let i = 0; i < cols.length; i++) {
const element = cols[i];
if (k < headColumn || k > endColumn) {
colgroup.removeChild(element);
i--;
}
k++;
}
let theads = table.getElementsByTagName('thead')
let thead = theads && theads.length > 0 ? theads[0] : null;
let tbody = thead ? thead.nextElementSibling : table.getElementsByTagName('tbody')
if (thead) {
let trs = thead.children
for (let i = 0; i < trs.length; i++) {
const tr = trs[i];
let tds = tr.children
for (let j = 0; j < tds.length; j++) {
const td = tds[j];
if (!idList.includes(td.id)) {
tr.removeChild(td);
j--;
}
}
tds = tr.children
if (!tds || tds.length <= 0) {
thead.removeChild(tr);
i--;
}
}
trs = thead.children
if (!trs || trs.length <= 0) {
table.removeChild(thead)
}
}
let trs = tbody.children
// k = countRow-1;
for (let i = 0; i < trs.length; i++) {
const tr = trs[i];
let tds = tr.children
for (let j = 0; j < tds.length; j++) {
const td = tds[j];
if (!idList.includes(td.id)) {
tr.removeChild(td);
j--;
}
}
tds = tr.children
if (!tds || tds.length <= 0) {
tbody.removeChild(tr);
i--;
}
}
trs = tbody.children
if (!trs || trs.length <= 0) {
table.removeChild(tbody)
}
// 重置ID
converTagTable(tagTable.getElementsByTagName('table')[0]);
tagTable.setAttribute("id", `tag_${global.id}`)
global.id = global.id + 1
// 遍历表格中的单元格,如果单元格占整行,跨行为1 如果单元格占整列 跨列为1
let nodes = table.children
for (let i = 0; i < nodes.length; i++) {
const el = nodes[i];
if (el.nodeName.toLowerCase() == 'thead' || el.nodeName.toLowerCase() == 'tbody') {
let rows = el.children;
for (let j = 0; j < rows.length; j++) {
const row = rows[j];
if (row.children.length === 1) {
// 占整行, 跨行为1
row.children[0].setAttribute('rowspan', 1)
}
for (let k = 0; k < row.children.length; k++) {
const col = row.children[k];
if (col.colSpan > rows.length) {
// 占满整列,跨列为1
col.setAttribute('colspan', 1)
}
}
}
}
}
// let div = document.createElement('div');
// div.appendChild(tagTable);
curTable.parentElement.insertAdjacentElement("afterend", tagTable);
downTable(tagTable.getElementsByTagName('table')[0]);
rowEmpty(tagTable.getElementsByTagName('table')[0]);
}
/**
* 重置ID
* @param {} table
*/
const converTagTable = (table) => {
table.setAttribute("id", `tag_${global.id}`)
global.id = global.id + 1
let theadList = table.getElementsByTagName('thead')
let tbodyList = table.getElementsByTagName('tbody')
let tdList = table.getElementsByTagName('td')
let thList = table.getElementsByTagName('th')
let trList = table.getElementsByTagName('tr')
let arr = [theadList, tbodyList, tdList, thList, trList]
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
const element = arr[i][j];
element.classList.remove("bag")
element.setAttribute("id", `tag_${global.id}`)
global.id = global.id + 1
}
}
let tags = table.getElementsByTagName('tag')
// 重置 tag 标签
for (let j = 0; j < tags.length; j++) {
const element = tags[j];
element.classList.remove("bag")
element.setAttribute("id", `tag_${global.id}`)
global.id = global.id + 1
}
}
export const rowEmpty = (table) => {
let nodes = table.children
for (let i = 0; i < nodes.length; i++) {
const el = nodes[i];
if (el.nodeType == 1 && (el.nodeName.toLowerCase() == 'thead') || el.nodeName.toLowerCase() == 'tbody') {
let thead = el.children
let k = thead.length
// 行号
let temp = 0
// 删除次数
let delIndex = 0
for (let j = k-1; j >=0; j--) {
let th = thead[j];
if (th.children.length<=0) {
temp = th.rowIndex
th.parentNode.removeChild(th)
delIndex++
}
}
if(temp <=0){
continue
}
let thList = Array.from(new Set(list[temp-1]));
for (let j = 0; j < thList.length; j++) {
let th = document.getElementById(thList[j])
if (th) {
th.setAttribute('rowspan', th.rowSpan - delIndex)
}
}
}
}
let trList = table.getElementsByTagName('tr')
for (let i = 0; i < trList.length; i++) {
const tr = trList[i];
if (!tr.children || tr.children.length <= 0) {
tr.parentElement.removeChild(tr)
}
}
}