There is a high probability that Table tables are involved in the project, and there will be a need to export Excel. In the project, the xlsx plug-in is generally used to export
Implementation process
train of thought
先来理一下实现这个需求的大纲
1. 首先是安装插件并使用
2. 获取到要导出的数据
3. 编写导出方法
4. 处理成xlsx插件接收的数据
5. 导出表格定制化
install plugin
npm install xlsx
npm install xlsx-js-style --save
npm install file-saver --save
npm install xlsx
npm install xlsx-js-style --save
npm install file-saver --save
import * as XLSX from 'xlsx' //Introduction to XLSX plug-in
import XLSXJSStyle from 'xlsx-js-style' //Customized XLSX style plug-in
import FileSaver from 'file-saver' //After adding styles, you need to use fileSaver everywhere (if You can directly use the export method of xlsx without using xlsx-js-style)
import * as XLSX from 'xlsx' //导XLSX插件
import XLSXJSStyle from 'xlsx-js-style' //定制化XLSX的样式插件
import FileSaver from 'file-saver' //添加样式后需要用fileSaver到处(如果不使用xlsx-js-style可以直接用xlsx的导出方法)
Get the data to be exported
I use antdv in my project, so I won’t show too much here
Write the export method
Our project requirements require merging cells, and the specific data format will be shown later
/**
*
* @param tableData 要导出的数据(必填)
* @param columns 要导出的数据的表头(必填)因为是用的表格组件所以我这里直接传的就是table组件要求的columns
* @param name 导出文件名称默认为test
* @param sheetName
* @param merges 要合并行/列 格式为 [{s:{r:x,c:x},e:{}}]
*/
export function exportExcel(
tableData,
columns,
name = 'test',
sheetName = 'sheetName',
merges: any = [],
) {
/* convert state to workbook */
const data: any[] = []
const keyArray: any[] = columns.map((item) => item.key) //获取key
const titleArr: any[] = columns.map((item) => item.title) //获取表头
// keyArray为英文字段表头
tableData.forEach((item) => {
const arr: any[] = keyArray.map((key) => {
return item[key]
})
data.push(arr)
})
data.splice(0, 0, titleArr)
// data.split(0,0,keyArray,titleArr) 如果需要英文表头的话
console.log('data', data)
const ws: any = XLSX.utils.aoa_to_sheet(data)
const wb = XLSX.utils.book_new()
// 此处隐藏英文字段表头
// const wsrows = [{ hidden: true }]
// ws['!rows'] = wsrows // ws - worksheet
ws['!merges'] = merges
console.log(ws)
for (const key in ws) {
if (key != '!rows' && key != '!merges' && key != '!ref') {
ws[key].s = {
alignment: {
horizontal: 'center', //水平居中
vertical: 'center', //垂直居中
},
}
}
}
XLSX.utils.book_append_sheet(wb, ws, sheetName)
const wbout = XLSXJSStyle.write(wb, {
bookType: 'xlsx', bookSST: true, type: 'array' })
try {
FileSaver.saveAs(new Blob([wbout], {
type: 'application/octet-stream' }), `${
name}.xlsx`)
} catch (error) {
}
}
Process into the data desired by xlsx
Our data is a piece of data in which a certain field is in the form of an array, so when exporting, we need to split it into corresponding data according to this field, and then merge the repeated fields. I will take the fields in our project as an example, the data The format is as follows
[
{
createTime: '',
deviceID: '',
deviceSN: '',
firewallVersion: '',
lastActiveTime: '',
online: '',
productID: '',
productName: '',
projectList: [
{
projectAddress: '',
projectID: '',
projectName: '',
projectShortName: '',
},
],
},
]
//导出方法具体使用
function exportSelectFun() {
let tableData = JSON.parse(JSON.stringify(state.selectedRows))
let {
arr, merges } = formatData(tableData, true) //拆分数据,以及处理合并单元格的数据
exportExcel(
arr,
[
{
title: '序号',
dataIndex: 'index',
key: 'index',
ellipsis: true,
},
...columns.filter((item) => item.key != 'operation'),
],
'智能终端设备列表',
'sheetName',
merges,
)
}
/**
*拆分数据以及处理数据
*target 目标数据
*flag 是否要拆分
*/
function formatData(target, flag = false) {
let arr: any[] = []
let merges: any[] = []
target.forEach((item, index) => {
let newArr = item.projectList.map((v) => {
let obj = {
...item,
...v,
index: index + 1,
}
obj.location = obj.projectAddress
if (flag) {
obj.monitorItemName = ''
obj.monitorPointName = ''
if (Array.isArray(obj.monitorPointList)) {
obj.monitorItemName = removeDuplicates(
obj.monitorPointList.map((point) => point.monitorItemName),
)?.join(',')
obj.monitorPointName = obj.monitorPointList
.map((point) => point.monitorPointName)
?.join(',')
}
}
return obj
})
//调用getMerges生成合并的数据
//这里用的取巧的办法
// 1.start传的是arr的长度,因为每次循环都会把拆分的数据重新添加到arr中所以我们start就用arr.length
// 2.end参数传的是newArr的长度,因为每次拆分好的数据是newArr 所以我要合并单元格的结束位置就是这个newArr,首次的时候newArr.length,之后就要变成arr.length+length了
if (arr.length == 0) {
merges.push(...getMerges(arr.length, newArr.length))
} else {
merges.push(...getMerges(arr.length, arr.length + newArr.length))
}
arr.push(...newArr)
})
return {
arr, merges }
}
/*
* 处理合并单元格参数merges
* start 起始位置
* end 结束位置
* num 是要合并几列
*/
function getMerges(start, end, num = 5) {
let merges: any[] = []
start += 1 //因为合并的时候要去除表头所以start要+1
for (let index = 0; index < num; index++) {
merges.push({
s: {
r: start, c: index }, e: {
r: end, c: index } })
}
console.log(merges)
return merges
}
export display
epilogue
It ended in a hurry, because it was time to get off work, and the workers never worked overtime hahahaha