vue+element+xlsx解析上传表格

重要代码已标红

用到的插件组件

npm i element

npm i xlsx

vue3 引入写法有差异 具体自行百度

html:

 <div class="crenter">

        <div>

          <el-card class="box-card">

            <el-upload ref="upload" accept=".xls,.xlsx"  action="#"  :auto-upload="false"

         :multiple="false" :file-list="fileList"  :before-upload="beforeUpload" 

          :http-request="uploadHttpRequest"  :on-remove="fileRemove"    :on-change="fileChange"

           drag   >

              <img class="upImg" src="../../style/img/up.png" alt="" />

              <el-button class="buttonUp" type="primary">上传excel</el-button>

              <div class="el-upload__text">或者拖放一个文件</div>

            </el-upload>

          </el-card>

          <div class="el-upload__tip">只能上传excel文件,且不超过500kb</div>

        </div>

        <div>

          <el-button style="width: 450px; margin: 20px auto; padding: 15px" type="primary"         @click="submitUpload">确认上传</el-button>

          </div>

      </div>

js:

引入组件

import XLSX from '../../../node_modules/xlsx'

export default {

  data() {

    return {

      options: [

        {

          value: 1,

          label: '整包',

        },

        {

          value: 2,

          label: '散包',

        },

        {

          value: 3,

          label: '单一来源',

        },

      ],

      is_type: '',

      action: process.env.VUE_APP_BASE_API + '/business/BizMaterialSum/importData',

      // 用户导入参数

      fileList: [],

      // 读取

      defaultIndex: 0, // 默认显示第一个工作表

      wb: null, // 工作表对象

      formData: {},

    }

  },

  created() {},

  methods: {

    beforeUpload(file) {

      //文件类型

      const isType = file.type === 'application/vnd.ms-excel'

      const isTypeComputer = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'

      const fileType = isType || isTypeComputer

      if (!fileType) {

        this.$message.error('上传文件只能是xls/xlsx格式!')

      }

      // 文件大小限制为10M

      const fileLimit = file.size / 1024 / 1024 < 10

      if (!fileLimit) {

        this.$message.error('上传文件大小不超过10M!')

      }

      return fileType && fileLimit

    },

    // 自定义上传方法,param是默认参数,可以取得file文件信息,具体信息如下图

    uploadHttpRequest(param) {

      // const formData = new FormData() //FormData对象,添加参数只能通过append('key', value)的形式添加

      // formData.append('file', param.file) //添加文件对象

      // formData.append('uploadType', this.is_type) //接口要传的参数

      // // 调用接口api

      // importData(formData).then((data) => {

      //   if (data.code == 200) {

      //     this.msgSuccess('成功')

      //     param.onSuccess() // 上传成功的文件显示绿色的对勾

      //     this.fileList = []

      //     this.is_type = ''

      //   } else {

      //     this.msgError(data.msg)

      //   }

      // })

    },

    // 点击上传:手动上传到服务器,此时会触发组件的http-request

    submitUpload() {

      if (this.is_type && this.fileList) {

        // this.$refs.upload.submit()

        // console.log(this.formData)

        importData(this.formData).then((data) => {

          if (data.code == 200) {

            this.msgSuccess('成功')

            this.fileList = []//清空上传的文件展示列表

            this.is_type = ''

          this.$refs.upload.clearFiles()//清空已上传的文件列表(该方法不支持在 before-upload 中调用)

          } else {

            this.msgError(data.msg)

          }

        })

      } else if (this.is_type && this.fileList.length == 0) {

        this.msgError('请选择上传文件')

      } else if (!this.is_type && this.fileList.length != 0) {

        this.msgError('请选择导入模式')

      } else if (!this.is_type && this.fileList.length == 0) {

        this.msgError('请选择导入模式和上传文件')

      }

    },

    // 移除选择的文件

    fileRemove(file, fileList) {

      if (fileList.length < 1) {

        this.uploadDisabled = true //未选择文件则禁用上传按钮

      }

    },

    // 取消

    closeDialog() {

      this.$refs.upload.clearFiles() //清除上传文件对象

      this.fileList = [] //清空选择的文件列表

      this.$emit('close', false)

    },

    // 文件发生改变

    fileChange(file, fileList) {

      // if (fileList.length > 0) {

      //   this.fileList = [fileList[fileList.length - 1]] // 展示最后一次选择的文件

      // }

      // console.log(file)

      this.formData = {

        Name: file.name,

        IsType: this.is_type,

      }

      let files = { 0: file.raw }

      this.readExcel(files)

    },

    // 导入用XLSX读取文档

    readExcel(files) {

      var that = this

      // 如果没有⽂件名

      if (files.length <= 0) {

        return false

      } else if (!/\.(xls|xlsx)$/.test(files[0].name.toLowerCase())) {

        this.$Message.error('上传格式不正确,请上传xls或者xlsx格式')

        return false

      }

      const fileReader = new FileReader()

      fileReader.onload = (ev) => {

        try {

          const data = ev.target.result

          const workbook = XLSX.read(data, {

            type: 'binary',

          })

          // 取第⼀张表

          const wsname = workbook.SheetNames[0] //

          // ⽣成

          // 表格内容

          const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname])

          console.log(ws, 'ws是表格⾥的数据,且是json格式')

          let list = ws.map((item) => {

            return {

              Coding: (item.物料编码)+'',

              Name: (item.物料名称)+'',

              Specification: (item.规格型号)+'',

              Units: (item.计量单位)+'',

              AllName: (item.全名)+'',

              ApplyNumber: (item.申请数量),

              AdjustNumber: (item.调剂后数量),

              Remark: (item.备注)+'',

            }

          })

          this.formData.BizMaterialSon = list

          // 重写数据

          this.$refs.upload.value = ''

        } catch (e) {

          return false

        }

      }

      fileReader.readAsBinaryString(files[0])

    },

  },

}

