js 获取xlsx内容

166 阅读2分钟
 <p-upload
      :show-upload-list="false"
      :before-upload="(file) => {return importExcel(file)}"
      accept=".xls,.xlsx"
    >
      <p-button
        type="primary"
        v-if="!edit"
      >
        批量上传
  </p-button>
</p-upload>

const excelmap = [
  {key: 'a', title: 'a'},
  {key: 'b', title: 'aa'},
  {key: 'c', title: 'aa'},
  {key: 'd', title: 'aa'},
  {key: 'e', title: 'aa'},
  {key: 'f', title: 'aa'},
  {key: 'g', title: 'aa'},
  {key: 'h', title: 'aa'},
  {key: 'i', title: 'aa'},
  {key: 'j', title: 'aa'},
  {key: 'k', title: 'aa'},
  {key: 'l', title: 'aa'},
  {key: 'm', title: 'aa'},
  {key: 'n', title: 'aa'}
]

import * as XLSX from 'xlsx'


importExcel (file) {
      console.log('file', file)
      const site = this.form.site
      if (file.name.indexOf('.xls') === -1 || file.name.indexOf('.xlsx') === -1) {
        this.$message.error('请上传xls或xlsx格式的文件')
        return false
      }
     
      this.loading = true
      // 使用xlsx插件解析excel文件
      const reader = new FileReader();
      reader.readAsBinaryString(file);
      reader.onload = (e) => {
        const data = e.target.result
        const workbook = XLSX.read(data, { type: 'binary' })
        const sheetNames = workbook.SheetNames
        console.log('sheetNames', sheetNames)
        // return
        const worksheet = workbook.Sheets[sheetNames[0]]
        const timeSheet = workbook.Sheets['特殊耗时']
        const json = XLSX.utils.sheet_to_json(worksheet) || []
        const length = json.length
        console.log('json', json)
        console.log('length', length)
        if (this.form.site === 't42' && length % 5 !== 0) {
          this.$message.error('上传数据行数异常,或存在空行数据,请检查')
          this.loading = false
          return false
        }
        if (this.form.site !== 't431' && length % 6 !== 0) {
          this.$message.error('上传数据行数异常,或存在空行数据,请检查')
          this.loading = false
          return false
        }
        // return
        this.exceltableList = this.parsingTable(worksheet)
        if (this.form.site !== 't45'&&timeSheet) {
          this.timetableList = this.parsingTable(timeSheet)
          const regex = new RegExp(/^[1-9]\d{3}-\d{2}$/)
          //将耗时表格数据合并到主表格数据中
          this.exceltableList = this.exceltableList.map((item, index) => {
            let obj = { ...item }
            let timeObj = this.timetableList[index]||{}
            for (let key in timeObj) {
              if (regex.test(key)) {
                obj[`${key}-time`] = timeObj[key]
              }
            }
            return obj
          })
        }
        console.log('exceltableList', this.exceltableList)

        // const json = XLSX.utils.sheet_to_json(worksheet)
        // console.log(json)
        // console.log(workbook, sheetNames, worksheet)
      }
      reader.onerror = (e) => {
        this.$message.error('文件解析失败')
        this.loading = false
      }
      return false
      // const formData = new FormData()
      // formData.append('file', file)
      // formData.append('site', this.form.site)
      // this.loading = true
      // rpApi.importExcel(formData).then(res => {
      //   if (res.data.success) {
      //     // this.getList()
      //     this.$message.success('上传成功!')
      //     this.$router.push(`/bprp/rpReview?site=${this.form.site}`)
      //   } else {
      //     this.$message.error(res.data.msg)
      //   }
      //   this.loading = false
      // }).catch(() => {
      // })

    },
    // 处理表格数据 拿到合并的项
    parsingTable (table) {
      console.log('table', table)
      let header = [] //表格列
      let dataSource = [] //表格数据
      let maxRowIndex = 0 //最大行数
      let mapHeader = [] //表头映射
      let keys = Object.keys(table)
      const range = XLSX.utils.decode_range(table['!ref'])
      maxRowIndex = range['e']['r'] - range['s']['r']
      for (let [i, h] of keys.entries()) {
        //提取key中的英文字母
        let col = h.replace(/[^A-Z]/g, '')
        //单元格是以A-1的形式展示的,所以排除包含!的key
        h.indexOf('!') === -1 && header.indexOf(col) === -1 && header.push(col)
        //如果!ref不存在时,  设置某一列最后一个单元格的索引为最大行数
        if (
          (!table['!ref'] || !table['!ref'].includes(':')) &&
          header.some((c) => table[`${c}${i}`])
        ) {
          maxRowIndex = i > maxRowIndex ? i : maxRowIndex
        }
      }
      // header = header.sort((a, b) => a.localeCompare(b)) //按字母顺序排序 [A, B, ..., E, F]
      //excel的行表示为 1, 2, 3, ......, 所以index起始为1
      //从1开始,maxRowIndex需要+1
      for (let index = 1; index <= maxRowIndex + 1; index++) {
        let row = [] //行
        //每行的单元格集合, 例: [A1, ..., F1]
        row = header.map((item, i) => {
          let key = `${item}${index}`
          let cell = table[key] || {}
          if (index === 1) {
            if (this.form.site === 't45') {
              mapHeader.push(
                excelmap.find((a) => cell?.w?.includes(a.title))?.key || cell.w?.trim()
              )
            } else {
              mapHeader.push(
                t35excelmap.find((a) => cell?.w?.includes(a.title))?.key || cell.w?.trim()
              )
            }
            // debugger
          }
          return {
            key,
            name: cell ? (cell.w?.trim() || '') : '',
            keyMap: mapHeader[i]
          }
        })
        dataSource.push(row)
      }
      //合并单元格
      if (table['!merges']) {
        for (let item of table['!merges']) {
          //s开始  e结束  c列  r行  (行、列的索引都是从0开始的)
          for (let r = item.s.r; r <= item.e.r; r++) {
            for (let c = item.s.c; c <= item.e.c; c++) {
              // console.log('=======', r, c)
              //查找单元格时需要r+1
              //例:单元格A1的位置是{c: 0, r:0}
              let rowIndex = r + 1
              let cell = dataSource[r].find((a) => a.key === `${header[c]}${rowIndex}`)
              if (cell) {//除了第一行都置为0
                if (c === item.s.c && r === item.s.r) {
                  cell.rowspan = item.e.r - item.s.r + 1 //纵向合并
                  cell.colspan = item.e.c - item.s.c + 1 //横向合并
                } else {
                  cell.rowspan = 0
                  cell.colspan = 0
                }
              }
            }
          }
        }
      }
      console.log(dataSource, 'dataSource')
      console.log(header, 'header')
      console.log(mapHeader, 'mapHeader')
      // console.log(XLSX.utils.sheet_to_json(table,{header:mapHeader,range:1}),'slk')
      return this.excelDatatrans(dataSource)
    },
    //excel 数据转换
    // ecxelList 为excel数据,会包含头部信息,需要从第二行开始
    excelDatatrans (tableList) {
      const arr = []
      tableList.map((item, index) => {
        if (index > 0) {
          const obj = {}
          item.map((i, ind) => {
            obj[i.keyMap] = i.name
            if (i.rowspan >= 0) {
              obj[`${i.keyMap}_rowspan`] = i.rowspan
            }
            if (i.colspan >= 0) {
              obj[`${i.keyMap}_colspan`] = i.colspan
            }
          })
          arr.push(obj)
        }
      })
      // 校验数组对象每一行除了包含_colspan和_rowspan的项,其他项的值不能全部为空
      let flag = arr.every((item, index) => {
        // console.log(item,'item')
        const keys = Object.keys(item)
        const length = keys.length
        const filterKeys = keys.filter((i) => i.indexOf('_colspan') === -1 && i.indexOf('_rowspan') === -1)
        const filterLength = filterKeys.length
        const filterArr = filterKeys.filter((i) => item[i] === '')
        const filterArrLength = filterArr.length
        if (filterLength === filterArrLength) {
          this.$message.error(`第${index + 2}行数据存在空行数据,请检查`)
          this.loading = false
          return false
        }
        return true
      })
      console.log(flag, 'flag')
      if (!flag) {
        return false
      }
      this.excelvisible = true
      this.loading = false
      return this.handleTableData(arr)
    },
    // 处理表格数据还原合并的项
    handleTableData (tableList) {
      const arr = []
      tableList.map((item, index) => {
        const obj = {}
        Object.keys(item).map((i, ind) => {
          if (i.indexOf('_rowspan') > -1 && item[i] === 0) {
            const key = i.split('_rowspan')[0]
            obj[key] = arr[index - 1][key]
          } else {
            obj[i] = item[i]
          }
        })
        arr.push(obj)
      })
      console.log(arr, 'arr')
      return arr
    },