excel上传及组件化 vue+element

247 阅读1分钟

image.png uploadExcel.vue (在src下的components文件夹中)

<template>
  <div>
    <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
    <el-button :loading="loading" type="primary" icon="el-icon-upload" @click="handleUpload">{{ btnText }}</el-button>
  </div>
</template>
<script>
import * as XLSX from 'xlsx'

export default {
  props: {
    beforeUpload: Function, // eslint-disable-line
    onSuccess: Function, // eslint-disable-line
    headerArray: {
      type: Array,
      required: true
    },
    btnText: {
      type: String,
      default: '导入'
    }
  },
  name: 'XLSX',
  data () {
    return {
      loading: false,
      excelData: {
        header: null,
        results: null
      }
    }
  },
  methods: {
    generateData ({ header, results }) {
      this.excelData.header = header
      this.excelData.results = results
      this.onSuccess && this.onSuccess(this.excelData)
    },
    handleDrop (e) {
      e.stopPropagation()
      e.preventDefault()
      if (this.loading) return
      const files = e.dataTransfer.files
      if (files.length !== 1) {
        this.$message.error('Only support uploading one file!')
        return
      }
      const rawFile = files[0] // only use files[0]

      if (!this.isExcel(rawFile)) {
        this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
        return false
      }
      this.upload(rawFile)
      e.stopPropagation()
      e.preventDefault()
    },
    handleDragover (e) {
      e.stopPropagation()
      e.preventDefault()
      e.dataTransfer.dropEffect = 'copy'
    },
    handleUpload () {
      this.$refs['excel-upload-input'].click()
    },
    handleClick (e) {
      const files = e.target.files
      const rawFile = files[0] // only use files[0]
      if (!rawFile) return
      this.upload(rawFile)
    },
    upload (rawFile) {
      this.$refs['excel-upload-input'].value = null // fix can't select the same excel
      if (!this.beforeUpload) {
        this.readerData(rawFile)
        return
      }
      const before = this.beforeUpload(rawFile)
      if (before) {
        this.readerData(rawFile)
      }
    },
    readerData (rawFile) {
      this.loading = true
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = e => {
          const data = e.target.result
          const workbook = XLSX.read(data, { type: 'array', cellDates: true })
          const firstSheetName = workbook.SheetNames[0]
          const worksheet = workbook.Sheets[firstSheetName]
          // const header = this.getHeaderRow(worksheet)  //原版获取Excel表格的第一行
          const header = this.headerArray.length > 0 ? this.headerArray : this.getHeaderRow(worksheet) // 人为的传表头
          const results = XLSX.utils.sheet_to_json(worksheet, { header: header })
          this.generateData({ header, results })
          this.loading = false
          resolve()
        }
        reader.readAsArrayBuffer(rawFile)
      })
    },
    // 人为表头 默认不删除
    getHeaderRow (sheet) {
      const headers = []
      const range = XLSX.utils.decode_range(sheet['!ref'])
      let C
      const R = range.s.r
      /* 从第一行开始 */
      for (C = range.s.c; C <= range.e.c; ++C) { /* 走范围内的每一列 */
        const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
        /* 在第一行中找到单元格 */
        let hdr = 'UNKNOWN ' + C // 替换为所需的默认值
        if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
        headers.push(hdr)
      }
      return headers
    },
    // 校验上传文件是否符合后缀
    isExcel (file) {
      return /\.(xlsx|xls|csv)$/.test(file.name)
    }
  }
}

</script>
<style scoped>
.excel-upload-input {
  display: none;
  z-index: -9999;
}

.drop {
  border: 2px dashed #bbb;
  width: 600px;
  height: 160px;
  line-height: 160px;
  margin: 0 auto;
  font-size: 24px;
  border-radius: 5px;
  text-align: center;
  color: #bbb;
  position: relative;
}
</style>

ceshi.vue (在ceshi文件中调用excel上传组件)

<template>
  <div id="app">
    <uploadexcelcomponent :header-array="headerList" :on-success="handleSuccess" :before-upload="beforeUpload" class="el-button" style="padding: 0px;margin-top: 10px" />
  </div>
</template>

<script>
import Pagination from '@/components/pagination'
import uploadexcelcomponent from '@/components/uploadExcel.vue'
export default {
  // 注册组件
  components: {
    uploadexcelcomponent
  },
  data () {
    return {
      headerList: ['name', 'age', 'addres', 'gender'] // 对应值的字段
    }
  },
  created () {

  },
  methods: {
    beforeUpload () {
      return true
    },
    // 导入表格
    async handleSuccess ({ results, header }) {
      results.shift() // 因为第一行是标题,所以删除第一行
      console.log(results)
    },
  }

}
</script>