没什么难度,只是一个记录一个用例,同时以后在需要前端导出表格时,可以直接粘贴代码使用。代码如下:
import XLSX, { utils } from 'xlsx'
exportTable () {
let workSheet = null
const workBook = utils.book_new()
for (let i = 0; i < sheetArr.length; i++) {
workSheet = this.exportTableAction(columns[i], tableData[i]) // columns存放所有sheet中表格的列数据,tableData中存放所有sheet页表格中的数据
utils.book_append_sheet(workBook, workSheet, sheetArr[i].label)
}
XLSX.writeFile(workBook, 'test.xlsx', { bookType: 'xlsx', type: 'buffer' })
},
// 导出表格数据
exportTableAction (column, data) {
let allRowNum = 1 // title所占总行数
const rowNumArr = []
const dataIndex = []
const tableData = [] // 表格数据按照要求格式暂存容器
let positionFlag = {
r: 0,
c: 0
} // Merges标志位
let exportTitleArr = [] // 按照需求格式暂存表格列名容器
let exportMergesArr = [] // 合并单元格merges数组(s:开始,e:结束,r:行,c:列)
// 判断列元素有多少个叶节点(所占列数)
const getNodeNum = (obj) => {
let count = 0
if (obj.children) {
for (let i = 0; i < obj.children.length; i++) {
count += getNodeNum(obj.children[i])
}
return count
} else {
return count + 1
}
}
// 判断行数
const getRowNum = (obj) => {
const rowNumArr = []
if (obj.children) {
for (let i = 0; i < obj.children.length; i++) {
rowNumArr.push(getRowNum(obj.children[i]))
}
return (Math.max(...rowNumArr) + 1)
} else {
return 1
}
}
// 转换对象为所需title数组的格式(目标对象, exportTitleArr标志位)
const getPos = (obj, rIndex) => {
const c = getNodeNum(obj)
for (let i = 0; i < c; i++) {
if (i === 0)
exportTitleArr[rIndex].push(obj.title)
else
exportTitleArr[rIndex].push(null)
}
if (obj.children) {
exportMergesArr.push({ s: { r: rIndex, c: positionFlag.c }, e: { r: rIndex, c: positionFlag.c + c - 1 } })
for (let i = 0; i < obj.children.length; i++) {
getPos(obj.children[i], rIndex + 1)
}
} else {
dataIndex.push(obj.dataIndex)
if (rIndex < allRowNum - 1) {
exportMergesArr.push({ s: { r: rIndex, c: positionFlag.c }, e: { r: rIndex + (allRowNum - 1 - rIndex), c: positionFlag.c + c - 1 } })
positionFlag.c = positionFlag.c + c
for (let i = rIndex + 1; i < allRowNum; i++) {
exportTitleArr[i].push(null)
}
} else {
exportMergesArr.push({ s: { r: rIndex, c: positionFlag.c }, e: { r: rIndex, c: positionFlag.c + c - 1 } })
positionFlag.c = positionFlag.c + c
}
}
}
for (let i = 0; i < column.length; i++) {
if (column[i].children) {
rowNumArr.push(getRowNum(column[i]))
}
}
if (rowNumArr.length !== 0) {
allRowNum = Math.max(...rowNumArr)
}
if (allRowNum !== 1) {
for (let i = 0; i < allRowNum; i++) {
exportTitleArr.push([])
}
for (let i = 0; i < column.length; i++) {
if (column[i].children) {
getPos(column[i], 0)
} else {
exportTitleArr.forEach((val, index) => {
if (index === 0)
val.push(column[i].title)
else
val.push(null)
})
dataIndex.push(column[i].dataIndex)
exportMergesArr.push({ s: { r: positionFlag.r, c: positionFlag.c }, e: { r: positionFlag.r + allRowNum - 1, c: positionFlag.c } })
positionFlag.c += 1
}
}
for (let i = 0; i < data.length; i++) {
const row = []
for (let j = 0; j < dataIndex.length; j++) {
row.push(data[i][dataIndex[j]])
}
tableData.push(row)
}
const arr = [...exportTitleArr, ...tableData]
// const workBook = utils.book_new()
const workSheet = utils.aoa_to_sheet(arr)
// const fileName = this.tableTitle + '.xlsx'
workSheet['!merges'] = exportMergesArr
// utils.book_append_sheet(workBook, workSheet, this.tableTitle)
// XLSX.writeFile(workBook, fileName, { bookType: 'xlsx', type: 'buffer' })
return workSheet
} else {
const title = []
column.forEach(val => {
title.push(val.title)
dataIndex.push(val.dataIndex)
})
for (let i = 0; i < data.length; i++) {
const row = []
for (let j = 0; j < dataIndex.length; j++) {
row.push(data[i][dataIndex[j]])
}
tableData.push(row)
}
const arr = [title, ...tableData]
// const workBook = utils.book_new()
const workSheet = utils.aoa_to_sheet(arr)
// const fileName = this.tableTitle + '.xlsx'
// utils.book_append_sheet(workBook, workSheet, this.tableTitle)
// XLSX.writeFile(workBook, fileName, { bookType: 'xlsx', type: 'buffer' })
return workSheet
}
}
代码中的sheetArr主要存放sheet页的相关信息,如sheet页个数以及名字等,根据需要进行修改。columns和tableData中的数据主要是按照antdv的table组件要求的数据格式进行存放的。举简单例子来说:
const column = [
{
title: 'aaa',
dataIndex: 'bbb'
},
{
title: 'ccc',
dataIndex: 'ddd'
},
]
const tableData = [
{
bbb: '111',
ddd: '222'
},
{
bbb: '333',
ddd: '444'
},
{
bbb: '555',
ddd: '666'
}
]
这样画出来的就是一个有两列三行的表格,列名分别为aaa和ccc,直接复制代码,然后按照格式传递数据就可以用了。
xlsx使用起来还是很简单的,主要是数据处理比较麻烦,因为导出数据要求是一个二维数组,数组中的一个数组代表一行数据,而当存在合并单元格的情况时也有一些处理需求。这里主要用了几个递归来进行数据处理。