导入excel功能

获取导入的excel数据, 导入excel接口

import { reqImportEmployee } from '@/api/employees'
export default {
  name: 'Import',
  methods: {
    async handleSuccess({ header, results }) {
      // header中, results中的数据是中文的, 但是提交给后台的要是英文的
      const userRelations = {
        '入职日期': 'timeOfEntry',
        '手机号': 'mobile',
        '姓名': 'username',
        '转正日期': 'correctionTime',
        '工号': 'workNumber'
      }
      const arr = []
      results.forEach(item => {
        const userInfo = {}
        for (const key in item) {
          userInfo[userRelations[key]] = item[key]
        }
        arr.push(userInfo)
      })
      // 调用导入接口
      await reqImportEmployee(arr) // 调用导入接口
      this.$router.back()
    }
  }
}

当excel中有日期格式的时候,实际转化的值为一个数字,我们需要一个方法进行转化 (已准备好)

Excel存储的日期是从1900年1月1日开始按天数来计算的,也就是说1900年1月1日在Excel中是1。

formatExcelDate(numb, format) {
  const time = new Date((numb - 1) * 24 * 3600000 + 1)  // 毫秒
  time.setYear(time.getFullYear() - 70)
  const year = time.getFullYear() + ''
  const month = time.getMonth() + 1 + ''
  const date = time.getDate() - 1 + ''
  if (format && format.length === 1) {
    return year + format + (month < 10 ? '0' + month : month) + format + (date < 10 ? '0' + date : date)
  }
  return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
}

处理日期:

methods: {
    async handleSuccess({ header, results }) {
      // header中, results中的数据是中文的, 但是提交给后台的要是英文的
      const userRelations = {
        '入职日期': 'timeOfEntry',
        '手机号': 'mobile',
        '姓名': 'username',
        '转正日期': 'correctionTime',
        '工号': 'workNumber'
      }
      const arr = []
      results.forEach(item => {
        const userInfo = {}
        for (const key in item) {
          if (['timeOfEntry', 'correctionTime'].includes(userRelations[key])) {
            userInfo[userRelations[key]] = this.formatExcelDate(item[key], '-')
          } else {
            userInfo[userRelations[key]] = item[key]
          }
        }
        arr.push(userInfo)
      })
      // 调用导入接口
      await reqImportEmployee(arr) // 调用导入接口
      this.$router.back()
    },

    // 转换excel的日期格式
    formatExcelDate(numb, format) {
      const time = new Date((numb - 1) * 24 * 3600000 + 1)
      time.setYear(time.getFullYear() - 70)
      const year = time.getFullYear() + ''
      const month = time.getMonth() + 1 + ''
      const date = time.getDate() - 1 + ''
      if (format && format.length === 1) {
        return year + format + (month < 10 ? '0' + month : month) + format + (date < 10 ? '0' + date : date)
      }
      return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
    }
  }
}

导出excel功能

Excel 的导入导出都是依赖于js-xlsx来实现的。
js-xlsx的基础上又封装了Export2Excel.js来方便导出数据

安装excel所需依赖和按需加载
由于 Export2Excel不仅依赖js-xlsx还依赖file-saverscript-loader

所以你先需要安装如下命令:

yarn add xlsx file-saver script-loader

vue-element-admin提供了 导出的功能模块,在课程资源/excel导出目录下的 vender,放置到src目录下

由于js-xlsx体积还是很大的,导出功能也不是一个非常常用的功能,所以使用的时候建议使用懒加载。使用方法如下:

import('@/vendor/Export2Excel').then(excel => {
  excel.export_json_to_excel({
    header: ['姓名', '工资'], // 表头 必填
    data: [
      ['刘备', 100],
      ['关羽', 500]
    ], // 具体数据 必填
    filename: 'excel-list', // 非必填
    autoWidth: true, // 非必填
    bookType: 'xlsx' // 非必填
  })
})

excel导出参数的介绍

参数

参数说明类型可选值默认值
header导出数据的表头Array/[]
data导出的具体数据Array/[[], []]
filename导出文件名String/excel-list
autoWidth单元格是否要自适应宽度Booleantrue / falsetrue
bookType导出文件类型Stringxlsx, csv, txt, morexlsx

excel导出基本的结构

我们最重要的一件事,就是把 表头 和 数据 进行相应的对应

因为数据中的key是英文,想要导出的表头是中文的话,需要将中文和英文做对应

const headersArr = ['姓名', '手机号', '入职日期', '聘用形式', '转正日期', '工号', '部门']
const headersRelations = {
  '姓名': 'username',
  '手机号': 'mobile',
  '入职日期': 'timeOfEntry',
  '聘用形式': 'formOfEmployment',
  '转正日期': 'correctionTime',
  '工号': 'workNumber',
  '部门': 'departmentName'
}

