js 自定义拆分表格 (按行/按列拆分)

一、存在选中的单元格,不管按行还是按列拆分都将选中的单元格拆出

思路:获取选中的单元格,将原来的表格克隆一份(这样可以保证拆分出的表格与原来的表格样式一样),对克隆出来的表格进行删除未选中的单元格,需要处理跨行的单元格,将修改后的表格插入到原表格的下一个兄弟节点

拆分为

注意:如果存在跨行,修改单元格跨行数

二、跨行拆分

思路:获取光标所在行,将原来的表格A克隆一份表格B,

将表格A对该行及以下的行删除,判断是否存在跨行的单元格,需要修改跨行数;

先将跨行的单元格进行克隆记录,将表格B对该行以上的行删除(下面案例 表头不删除),同时添加跨行的单元格,需要修改跨行的行数,同时注意添加单元格的顺序;将表格B插入到表格A的下方

效果:

按行拆分后

 跨行的案例

 拆分后

三、跨列拆分

思路:获取光标所在列,将原来的表格A克隆一份表格B,

将表格A对该列及右边的列数删除,判断是否存在跨列的单元格,需要修改跨列数;

先将跨列的单元格进行克隆记录,将表格B对该列左边的列删除,同时添加跨行的单元格,需要修改跨列数;将表格B插入到表格A的下方

注:如果单元格占整行需要修改跨行数为1

效果:

 拆分后

跨列的效果:

 

拆分后

 

代码逻辑:

代码中存在的方法或遍历需要看前面的文章:js 自定义表格的合并单元格、插入行列、删除行列_js合并单元格-CSDN博客

/**
 * 按列拆分单元格, 行数不变
 */
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 = '&nbsp;'
            }
        }
    }
    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)
        }
    }

}



 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值