vue导入导出excel组件封装

vue导入导出excel组件

可直接使用

参考以下博客,侵删
参考的博客
##
项目安装依赖 npm install --save xlsx
在项目中创建文件夹及文件如下图:
在这里插入图片描述
excel-import.vue 源码:

<template>
  <div class="index" v-loading.fullscreen.lock="fullscreenLoading" element-loading-text="拼命加载中...">
   <el-row>
        <input  type="file" @change="importFile()" id="imFile" style="display: none" 
           accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
           />
    <el-button class="button" type="primary" @click="uploadFile()">选择文件</el-button>
    {{fileName}}
    <el-button class="button" type="primary" @click="exportexcel()">导入</el-button>
   </el-row>
    
    <!--错误信息提示-->
    <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>
    
  </div>
</template>

<script>
  var XLSX = require('xlsx')
  export default {
    name: 'excel-import',
    data () {
      return {
          fileName: "未选择",
          file: "",
        fullscreenLoading: false, // 加载中
        imFile: '', // 导入文件el
        errorDialog: false, // 错误信息弹窗
        errorMsg: '', // 错误信息内容
        excelData: ["ef"] // excel数据
      }
    },
    mounted () {
      this.imFile = document.getElementById('imFile')
    },
    methods: {
        exportexcel(){
            this.$emit("getExcelData",this.excelData)
        },
      uploadFile: function () { // 按钮导入
        this.imFile.click()
      },
      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 $t = this
        reader.onload = function (e) {
          var data = e.target.result
          if ($t.rABS) {
            $t.wb = XLSX.read(btoa(this.fixdata(data)), {  // 手动转化
              type: 'base64'
            })
          } else {
            $t.wb = XLSX.read(data, {
              type: 'binary'
            })
          }
          let json = XLSX.utils.sheet_to_json($t.wb.Sheets[$t.wb.SheetNames[0]])
          $t.dealFile($t.analyzeData(json)) // analyzeData: 解析导入数据
        }
        if (this.rABS) {
          reader.readAsArrayBuffer(f)
        } else {
          reader.readAsBinaryString(f)
        }
        var file = document.getElementById("imFile");
            this.fileName = file.value;
      },
      analyzeData: function (data) {  // 此处可以解析导入数据
        return data
      },
      dealFile: function (data) {   // 处理导入的数据
        console.log(data)
        this.imFile.value = ''
        this.fullscreenLoading = false
        if (data.length <= 0) {
          this.errorDialog = true
          this.errorMsg = '请导入正确信息'
        } else {
          this.excelData = data
          console.log(this.excelData)
        }
      },
      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>

excel-export 源码:

<template>
  <div class="index" v-loading.fullscreen.lock="fullscreenLoading" element-loading-text="拼命加载中...">
    <a id="downlink"></a>
    <el-row>
        文件名:<input v-model="fileName" style="height:30px">
        <el-button type="primary" class="button" @click="downloadFile(excelData)">导出</el-button>
    </el-row>  
  </div>
</template>

<script>
  var XLSX = require('xlsx')
  export default {
    name: 'excel-export',
    props:{
        excelData: {
            type: Array,
            required: true
        }
    },
    data () {
      return {
        fullscreenLoading: false, // 加载中
        outFile: '',  // 导出文件el
       fileName: "请输入文件名"
      }
    },
    mounted () {
      this.outFile = document.getElementById('downlink')
    },
    methods: {
      downloadFile: function (rs) { // 按钮导出
        console.log(rs)
        let data = [{}]
        for (let k in rs[0]) {
          data[0][k] = k
        }
        data = data.concat(rs)
        this.downloadExl(data, this.fileName)
      },
     
      downloadExl: function (json, downName, type) {  // 导出到excel
        let keyMap = [] // 获取键
        for (let k in json[0]) {
          keyMap.push(k)
        }
        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)
      },
      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>

##二:
在其他组件里面使用:

<template>
<div>
  <excel-import @getExcelData="ss"></excel-import>
  <excel-export :excelData="tableData"></excel-export>
  <!--展示导入信息-->
    <el-table :data="tableData" 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>
import excelImport from "../../excel/excel-import"
import excelExport from "../../excel/excel-export"
export default {
  name: "Page_1_4_Question",
  components: { excelImport, excelExport },
  data() {
    return {
      tableData: [],
    }
  },
 
  methods: {
    ss(data){
       this.tableData = data
    },
  }
};
</script>

<style scoped>
#icons {
  margin-top: 25px;
  margin-bottom: 25px;
}
.el-link {
  margin-right: 30px;
}
.handle-box {
  margin-bottom: 20px;
}
.handle-select {
  width: 120px;
}
.handle-input {
  width: 100px;
  display: inline-block;
}
.del-dialog-cnt {
  font-size: 16px;
  text-align: center;
}
.table {
  width: 100%;
  font-size: 14px;
}
.red {
  color: #ff0000;
}
.blue {
  color: rgb(70, 78, 187);
}
.green {
  color: forestgreen;
}
.mr10 {
  margin-right: 10px;
}
.wathet {
  color: rgb(43, 64, 128);
}
.block {
  margin-top: 10px;
}
.el-input {
  margin-right: 25px;
}
.el-select {
  margin-right: 25px;
}
.el-date-picker {
  width: 70px;
}
</style>

<style>
.el-table .warning-row {
  background: rgb(237, 250, 243);
}
.el-table .success-row {
  background: #fdfce5;
}
.el-button {
  margin-left: 5px;
}
.el-upload {
  width: 120px;
  height: 30px;
}
</style>

效果图:
vue导入导出excel组件封装_第1张图片
选择文件点击导入:
vue导入导出excel组件封装_第2张图片
原excel:
vue导入导出excel组件封装_第3张图片
导出:
vue导入导出excel组件封装_第4张图片
文件导出在浏览器下载地址
vue导入导出excel组件封装_第5张图片

你可能感兴趣的:(vue导入导出excel组件封装)