1、装置依赖

cnpm i xlsx --D

2、某个模块中引入或者全局引入

import XLSX from 'xlsx'

3、导入excel

  • commonjs(公共函数)
/** * 1、 String.fromCharCode(65 + i) + 1 :             A1,B1,C1.... * 2、 String.fromCharCode(65 + j) + (i + 2)         A2,B2,C2... *                                                   A3,B3,C3... * 测试: *  const headers = [{ key: 'date', title: '日期' }, { key: 'name', title: '名称' }] *  const  data = [{ date: '2019-05-31', name: 'megen.huang' }, { date: '2019-06-20', name: '小明' }] *  console.log(exportJsonToExcel(headers, data)) * 应用xlsx插件将json数据导出到Excel中----针对表格数据 * @param {Array} headers 表头:[{key: 'date', title: '日期'}, {key: 'name', title: '名称'}] * @param {Array} data 表体数据:[{date: '2019-05-31', name: 'megen.huang'}, {date: '2019-06-20', name: '小明'}] * @param {String} fileName 导出的文件名称 :'export.xlsx' */export function exportJsonToExcel (headers = [], data = [], fileName = 'export.xlsx') {// 先解决数据  data = handleCSV(data)  const _headers = headers    .map((item, i) => Object.assign({}, { key: item.key, title: item.title, position: String.fromCharCode(65 + i) + 1 }))    .reduce((prev, next) => Object.assign({}, prev, { [next.position]: { key: next.key, v: next.title }}), {})  const _data = data  // 二维数组    .map((item, i) => headers.map((key, j) => Object.assign({}, { content: item[key.key], position: String.fromCharCode(65 + j) + (i + 2) })))    // 二维转一维    .reduce((prev, next) =>  prev.concat(next))    // 转成worksheet须要的数据结构    .reduce((prev, next) => Object.assign({}, prev, { [next.position]: { v: next.content }}), {})  // 合并 headers 和 data  const output = Object.assign({}, _headers, _data)  console.log('output', output)  // 获取所有单元格的地位  const outputPos = Object.keys(output)  // 计算出范畴 ,["A1",..., "H2"]  const ref = `${outputPos[0]}:${outputPos[outputPos.length - 1]}`  console.log('ref', ref)  // 构建 workbook 对象  const wb = {    SheetNames: ['mySheet'],    Sheets: {      mySheet: Object.assign(        {},        output,        {          '!ref': ref,          '!cols': headers.map(item => ({ wpx: 120 }))// width in screen pixels        }      )    }  }  // 导出 Excel  XLSX.writeFile(wb, fileName)}// 避免CSV注入解决export function handleCSV (arr) {  const reg = new RegExp('(^=|^-)')  if (Array.isArray(arr) && arr.length > 0) {    for (const item of arr) {      Object.keys(item).forEach(key => {        if (item[key] && reg.test(item[key])) {          item[key] = '\'' + item[key]        }      })    }  }  return arr}/** * 日期格局转换 * `第一个参数为传入的以毫秒为单位的工夫戳,第二个参数为格局,具体阐明见代码; * 不传参则返回以后日期,则为“'yyyy年MM月dd日'”格局显示.` * @param {object} _date 日期 * @param {string} _format 转换后的日期格局 */export function FormatDate (_date, _format) {  if (_format && !_date) {    return ''  }  var date = _date || new Date()  var format = _format || 'yyyy/MM/dd'  date = new Date(_date)  var map = {    M: date.getMonth() + 1, // 月份    d: date.getDate(), // 日    h: date.getHours(), // 小时    m: date.getMinutes(), // 分    s: date.getSeconds(), // 秒    q: Math.floor((date.getMonth() + 3) / 3), // 季度    S: date.getMilliseconds() // 毫秒  }  format = format.replace(/([yMdhmsqS])+/g, function (all, t) {    var v = map[t]    if (v !== undefined) {      if (all.length > 1) {        v = '0' + v        v = v.substr(v.length - 2)      }      return v    } else if (t === 'y') {      return (date.getFullYear() + '').substr(4 - all.length)    }    return all  })  return format}
  • html
<template><div>  <!-- 这里应用了ElementUI的el-upload组件 -->  <el-upload        ref="upload"        class="upload-demo"        :action="''"        :multiple="false"        :show-file-list="false"        :limit="1"        :before-upload="beforeAvatarUpload"        :file-list="fileList"      >从Excel导入      </el-upload></div></template>
  • js
import { exportJsonToExcel, deepClone, FormatDate } from '@/utils'data(){  return {    outJson: [], // 最初要发送给后盾的json数据    // 导入表头必填字段      excelHeaderRequired: [        '序号(必填)',        '子工作名称(必填)',        '子工作内容(必填)',        '执行人(必填)',        '预计开始工夫(必填)',        '预计实现工夫(必填)',        '紧急水平(必填)'      ],      exportHeader: Object.freeze([{        key: 'index', title: '序号' }, {        key: 'workItem', title: '事项名称' }, {        key: 'taskName', title: '子工作名称' }, {        key: 'remark', title: '子工作内容' }, {        key: 'executor', title: '执行人' }, {        key: 'planStarttime', title: '预计开始工夫' }, {        key: 'planEndtime', title: '预计实现工夫' }, {        key: 'actualStarttime', title: '理论开始工夫' }, {        key: 'actualEndtime', title: '理论实现工夫' }, {        key: 'tagList', title: '标签' }, {        key: 'orderNum', title: '紧急水平' }, {        key: 'taskProgress', title: '工作进展' }      ]),      order: Object.freeze({        '紧急': 0,        '个别': 1,        '重要紧急': 2      }),      orderObj: Object.freeze({        0: '紧急',        1: '个别',        2: '重要紧急'      }),  }}methods:{  <!-- 上传之前进行文件校验 -->  beforeAvatarUpload (file) {      if (!file) {        // 没有文件        return false      } else if (!/\.(xls|xlsx)$/.test(file.name.toLowerCase())) {        // 格局依据本人需要定义        this.$message.error('上传格局不正确,请上传xls或者xlsx格局')        return false      }      this.handleExcel(file)// 解决数据      this.$refs.upload.clearFiles()    },    handleExcel (file) {      // 表格导入      const files = file // excel文件      const fileReader = new FileReader()      fileReader.onload = ev => {        try {          const data = ev.target.result          const workbook = XLSX.read(data, {            type: 'binary',            cellDates: true          })          const wsname = workbook.SheetNames[0]// 取第一张表          const tempArr = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]) // 生成json表格内容,如果某个字段列没有填,则解析进去就会没有该字段          console.log('解析进去的数据', tempArr)          this.outJson = []          let isValidPass = true          for (const item of tempArr) {            console.log('几次', item)            const obj = {}            const bool = this.validFieldRequired(item)            if (!bool) { // 如果不是true,阐明有些必填字段没有填              isValidPass = false              break            }            const isValidSuccess = this.handleoutJson(item, obj)            if (!isValidSuccess) {              isValidPass = false              break            } else {              this.outJson.push(this.successObj)// this.outJson放的就是须要返回给后盾的            }          }          if (isValidPass) {            // 如果this.outJson有数据阐明曾经全副校验胜利能够传给后盾了            batchSaveTask(this.outJson).then(res => {              this.$message.success('导入胜利')              this.init()            }).catch(e => {})          }        } catch (e) {          console.log(e)          return false        }      }      fileReader.readAsBinaryString(files)    },    // 校验必填字段的值是否存在    validFieldRequired (item) {      let boolean = true      for (const el of this.excelHeaderRequired) {        if (!Object.keys(item).includes(el)) {          this.$message.error(`${el}`)          boolean = false          break        }      }      return boolean    },    // 将解析的json转为后盾须要的字段    handleoutJson (item, obj) {      // if (item['事项名称(必填)']) {      // }      this.successObj = {}      obj['matterId'] = this.$route.query.id      obj['taskName'] = item['子工作名称(必填)'].trim()      obj['remark'] = item['子工作内容(必填)'].trim()      // 人员的须要传三个参数      obj['executorAccount'] = item['执行人(必填)'].trim()      obj['executorId'] = ''      obj['executor'] = ''      if (!DataType(item['预计开始工夫(必填)'], 'date')) {        this.$message.error('预计开始工夫格局不合乎')        return false      }      if (!DataType(item['预计实现工夫(必填)'], 'date')) {        this.$message.error('预计完结工夫格局不合乎')        return false      }      if (item['预计开始工夫(必填)'] > item['预计实现工夫(必填)']) {        this.$message.error('预计开始工夫不能晚于预计完结工夫')        return false      } else {        // 须要对工夫进行解决        obj['planStarttime'] = FormatDate(item['预计开始工夫(必填)'], 'yyyy-MM-dd hh:mm:ss')        // 须要对工夫进行解决        obj['planEndtime'] = FormatDate(item['预计实现工夫(必填)'], 'yyyy-MM-dd hh:mm:ss')      }      console.log(item['预计开始工夫(必填)'], item['预计实现工夫(必填)'])      if (item['紧急水平(必填)'] && Object.keys(this.order).includes(item['紧急水平(必填)'].trim())) {        // 须要把汉字转成key传过来        obj['orderNum'] = this.order[item['紧急水平(必填)'].trim()]      } else {        this.$message.error('工作等级不存在')        return false      }      this.successObj = { ...obj }      return true    },}

4、导出excel

  • js
 // 导出    exportMatter (type, tag) {      if (type === '1' && this.completeList.length > 0) {        // 这里深copy避免净化原数据        const arr = deepClone(this.completeList)        // 须要解决数据        const sourceData = arr.map((item, index) => {          item['index'] = index + 1          item['tagList'] = this.tagsText(item.tagList)          item['orderNum'] = this.orderObj[item.orderNum]          item['planStarttime'] = item.planStarttime ? FormatDate(item.planStarttime, 'yyyy/MM/dd hh:mm:ss') : ''          item['planEndtime'] = item.planEndtime ? FormatDate(item.planEndtime, 'yyyy/MM/dd hh:mm:ss') : ''          item['actualStarttime'] = item.actualStarttime ? FormatDate(item.actualStarttime, 'yyyy/MM/dd hh:mm:ss') : ''          item['actualEndtime'] = item.planStarttime ? FormatDate(item.actualEndtime, 'yyyy/MM/dd hh:mm:ss') : ''          Object.keys(item).forEach(key => {            item[key] = item[key] === null ? '' : item[key]          })          return item        })        exportJsonToExcel(this.exportHeader, sourceData, 'exportSubTask.xlsx')      } else {        this.$message.error('没有可导出的已实现工作')      }    },