king
2024-02-22 a7813a33fc5f60ea995dfe0f09f52243e2ccfbb2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import * as XLSX from 'sheetjs-style'
import Utils from '@/utils/utils.js'
import './index.scss'
 
class ExcelIn extends Component {
  static propTpyes = {
    btn: PropTypes.object,         // 按钮信息
    returndata: PropTypes.func,    // 获取返回数据
    triggerExcelIn: PropTypes.func // 修改上传状态
  }
 
  state = {
    excelId: Utils.getuuid()
  }
 
  exceltrigger = () => {
    const { excelId } = this.state
    let _excelInput = document.getElementById(excelId)
    
    if (_excelInput) {
      _excelInput.click()
    }
  }
  onImportExcel = file => {
    const { btn } = this.props
 
    // excel数据处理
    const { files } = file.target
    const fileReader = new FileReader()
 
    this.props.triggerExcelIn()
    fileReader.onload = event => {
      try {
        const { result } = event.target
        // 以二进制流方式读取得到整份excel表格对象
        const workbook = XLSX.read(result, { type: 'binary' })
 
        if (btn.verify.excelHandle === 'true') {
          // eslint-disable-next-line
          let func = new Function('XLSX', 'workbook', 'btn', 'callback', btn.verify.excel_func)
          func(XLSX, workbook, btn.verify, (data, error) => {
            if (!error && (!data || data.length === 0)) {
              error = '未获取到Excel数据!'
            }
            this.props.returndata(data, error)
          })
        } else {
          let btnColumns = btn.verify.columns.filter(option => option.import !== 'init')
          let columns = btnColumns.map(option => option.Column)
          let range = btn.verify.range || 0
  
          let error = null
          let sheetName = btn.verify.sheet
  
          if (sheetName === 'Sheet1' && Object.keys(workbook.Sheets).length === 1) {
            sheetName = Object.keys(workbook.Sheets)[0]
          }
  
          if (!workbook.Sheets.hasOwnProperty(sheetName)) {
            error = '工作表《' + sheetName + '》不存在!'
          } else if (range === 1) {
            let header = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {header: columns})[0]
  
            if (!header) {
              error = '工作表《' + sheetName + '》为空!'
            } else {
              btnColumns.forEach(op => {
                if (error) return
  
                let _name = typeof(header[op.Column]) === 'string' ? header[op.Column].replace(/(^\s*|\s*$)/g, '') : header[op.Column]
                let _text = op.Text ? op.Text.replace(/(^\s*|\s*$)/g, '') : op.Text
  
                if (!_name) {
                  error = `工作表《${sheetName}》表头错误,Excel中不存在(${_text})列!`
                } else if (_name !== _text) {
                  error = `工作表《${sheetName}》表头错误,Excel中(${_name})与按钮列信息(${_text})不一致!`
                }
              })
            }
          }
  
          let data = []
  
          if (!error) {
            data = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {header: columns, range: (range)})
  
            if (!data || data.length === 0) {
              error = '未获取到工作表《' + sheetName + '》数据!'
            }
          }
  
          // 最终获取到并且格式化后的 json 数据
          this.props.returndata(data, error)
        }
 
        this.setState({
          excelId: '',
        }, () => {
          this.setState({
            excelId: Utils.getuuid()
          })
        })
      } catch (e) {
        this.setState({
          excelId: ''
        }, () => {
          this.setState({
            excelId: Utils.getuuid()
          })
        })
        // 错误传递
        this.props.returndata([], '文件解析错误!')
      }
    }
 
    // 以二进制方式打开文件
    fileReader.readAsBinaryString(files[0])
  }
 
  render() {
    return (
      <span>
        {this.state.excelId ? <input className="excel-in-input" id={this.state.excelId} type='file' accept='.xlsx, .xls' onAbort={this.onImportExcel} onChange={this.onImportExcel} /> : null}
      </span>
    )
  }
}
 
export default ExcelIn