vue采用 XLSX文件上传与下载

254 阅读2分钟

vue采用 XLSX文件上传与下载

先安装xlsx

npm install xlsx

安装之后直接在该页面script标签里面导入

import * as XLSX from 'xlsx'

注意 此处不用再去其他地方再做配置了

上传

采用elment组件el-upload

 <el-upload
          accept=".xlsx, .xls"
          :file-list="fileList"
          :before-upload="beforeUploadFile"
          :on-exceed="exceedFile"
          :on-success="uploadSuccess"
          :show-file-list="false"
          multiple
          :limit="1"
          style="margin: 0px 24px 5px 24px"
        >
          <el-dialog
            title="提示"
            :visible.sync="dialogVisible"
            width="30%"
            :show-close="false"
          >
              此处设置的dialogText目的是为了记录导入表之前对应的table是否为空,而展示出不同的提醒
            <span>{{this.dialogText}}</span>
            <span slot="footer" class="dialog-footer">
              <el-button @click.stop="dialogVisible = false">取 消</el-button>
              <el-button type="primary" @click.prevent="dialogVisible = false"
                >确 定</el-button
              >
            </span>
          </el-dialog>
        <el-button
            style="left: 0px"
            @click.stop="dialogVisible = true"
            >导入Excel</el-button
          >
        </el-upload>

对应的methods

 // 1.文件上传相关
    // 1.1 beforeUploadFile文件上传之前的钩子
    beforeUploadFile (file) {//此处传入的file其实也就是el-upload组件中绑定的:file-list
      // 1.1.1 校验文件名
      var FileExt = file.name.replace(/.+./, '')
      if (['xls', 'xlsx'].indexOf(FileExt.toLowerCase()) === -1) {
        this.$message({
          type: 'warning',
          message: '请上传后缀名为xls、xlsx的附件!'
        })
        return false
      }
      // 1.1.2 校验file.size上传文件大小 以字节为单位
      this.isLt2k = file.size / 2048 < 100 ? '1' : '0'
      if (this.isLt2k === '0') {
        this.$message({
          message: '上传文件大小不能超过100k!',
          type: 'error'
        })
      } else {
        //  1.1.3 excel转化为需要的json
        var reader = new FileReader()
        reader.readAsBinaryString(file)
        reader.onload = (ev) => {
          var data = ev.target.result
          var workbook = XLSX.read(btoa(data), { type: 'base64' })
          var workbookjson = XLSX.utils.sheet_to_json(
            workbook.Sheets[workbook.SheetNames[0]],
            { range: 1, defval: '', raw: false }
          )
          //range值为0对应的是从第一行开始上传,并且第一行会解析为json对应的属性名,因为我的excel第一行是中文的,第二行设置的英文字段,所以range设置为1
          // 1.1.4 发请求以及上传后 拿到返回后的数据的处理
          this.$axios
            .post('/api/users/queryExcel', JSON.stringify(workbookjson))
            .then((res) => {
              //此处是我自己对应处理的数据逻辑 可以略过
              var resdata = res.data.data
              if (resdata) {
                var i = 1
                this.resData = resdata.map((e) => {
                  e.index = i++
                  return e
                })
                this.querydata = this.resData
                this.total = resdata.length
                this.queryPagesData = this.querydata.slice(0, 10)
                this.$message({ type: 'success', message: '文件上传成功' })
                this.dialogText = '注意:表中已有数据,再次上传会覆盖原列表!'
              } else {
                this.$message.warning(`文件导入失败`)
              }
            })
        }
      }
    },
    // 1.2 exceedFile文件超出个数时的钩子
    exceedFile (files, fileList) {
      this.$message.warning(`只能选择1个文件,当前共选择了 ${files.length} 个`)
    },
​

下载

<el-button
            type="primary"
            :loading="false"
            @click="handleExcel"
            style="left:0px"
      >导出excel</el-button>
handleExcel () {
    // this.querydata为对应的table导出来的list只有英文的属性没有对应的中文表头,所以需要在第二个参数配置表头 this.listHanders
      xlsxTran(this.querydata, this.listHander, '下载excel')
    },
​
// 导出excel封装的函数
function xlsxTran (json, fields, filename = '.xlsx') {
  // 导出xlsx
  json.forEach((item) => {
    for (let i in item) {
      if (fields.hasOwnProperty(i)) {
        item[fields[i]] = item[i]
      }
      delete item[i] // 删除原先的对象属性
    }
  })
  let sheetName = filename // excel的文件名称
  let wb = XLSX.utils.book_new() // 工作簿对象包含一SheetNames数组,以及一个表对象映射表名称到表对象。XLSX.utils.book_new实用函数创建一个新的工作簿对象。
  let ws = XLSX.utils.json_to_sheet(json, { header: Object.values(fields) }) // 将JS对象数组转换为工作表。
  wb.SheetNames.push(sheetName)
  wb.Sheets[sheetName] = ws
  const defaultCellStyle = {
    font: { name: 'Verdana', sz: 13, color: 'FF00FF88' },
    fill: { fgColor: { rgb: 'FFFFAA00' } }
  } // 设置表格的样式
  let wopts = {
    bookType: 'xlsx',
    bookSST: false,
    type: 'binary',
    cellStyles: true,
    defaultCellStyle: defaultCellStyle,
    showGridLines: false
  } // 写入的样式
  let wbout = XLSX.write(wb, wopts)
  let blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
  fs.saveAs(blob, filename + '.xlsx')
}
​
const s2ab = (s) => {
  var buf
  if (typeof ArrayBuffer !== 'undefined') {
    buf = new ArrayBuffer(s.length)
    var view = new Uint8Array(buf)
    for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
    return buf
  } else {
    buf = new Array(s.length)
    for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff
    return buf
  }
}

\