</script>

css:掺杂了一些其他的代码

<style scoped lang="scss">

.title {

  text-align: center;

  font-size: 70px;

  font-weight: 600;

}

.crenter {

  width: 450px;

  margin: 20px auto;

}

.select {

  position: relative;

}

.selectright {

  width: 450px;

  margin: 20px auto;

}

.selectLeft {

  width: 410px;

  position: absolute;

  left: 54%;

  top: 0;

}

.upload-demo {

  width: 100%;

}

.upImg {

  width: 150px;

  // height: 100px;

  margin: 10px auto;

}

</style>

<style scoped>

.upload-demo >>> .el-upload-dragger {

  border: none;

  height: 250px !important;

  width: 100%;

}

.box-card >>> .el-upload-dragger {

  border: none;

  height: 208px !important;

  width: 100%;

}

.el-card.is-always-shadow {

  -webkit-box-shadow: 0 2px 12px 0 #f0f0f0;

  box-shadow: 0px -6px 20px 0 #f0f0f0;

  border: none;

}

.box-card >>> .el-upload {

  display: block !important;

}

.buttonUp {

  display: block;

  width: 140px;

  padding: 15px;

  border-radius: 5px;

  margin: 0px auto;

  margin-bottom: 10px;

}

.el-upload__tip {

  text-align: center;

  color: #a7a3a2;

  padding: 20px;

  box-shadow: 0px 4px 14px 0px #f0f0f0;

  margin-top: 0px;

}

</style>

整合:一整个页面里的代码,可以复制过去自己修改

