实现el-table、markdown文本、excel表格格式间的转换

751 阅读3分钟

拥有一份markdown格式字符串数据,如何将其展示在element-ui的el-table上呢?

实现markdown文本转为对象数组格式(markdown字符串 -> 对象数组)

想要将数据展示在el-table上,并且想利用el-table的单元格编辑实现表格数据更改的话,就要拥有一份对象数组格式的数据,可以封装一个方法,解析markdown字符串,将md的表格格式部分数据抽离出来,并解析转换为对象数组。

const parseMarkdown = (markdown: any) => {
    //将markdown字符串转为对象数组格式
    const rows = markdown.split('\n')   //将markdown字符串分割成多个行的数组,用\n作为分隔符确定每个新行的边界
    let tableStart = -1 //表格的起始行
    let tableEnd = -1   //表格的结束行
    let headers = []    //表头数据
    let data = []   //表体数据
    for (let i = 0; i < rows.length; i++) {    //遍历数组中的每一行,判断该行是否以|开头,是则说明该行为表格的一行
        const row = rows[i]
        if (row.startsWith('|')) {
            if (tableStart === -1) {    //tableStart 的值为 -1,则说明该行为表格的第一行,更新 tableStart 的值为当前行的行号
                tableStart = i
                headers = row .slice(1, -1) .split('|').map((header) => header.trim())    //将该行的内容解析为表头,并存储在 headers 数组中
            } else {
                data.push( row .slice(1, -1).split('|') .map((cell) => cell.trim()))    //将该行的内容解析为数据,并存储在 data 数组中
            }
        } else {
            if (tableStart !== -1 && tableEnd === -1) {    //如果当前行不是表格的一行,且 tableStart 的值不为 -1,说明当前行为表格的最后一行,更新 tableEnd 的值为当前行的行号
                tableEnd = i
            }
        }
    }
    const table = data.map((row) => {    //将row数组转换为js对象数组
        return headers.reduce((obj, header, index) => {
            obj[header] = row[index]
            return obj
        }, {})
    })
    let title = rows.slice(0, tableStart)[0]    //表格前的标题
    let tip = rows.slice(tableEnd)[1]    //表格后的提示文案
    const content = [...rows.slice(0, tableStart), ...rows.slice(tableEnd)].join('\n').trim()
    table.shift()
    let updatedTable = table.map((tableItem) => {
        return {
            data1: tableItem.数据1,
            data2: tableItem.数据2,
            data3: tableItem.数据3,
            data4: tableItem.数据4,
            data5: tableItem.数据5
        }
    })
    return {
        updatedTable,
        title,
        tip
    }
}

想将el-table表格的数据一键复制到excel表格,该如何实现呢?

实现对象数组到HTML格式的构建(对象数组 -> HTML)

想要将el-table表格的数据复制到xlsx表格,并保持排版的话,就需要将对象数组转为xlsx支持的表格格式,也就是HTML格式的数据。

const copyTable = async (index: any) => {
    //点击复制按钮复制表格,转为可复制在excel文档上的格式
    try {
        let table = buildTable(videoList.value[index].content) //调用封装方法构建对象数组为HTML格式
        await toClipboard('<table>' + table.innerHTML.toString() + '</table>')    //前后拼接table标签,才是可复制到xlsx表格格式
        ElMessage.success('复制成功!')
    } catch (e) {
        ElMessage({
            message: '复制失败,请手动复制',
            type: 'error'
        })
    }
}
const buildTable = (data: any[]) => {
    //将对象数组转为HTML格式
    var table = document.createElement('table')    //创建HTML表格元素
    var fields = Object.keys(data[0])
    var myHead = ['数据1', '数据2', '数据3', '数据4', '数据5]    //解析出的表头是英文变量的,想复制到xlsx上时是中文形式,则自定义初始化表头数组
    var headRow = document.createElement('tr')
    myHead.forEach(function (field) {
        var headCell = document.createElement('th')
        headCell.textContent = field
        headRow.appendChild(headCell)
    })
    table.appendChild(headRow)
    data.forEach(function (object) {
        var row = document.createElement('tr')
        fields.forEach(function (field, index) {
            if (index !== fields.length - 1) {
                var cell = document.createElement('td')
                cell.textContent = object[field]
                row.appendChild(cell)
            }
        })
        table.appendChild(row)
    })
    return table
}

该方法将变量的内容复制到剪切板需要引入第三方库vue-clipboard3,执行npm install --save vue-clipboard3指令,并在代码中引入声明

import useClipboard from 'vue-clipboard3'    //clipboard可以将变量或常量直接复制到剪切板
const { toClipboard } = useClipboard()

想直接将el-table的数据导出为xlsx文件,该如何实现呢?

引入xlsx库(对象数组 -> xlsx工作流)

想要将el-table表格的直接导出为xlsx文件,表格的内容与排版都在文件内,就要引入xlsx库,将数据插入并导出。

const exportToExcel = (index: any) => {
    //导出表格,将对象数组导出为xlsx表格
    // 创建一个工作簿
    const workbook = XLSX.utils.book_new()
    // 创建一个工作表
    let header = ['数据1', '数据2', '数据3', '数据4', '数据5']    //自定义中文表头数组
    let sheet = []
    sheet.push(header)
    videoList.value[index].content.forEach((item, index) => {
        sheet.push([item.data1, item.data2, item.data3, item.data4, item.data5])
    })
    const worksheet = XLSX.utils.aoa_to_sheet(sheet)
    // 将工作表添加到工作簿
    XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
    // 生成Excel文件
    XLSX.writeFile(workbook, '内容' + (index + 1) + '.xlsx')
}

该方法需要引入第三方库xlsx

import * as XLSX from 'xlsx'