纯前端导入excel表格数据

安装插件 js-xlsx

npm install xlsx --save

js-xlsx
使用js-xlsx时,前端可以将后端返回的json数据拼接成自己需要导出的格式,下载到电脑中,完全不依赖后端。导入只需像平时一样选择文件,然后解析excel表格数据,转换成json格式。

<template>
<div class="index" v-loading.fullscreen.lock="fullscreenLoading" element-loading-text="拼命加载中...">
  <input
        type="file"
        @change="importFile(this)"
        id="imFile"
        style="display: none"
        accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"/>
 <a id="downlink"></a>
<el-button class="button" @click="uploadFile()">导入</el-button>
 <el-button class="button" @click="downloadFile(excelData)">导出</el-button>
 <!--错误信息提示-->
 <el-dialog title="提示" v-model="errorDialog" size="tiny">
 <span>{{errorMsg}}</span>
   <span slot="footer" class="dialog-footer">
   <el-button type="primary" @click="errorDialog=false">确认</el-button>
   </span>
   </el-dialog>
   <!--展示导入信息-->
   <el-table :data="excelData" tooltip-effect="dark">
   <el-table-column label="名称" prop="name" show-overflow-tooltip></el-table-column>
   <el-table-column label="分量" prop="size" show-overflow-tooltip></el-table-column>
   <el-table-column label="口味" prop="taste" show-overflow-tooltip></el-table-column>
   <el-table-column label="单价(元)" prop="price" show-overflow-tooltip></el-table-column>
   <el-table-column label="剩余(份)" prop="remain" show-overflow-tooltip></el-table-column>
   </el-table>
 </div>
</template>
<script>
// 引入xlsx
var XLSX = require('xlsx')
export default {
  name: 'Index',
  data () {
    return {
      fullscreenLoading: false, // 加载中
      imFile: '', // 导入文件el
      outFile: '', // 导出文件el
      errorDialog: false, // 错误信息弹窗
      errorMsg: '', // 错误信息内容
      excelData: [ // 测试数据
        {
          name: '泡芙', size: '500g', taste: '酸奶', price: '30', remain: '56'
        }, {
          name: '蛋挞', size: '500g', taste: '原味', price: '34', remain: '32'
        },  {
          name: '冰淇淋', size: '500g',taste: '抹茶', price: '45', remain: '21'
        },  {
          name: '榴莲酥', size: '500g', taste: '榴莲', price: '25', remain: '26'
        }
      ]
    }
  },
  mounted () {
    this.imFile = document.getElementById('imFile')
    this.outFile = document.getElementById('downlink')
  },
  methods: {
    uploadFile: function () { // 点击导入按钮
      this.imFile.click()
    },
    downloadFile: function (rs) { // 点击导出按钮
      let data = [{}]
      for (let k in rs[0]) {
        data[0][k] = k
      }
      data = data.concat(rs)
      this.downloadExl(data, '菜单')
    },
    importFile: function () { // 导入excel
      this.fullscreenLoading = true
      let obj = this.imFile
      if (!obj.files) {
        this.fullscreenLoading = false
        return
      }
      var f = obj.files[0]
      var reader = new FileReader()
      let _this = this
      reader.onload = function (e) {
        var data = e.target.result
        if (_this.rABS) {
          _this.wb = XLSX.read(btoa(this.fixdata(data)), { // 手动转化
            type: 'base64'
          })
        } else {
          _this.wb = XLSX.read(data, {
            type: 'binary'
          })
        }
        let json = XLSX.utils.sheet_to_json(_this.wb.Sheets[_this.wb.SheetNames[0]])
        console.log(typeof json)
        _this.dealFile(_this.analyzeData(json)) // analyzeData: 解析导入数据
      }
      if (this.rABS) {
        reader.readAsArrayBuffer(f)
      } else {
        reader.readAsBinaryString(f)
      }
    },
    downloadExl: function (json, downName, type) { // 导出到excel
      let keyMap = [] // 获取键
      for (let k in json[0]) {
        keyMap.push(k)
      }
      console.info('keyMap', keyMap, json)
      let tmpdata = [] // 用来保存转换好的json
      json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
        v: v[k],
        position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
      }))).reduce((prev, next) => prev.concat(next)).forEach(function (v) {
        tmpdata[v.position] = {
          v: v.v
        }
      })
      let outputPos = Object.keys(tmpdata) // 设置区域,比如表格从A1到D10
      let tmpWB = {
        SheetNames: ['mySheet'], // 保存的表标题
        Sheets: {
          'mySheet': Object.assign({},
            tmpdata, // 内容
            {
              '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] // 设置填充区域
            })
        }
      }
      let tmpDown = new Blob([this.s2ab(XLSX.write(tmpWB,
        {bookType: (type === undefined ? 'xlsx' : type), bookSST: false, type: 'binary'} // 这里的数据是用来定义导出的格式类型
      ))], {
        type: ''
      }) // 创建二进制对象写入转换好的字节流
      var href = URL.createObjectURL(tmpDown) // 创建对象超链接
      this.outFile.download = downName + '.xlsx' // 下载名称
      this.outFile.href = href // 绑定a标签
      this.outFile.click() // 模拟点击实现下载
      setTimeout(function () { // 延时释放
        URL.revokeObjectURL(tmpDown) // 用URL.revokeObjectURL()来释放这个object URL
      }, 100)
    },
    analyzeData: function (data) { // 此处可以解析导入数据
      return data
    },
    dealFile: function (data) { // 处理导入的数据
      console.log(data[0], '处理导入的数据')
      this.imFile.value = ''
      this.fullscreenLoading = false
      if (data.length <= 0) {
        this.errorDialog = true
        this.errorMsg = '请导入正确信息'
      } else {
        this.excelData = data.map(item => {
          const arrItem = {
            name: '',
            size: '',
            taste: '',
            price: '',
            remain: ''
          }
          //将excel文件的标题名称转换,将数据格式转换成数组显示格式
          for (let key in item) {
            if (key === '名称') {
              arrItem.name = item[key]
            } else if (key === '分量') {
              arrItem.size = item[key]
            } else if (key === '口味') {
              arrItem.taste = item[key]
            } else if (key === '单价(元)') {
              arrItem.price = item[key]
            } else if (key === '剩余(份)') {
              arrItem.remain = item[key]
            }
          }
          return arrItem
        })
      }
    },
    s2ab: function (s) { // 字符串转字符流
      var buf = new ArrayBuffer(s.length)
      var view = new Uint8Array(buf)
      for (var i = 0; i !== s.length; ++i) {
        view[i] = s.charCodeAt(i) & 0xFF
      }
      return buf
    },
    getCharCol: function (n) { // 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
      let s = ''
      let m = 0
      while (n > 0) {
        m = n % 26 + 1
        s = String.fromCharCode(m + 64) + s
        n = (n - m) / 26
      }
      return s
    },
    fixdata: function (data) { // 文件流转BinaryString
      var o = ''
      var l = 0
      var w = 10240
      for (; l < data.byteLength / w; ++l) {
        o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)))
      }
      o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
      return o
    }
  }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
.el-table th>.cell {
  text-align: center
 }
 .button {
  margin-bottom: 20px
 }
</style>

实现导入功能图片:
在这里插入图片描述
在这里插入图片描述
js-xlsx的使用

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值