element-ui 表格导出excel

针对嵌套表头的这种表格做了特殊处理,主要使用了excel.js

image.png

实际导出效果图

image.png
import ExcelJS from 'exceljs'
const ColumnStyle = { alignment: { horizontal: 'center', vertical: 'middle' }, font: { name: '微软雅黑' } }
// 下划线开头函数请从lodash导入
            // 找出header 和body
            const elTableOutSide = chartControl.$el.querySelector('.el-table')
            const tableHeader = elTableOutSide.querySelector('.el-table__header')
            const tableBody = elTableOutSide.querySelector('.el-table__body')
            exportCrossTable(tableHeader, tableBody)
            // 核心部分
exportCrossTable(header, body) {
            const { _map, _filter, _isNil, _forEach, chart: { displayName }, createExcel } = this
            const workbook = new ExcelJS.Workbook()
            const worksheet = workbook.addWorksheet('index')
            // 开始整理表头数据
            const headerTrNodeList = header.querySelectorAll('tr')
            const headerTrList = _map(headerTrNodeList, trNode => {
                const thNodeList = trNode.querySelectorAll('th')
                return {
                    children: _filter(_map(thNodeList, thNode => ({
                        text: thNode.querySelector('.cell')?.innerText,
                        colspan: parseInt(thNode.getAttribute('colspan')),
                        rowspan: parseInt(thNode.getAttribute('rowspan')),
                    })), item => !_isNil(item.text)),
                }
            })
            const height = headerTrList.length  // 高
            const width = headerTrList[height - 1].children.length // 宽
            const generateRow = () => new Array(width).fill(false)
            const mergeLog = _map(new Array(height), () => generateRow())
            _forEach(headerTrList, (tr, rowIndex) => {
                const y = rowIndex + 1 // 纵坐标
                let x = 1 // 横坐标
                const currentLineLog = mergeLog[rowIndex]
                for (let i = 0; i < width; i++) {
                    if (!currentLineLog[i]) {
                        x = i + 1
                        break
                    }
                }
                _forEach(tr.children, th => {
                    const { rowspan, colspan } = th
                    const top = y // 开始行
                    const left = x // 开始列
                    const bottom = y + rowspan - 1 // 结束行
                    const right = x + colspan - 1 // 结束列
                    worksheet.mergeCells(top, left, bottom, right)
                    const cell = worksheet.getCell(top, left)
                    cell.value = th.text
                    cell.font = ColumnStyle.font
                    cell.alignment = ColumnStyle.alignment
                    for (let i = top - 1; i < bottom; i ++) {
                        for (let j = left - 1; j < right; j++) {
                            mergeLog[i][j] = true
                        }
                    }
                    x += colspan
                })
            })
            // 开始整理body处的数据
            const bodyTrNodeList = body.querySelectorAll('tr')
            const bodyTrList = _map(bodyTrNodeList, trNode => {
                const tdNodeList = trNode.querySelectorAll('td')
                return {
                    children: _filter(_map(tdNodeList, thNode => ({
                        text: thNode.querySelector('.cell')?.innerText,
                    })), item => !_isNil(item.text)),
                }
            })
            _forEach(bodyTrList, tr => {
                const row = _map(tr.children, td => td.text)
                worksheet.addRow(row)
            })
            createExcel(workbook, displayName)
        },
        // 导出
       async createExcel(excel, filename) {
            const buffer = await excel.xlsx.writeBuffer()
            const a = document.createElement('a')
            const fileUrl = URL.createObjectURL(new Blob([buffer]))
            a.href = fileUrl
            a.download = `${filename}.xlsx`
            a.click()
            URL.revokeObjectURL(fileUrl)
        },

你可能感兴趣的:(element-ui 表格导出excel)