导出Excel

297 阅读2分钟

使用node+react导出excel

后端导出

技术栈

  • React
  • egg.js

依赖

  • node-xlsx
  • fs
  • axios

我使用的是node-xlsx的库来进行导出 直接上代码

//后端
const xlsx = require('node-xlsx')
const fs = require('fs')

//字段映射
const column = [
      { name: '姓名', dataIndex: 'name' },
      { name: '年龄', dataIndex: 'age' },
      { name: '性别', dataIndex: 'sex' },
      { name: '电话号', dataIndex: 'phone' }
    ]

//模拟数据
const data = [
      { name: '张三', age: 20, sex: 'female', phone: '13211111111' },
      { name: '张四', age: 21, sex: 'male', phone: '13211111112' },
      { name: '张五', age: 22, sex: 'female', phone: '13211111113' },
      { name: '张六', age: 23, sex: 'male', phone: '13211111114' },
      { name: '张七', age: 24, sex: 'female', phone: '13211111115' },
    ]

const colArr = []
const colArrTwo = []

//构建xlsx导出数据

//xlsx表头
colArr.push([...column.map(col => col.name)])
colArrTwo.push([...column.map(col => col.name)])

//xlsx数据
data.forEach(item => {
    colArr.push([...column.map(col => item[col.dataIndex])])
    colArrTwo.push([...column.map(col => item[col.dataIndex])])
})

//这个是导出文件中包含两个不同工作表
const buffer = xlsx.build([{name:'导出sheet1',data:colArr},{name:'导出sheet2',data:colArrTwo}]);

//生成文件
fs.writeFileSync('exportDir/导出excel文件.xlsx', buffer, { flags: 'w' })


//返回后端目录
return {path: 'exportDir/导出excel文件.xlsx'}

客户端

import axios form 'axios'

exportData =() => {
    axios.get('/api/exportExcel').then(res => {
        const {data:{path}} = res
        location.assign(path)
    })
}

最开始我是用的location.assign来进行下载excel。后来在进行测试的时候发现如果没有该路径会报错。页面直接白掉。 然后尝试了window.open(path, '_blank')来进行下载,和location.assign的问题一样。

最后是使用插入a标签来进行下载

import axios form 'axios'

const exportData =() => {
    axios.get('/api/exportExcel').then(res => {
        const {data:{path}} = res
        const pathArr = path.split('/')
        const filename = pathArr[pathArr.length - 1]
        let el = document.createElement('a')
        el.href = data.path
        el.download = filename
        el.hidden = true
        document.body.appendChild(el)
        el.click()
        document.body.removeChild(el)
    })
}

至此前后端代码就完成了个初版。

之后需要根据生成时间来进行一个导出。因此我们需要考虑删除之前的文件,每次重建数据。

//后端
const xlsx = require('node-xlsx')
const fs = require('fs')

const fileList = fs.readdirSync(`exportDir`)
fileList.forEach(item => {
      if (!item.endsWith('.xlsx')) {
        return
      }

      fs.unlinkSync(`exportDir/${item}`)
    })

至此就完成了excel导出

前端导出

技术栈

  • React

依赖

  • xlsx
//前端
const xlsx = require('xlsx')

//字段映射
const column = [
      { name: '姓名', dataIndex: 'name' },
      { name: '年龄', dataIndex: 'age' },
      { name: '性别', dataIndex: 'sex' },
      { name: '电话号', dataIndex: 'phone' }
    ]

//模拟数据
const data = [
      { name: '张三', age: 20, sex: 'female', phone: '13211111111' },
      { name: '张四', age: 21, sex: 'male', phone: '13211111112' },
      { name: '张五', age: 22, sex: 'female', phone: '13211111113' },
      { name: '张六', age: 23, sex: 'male', phone: '13211111114' },
      { name: '张七', age: 24, sex: 'female', phone: '13211111115' },
    ]

const colArr = []
const colArrTwo = []

//构建xlsx导出数据

//xlsx表头
colArr.push([...column.map(col => col.name)])
colArrTwo.push([...column.map(col => col.name)])

//xlsx数据
data.forEach(item => {
    colArr.push([...column.map(col => item[col.dataIndex])])
    colArrTwo.push([...column.map(col => item[col.dataIndex])])
})


const sheet = XLSX.utils.book_new()

//这个是导出文件中包含两个不同工作表
const sheetDataOne = XLSX.utils.aoa_to_sheet(colArr)
XLSX.utils.book_append_sheet(sheet, sheetDataOne, '导出sheet1')

const sheetDataTwo = XLSX.utils.aoa_to_sheet(colArrTwo)
XLSX.utils.book_append_sheet(sheet, sheetDataTwo, '导出sheet2')

//导出文件
XLSX.writeFile(sheet, '导出excel.xlsx')