针对嵌套表头的这种表格做了特殊处理,主要使用了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)
},
网友评论