然后,完成导出代码

async clickExport() {
  // 请注意: 如果导出的是当前页, 那么数据, this.list 即可,
  // 但是我们一般导出的是全部的数据, 需要请求到所有的数据
  const { data: { rows }} = await reqGetEmployeeList(1, this.total)
  const headersArr = ['姓名', '手机号', '入职日期', '聘用形式', '转正日期', '工号', '部门']
  const headersRelations = {
    '姓名': 'username',
    '手机号': 'mobile',
    '入职日期': 'timeOfEntry',
    '聘用形式': 'formOfEmployment',
    '转正日期': 'correctionTime',
    '工号': 'workNumber',
    '部门': 'departmentName'
  }
  const dataArr = this.formatJson(rows, headersArr, headersRelations)

  import('@/vendor/Export2Excel').then(excel => {
    excel.export_json_to_excel({
      header: headersArr, // 表格的头部
      // 二维数组 [ [], [], [] ]
      data: dataArr,
      filename: '学生信息表', // 导出的excel文件名
      autoWidth: true, // 是否开启单元格宽度自适应
      bookType: 'xlsx' // 类型
    })
  })
},

// 将表头数据和数据进行对应
formatJson(rows, headersArr, headersRelations) {
  // [
  //   [ 值1, 值2, 值3, ... ]
  // ]
  const resultsArr = rows.map(item => {
    const arr = []
    headersArr.forEach(key => {
      const englishKey = headersRelations[key]
      arr.push(item[englishKey])
    })
    return arr
  })
  return resultsArr
}

导出时间和聘用形式的格式处理

formatJson(rows, headersArr, headersRelations) {
  // [
  //   [ 值1, 值2, 值3, ... ]
  // ]
  const resultsArr = rows.map((item) => {
    const arr = []
    headersArr.forEach(key => {
      const englishKey = headersRelations[key]
      let value = item[englishKey]
      if (['timeOfEntry', 'correctionTime'].includes(englishKey)) {
        value = formatDate(value)
      }
      if (englishKey === 'formOfEmployment') {
        const obj = EmployeeEnum.hireType.find(obj => obj.id === +value)
        value = obj ? obj.value : '未知'
      }
      arr.push(value)
    })
    return arr
  })
  return resultsArr
}

复杂表头的导出

vue-element-admin 提供的导出方法中有 multiHeadermerges** 的参数

参数说明类型可选值默认值
multiHeader复杂表头的部分Array/[[]]
merges需要合并的部分Array/[]

multiHeader里面是一个二维数组,里面的一个元素是一行表头,假设你想得到一个如图的结构

2022-06-05T03:26:09.png

mutiHeader应该这样定义

const multiHeader = [['姓名', '主要信息', '', '', '', '', '部门']]

multiHeader中的一行表头中的字段的个数需要和真正的列数相等,假设想要跨列,多余的空间需要定义成空串

它主要对应的是标准的表头

const header = ['姓名', '手机号', '入职日期', '聘用形式', '转正日期', '工号', '部门']

如果,我们要实现其合并的效果, 需要设定merges选项

 const merges = ['A1:A2', 'B1:F1', 'G1:G2']

merges的顺序是没关系的,只要配置这两个属性,就可以导出复杂表头的excel了

async clickExport() {
  // 请注意: 如果导出的是当前页, 那么数据, this.list 即可,
  // 但是我们一般导出的是全部的数据, 需要请求到所有的数据
  const { data: { rows }} = await reqGetEmployeeList(1, this.total)
  const headersArr = ['姓名', '手机号', '入职日期', '聘用形式', '转正日期', '工号', '部门']
  const multiHeader = [['姓名', '主要信息', '', '', '', '', '部门']]
  const headersRelations = {
    '姓名': 'username',
    '手机号': 'mobile',
    '入职日期': 'timeOfEntry',
    '聘用形式': 'formOfEmployment',
    '转正日期': 'correctionTime',
    '工号': 'workNumber',
    '部门': 'departmentName'
  }
  const dataArr = this.formatJson(rows, headersArr, headersRelations)
  const merges = ['A1:A2', 'B1:F1', 'G1:G2']

  import('@/vendor/Export2Excel').then(excel => {
    excel.export_json_to_excel({
      header: headersArr, // 表格的头部
      // 二维数组 [ [], [], [] ]
      data: dataArr,
      filename: '学生信息表', // 导出的excel文件名
      autoWidth: true, // 是否开启单元格宽度自适应
      bookType: 'xlsx', // 类型
      multiHeader,
      merges
    })
  })
},

发表评论