<template>

  <div class="app-container home">

    <div style="padding-top: 30px">

      <div class="title">上传excel导入物料采购单</div>

      <div class="select">

        <div class="selectright">

          <el-form>

            <el-form-item label="导入模式">

              <el-select v-model="is_type" placeholder="请输入导入模式">

                <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>

              </el-select>

            </el-form-item>

          </el-form>

        </div>

        <div class="selectLeft">

          <span style="color: red">*</span>

          打包为整包、散包、单一来源;为整包时,填写价格时不可填写0,且每个都必填;为散包时,价格可填写为0。

        </div>

      </div>

      <div class="crenter">

        <div>

          <el-card class="box-card">

            <el-upload

              ref="upload"

              accept=".xls,.xlsx"

              action="#"

              :auto-upload="false"

              :multiple="false"

              :file-list="fileList"

              :before-upload="beforeUpload"

              :http-request="uploadHttpRequest"

              :on-remove="fileRemove"

              :on-change="fileChange"

              drag

            >

              <img class="upImg" src="../../style/img/up.png" alt="" />

              <el-button class="buttonUp" type="primary">上传excel</el-button>

              <div class="el-upload__text">或者拖放一个文件</div>

            </el-upload>

          </el-card>

          <div class="el-upload__tip">只能上传excel文件,且不超过500kb</div>

        </div>

        <div><el-button style="width: 450px; margin: 20px auto; padding: 15px" type="primary" @click="submitUpload">确认上传</el-button></div>

      </div>

    </div>

  </div>

</template>

<script>

import request from '@/utils/request'

import { getToken } from '@/utils/auth'

import { importData } from '@/api/purchase/purchase'

import XLSX from '../../../node_modules/xlsx'

export default {

  data() {

    return {

      options: [

        {

          value: 1,

          label: '整包',

        },

        {

          value: 2,

          label: '散包',

        },

        {

          value: 3,

          label: '单一来源',

        },

      ],

      is_type: '',

      action: process.env.VUE_APP_BASE_API + '/business/BizMaterialSum/importData',

      // 用户导入参数

      fileList: [],

      // 读取

      defaultIndex: 0, // 默认显示第一个工作表

      wb: null, // 工作表对象

      formData: {},

    }

  },

  created() {},

  methods: {

    beforeUpload(file) {

      //文件类型

      const isType = file.type === 'application/vnd.ms-excel'

      const isTypeComputer = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'

      const fileType = isType || isTypeComputer

      if (!fileType) {

        this.$message.error('上传文件只能是xls/xlsx格式!')

      }

      // 文件大小限制为10M

      const fileLimit = file.size / 1024 / 1024 < 10

      if (!fileLimit) {

        this.$message.error('上传文件大小不超过10M!')

      }

      return fileType && fileLimit

    },

    // 自定义上传方法,param是默认参数,可以取得file文件信息,具体信息如下图

    uploadHttpRequest(param) {

      // const formData = new FormData() //FormData对象,添加参数只能通过append('key', value)的形式添加

      // formData.append('file', param.file) //添加文件对象

      // formData.append('uploadType', this.is_type) //接口要传的参数

      // // 调用接口api

      // importData(formData).then((data) => {

      //   if (data.code == 200) {

      //     this.msgSuccess('成功')

      //     param.onSuccess() // 上传成功的文件显示绿色的对勾

      //     this.fileList = []

      //     this.is_type = ''

      //   } else {

      //     this.msgError(data.msg)

      //   }

      // })

    },

    // 点击上传:手动上传到服务器,此时会触发组件的http-request

    submitUpload() {

      if (this.is_type && this.fileList) {

        // this.$refs.upload.submit()

        // console.log(this.formData)

        importData(this.formData).then((data) => {

          if (data.code == 200) {

            this.msgSuccess('成功')

            this.fileList = []//清空上传的文件展示列表

            this.is_type = ''

          this.$refs.upload.clearFiles()//清空已上传的文件列表(该方法不支持在 before-upload 中调用)

          } else {

            this.msgError(data.msg)

          }

        })

      } else if (this.is_type && this.fileList.length == 0) {

        this.msgError('请选择上传文件')

      } else if (!this.is_type && this.fileList.length != 0) {

        this.msgError('请选择导入模式')

      } else if (!this.is_type && this.fileList.length == 0) {

        this.msgError('请选择导入模式和上传文件')

      }

    },

    // 移除选择的文件

    fileRemove(file, fileList) {

      if (fileList.length < 1) {

        this.uploadDisabled = true //未选择文件则禁用上传按钮

      }

    },

    // 取消

    closeDialog() {

      this.$refs.upload.clearFiles() //清除上传文件对象

      this.fileList = [] //清空选择的文件列表

      this.$emit('close', false)

    },

    // 文件发生改变

    fileChange(file, fileList) {

      // if (fileList.length > 0) {

      //   this.fileList = [fileList[fileList.length - 1]] // 展示最后一次选择的文件

      // }

      // console.log(file)

      this.formData = {

        Name: file.name,

        IsType: this.is_type,

      }

      let files = { 0: file.raw }

      this.readExcel(files)

    },

    // 导入用XLSX读取文档

    readExcel(files) {

      var that = this

      // 如果没有⽂件名

      if (files.length <= 0) {

        return false

      } else if (!/\.(xls|xlsx)$/.test(files[0].name.toLowerCase())) {

        this.$Message.error('上传格式不正确,请上传xls或者xlsx格式')

        return false

      }

      const fileReader = new FileReader()

      fileReader.onload = (ev) => {

        try {

          const data = ev.target.result

          const workbook = XLSX.read(data, {

            type: 'binary',

          })

          // 取第⼀张表

          const wsname = workbook.SheetNames[0] //

          // ⽣成

          // 表格内容

          const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname])

          console.log(ws, 'ws是表格⾥的数据,且是json格式')

          let list = ws.map((item) => {

            return {

              Coding: (item.物料编码)+'',

              Name: (item.物料名称)+'',

              Specification: (item.规格型号)+'',

              Units: (item.计量单位)+'',

              AllName: (item.全名)+'',

              ApplyNumber: (item.申请数量),

              AdjustNumber: (item.调剂后数量),

              Remark: (item.备注)+'',

            }

          })

          this.formData.BizMaterialSon = list

          // 重写数据

          this.$refs.upload.value = ''

        } catch (e) {

          return false

        }

      }

      fileReader.readAsBinaryString(files[0])

    },

  },

}

