前言
基于xlsx插件,可以控制读取Excel表中的特定Sheet中的数据和从第几个单元格开始获取数据。
因为xlsx插件默认是从A1单元格开始读取的,这样就不适合某些业务场景,如在表格中包含了一些表格说明等,官方好像也没有API可以进行控制(有可能是我没发现,有发现的朋友可以告知一下),于是自己通过返回的数据进行改造,从而达到目的。
获取读取的数据
readerData(rawFile) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = e => {
const data = e.target.result
const workbook = XLSX.read(data, { type: 'array' })
// 这里是控制获取第几个Sheet表的数据
const firstSheetName = workbook.SheetNames[this.sheet]
// 获取还未处理的表格的数据
let worksheet = workbook.Sheets[firstSheetName]
// 这里对返回的表格数据进行处理,设置开始读取的单元格
worksheet = this.handleStartTd(worksheet, this.cell)
// 获取数据的表头
const header = this.getHeaderRow(worksheet)
// 获取最终数据
const results = XLSX.utils.sheet_to_json(worksheet)
resolve()
}
reader.readAsArrayBuffer(rawFile)
})
}
更改开始读取的单元格位置
handleStartTd(worksheet, start) {
let old = worksheet['!ref']
old = old.split(':')
worksheet['!ref'] = start + ':' + old[1]
return worksheet
}
完整组件
<template>
<div style="display: inline;">
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
<button class="d_btn font14 text_white bg_blue" @click="handleUpload">
{{text}}
</button>
</div>
</template>
<script>
import XLSX from 'xlsx'
export default {
props: {
text: {
type: String,
default: '导入'
},
sheet: { // Excel中的第几个表
type: Number,
default: 0
},
cell: { // 从哪个单元格开始获取数据
type: String,
default: 'A1'
},
beforeUpload: Function, // eslint-disable-line
onSuccess: Function// eslint-disable-line
},
data() {
return {
loading: false,
excelData: {
header: null,
results: null
}
}
},
methods: {
generateData(header, results) {
this.excelData.header = header
this.excelData.results = results
this.onSuccess && this.onSuccess(this.excelData)
},
handleUpload() {
this.$refs['excel-upload-input'].click()
},
handleClick(e) {
const files = e.target.files
const rawFile = files[0]
if (!rawFile) return
this.upload(rawFile)
},
upload(rawFile) {
this.$refs['excel-upload-input'].value = null
if (!this.beforeUpload) {
this.readerData(rawFile)
return
}
const before = this.beforeUpload(rawFile)
if (before) {
this.readerData(rawFile)
}
},
readerData(rawFile) {
this.loading = true
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = e => {
const data = e.target.result
const workbook = XLSX.read(data, { type: 'array' })
const firstSheetName = workbook.SheetNames[this.sheet]
let worksheet = workbook.Sheets[firstSheetName]
worksheet = this.handleStartTd(worksheet, this.cell)
const header = this.getHeaderRow(worksheet)
const results = XLSX.utils.sheet_to_json(worksheet)
this.generateData(header, results)
this.loading = false
resolve()
}
reader.readAsArrayBuffer(rawFile)
})
},
handleStartTd(worksheet, start) {
let old = worksheet['!ref']
old = old.split(':')
worksheet['!ref'] = start + ':' + old[1]
return worksheet
},
getHeaderRow(sheet) {
const headers = []
const range = XLSX.utils.decode_range(sheet['!ref'])
let C
const R = range.s.r
/* start in the first row */
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
/* find the cell in the first row */
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
headers.push(hdr)
}
return headers
},
}
}
</script>
<style scoped>
.excel-upload-input{
display: none;
z-index: -9999;
}
.d_btn {
height: 40px;
padding: 0 21px;
border: 0;
outline: 0;
cursor: pointer;
border-radius: 4px;
}
</style>
使用
<upload-excel :cell="'A8'" :on-success="execlSuccess"></upload-excel>