</script>

<style scoped lang="scss">

.title {

  text-align: center;

  font-size: 70px;

  font-weight: 600;

}

.crenter {

  width: 450px;

  margin: 20px auto;

}

.select {

  position: relative;

}

.selectright {

  width: 450px;

  margin: 20px auto;

}

.selectLeft {

  width: 410px;

  position: absolute;

  left: 54%;

  top: 0;

}

.upload-demo {

  width: 100%;

}

.upImg {

  width: 150px;

  // height: 100px;

  margin: 10px auto;

}

</style>

<style scoped>

.upload-demo >>> .el-upload-dragger {

  border: none;

  height: 250px !important;

  width: 100%;

}

.box-card >>> .el-upload-dragger {

  border: none;

  height: 208px !important;

  width: 100%;

}

.el-card.is-always-shadow {

  -webkit-box-shadow: 0 2px 12px 0 #f0f0f0;

  box-shadow: 0px -6px 20px 0 #f0f0f0;

  border: none;

}

.box-card >>> .el-upload {

  display: block !important;

}

.buttonUp {

  display: block;

  width: 140px;

  padding: 15px;

  border-radius: 5px;

  margin: 0px auto;

  margin-bottom: 10px;

}

.el-upload__tip {

  text-align: center;

  color: #a7a3a2;

  padding: 20px;

  box-shadow: 0px 4px 14px 0px #f0f0f0;

  margin-top: 0px;

}

</style>

页面图片:

猜你喜欢

转载自blog.csdn.net/weixin_51426266/article/details/125312184