vue采用 XLSX文件上传与下载
先安装xlsx
npm install xlsx
安装之后直接在该页面script标签里面导入
import * as XLSX from 'xlsx'
注意 此处不用再去其他地方再做配置了
上传
采用elment组件el-upload
<el-upload
accept=".xlsx, .xls"
:file-list="fileList"
:before-upload="beforeUploadFile"
:on-exceed="exceedFile"
:on-success="uploadSuccess"
:show-file-list="false"
multiple
:limit="1"
style="margin: 0px 24px 5px 24px"
>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:show-close="false"
>
此处设置的dialogText目的是为了记录导入表之前对应的table是否为空,而展示出不同的提醒
<span>{{this.dialogText}}</span>
<span slot="footer" class="dialog-footer">
<el-button @click.stop="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click.prevent="dialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
<el-button
style="left: 0px"
@click.stop="dialogVisible = true"
>导入Excel</el-button
>
</el-upload>
对应的methods
// 1.文件上传相关
// 1.1 beforeUploadFile文件上传之前的钩子
beforeUploadFile (file) {//此处传入的file其实也就是el-upload组件中绑定的:file-list
// 1.1.1 校验文件名
var FileExt = file.name.replace(/.+./, '')
if (['xls', 'xlsx'].indexOf(FileExt.toLowerCase()) === -1) {
this.$message({
type: 'warning',
message: '请上传后缀名为xls、xlsx的附件!'
})
return false
}
// 1.1.2 校验file.size上传文件大小 以字节为单位
this.isLt2k = file.size / 2048 < 100 ? '1' : '0'
if (this.isLt2k === '0') {
this.$message({
message: '上传文件大小不能超过100k!',
type: 'error'
})
} else {
// 1.1.3 excel转化为需要的json
var reader = new FileReader()
reader.readAsBinaryString(file)
reader.onload = (ev) => {
var data = ev.target.result
var workbook = XLSX.read(btoa(data), { type: 'base64' })
var workbookjson = XLSX.utils.sheet_to_json(
workbook.Sheets[workbook.SheetNames[0]],
{ range: 1, defval: '', raw: false }
)
//range值为0对应的是从第一行开始上传,并且第一行会解析为json对应的属性名,因为我的excel第一行是中文的,第二行设置的英文字段,所以range设置为1
// 1.1.4 发请求以及上传后 拿到返回后的数据的处理
this.$axios
.post('/api/users/queryExcel', JSON.stringify(workbookjson))
.then((res) => {
//此处是我自己对应处理的数据逻辑 可以略过
var resdata = res.data.data
if (resdata) {
var i = 1
this.resData = resdata.map((e) => {
e.index = i++
return e
})
this.querydata = this.resData
this.total = resdata.length
this.queryPagesData = this.querydata.slice(0, 10)
this.$message({ type: 'success', message: '文件上传成功' })
this.dialogText = '注意:表中已有数据,再次上传会覆盖原列表!'
} else {
this.$message.warning(`文件导入失败`)
}
})
}
}
},
// 1.2 exceedFile文件超出个数时的钩子
exceedFile (files, fileList) {
this.$message.warning(`只能选择1个文件,当前共选择了 ${files.length} 个`)
},
下载
<el-button
type="primary"
:loading="false"
@click="handleExcel"
style="left:0px"
>导出excel</el-button>
handleExcel () {
// this.querydata为对应的table导出来的list只有英文的属性没有对应的中文表头,所以需要在第二个参数配置表头 this.listHanders
xlsxTran(this.querydata, this.listHander, '下载excel')
},
// 导出excel封装的函数
function xlsxTran (json, fields, filename = '.xlsx') {
// 导出xlsx
json.forEach((item) => {
for (let i in item) {
if (fields.hasOwnProperty(i)) {
item[fields[i]] = item[i]
}
delete item[i] // 删除原先的对象属性
}
})
let sheetName = filename // excel的文件名称
let wb = XLSX.utils.book_new() // 工作簿对象包含一SheetNames数组,以及一个表对象映射表名称到表对象。XLSX.utils.book_new实用函数创建一个新的工作簿对象。
let ws = XLSX.utils.json_to_sheet(json, { header: Object.values(fields) }) // 将JS对象数组转换为工作表。
wb.SheetNames.push(sheetName)
wb.Sheets[sheetName] = ws
const defaultCellStyle = {
font: { name: 'Verdana', sz: 13, color: 'FF00FF88' },
fill: { fgColor: { rgb: 'FFFFAA00' } }
} // 设置表格的样式
let wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary',
cellStyles: true,
defaultCellStyle: defaultCellStyle,
showGridLines: false
} // 写入的样式
let wbout = XLSX.write(wb, wopts)
let blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
fs.saveAs(blob, filename + '.xlsx')
}
const s2ab = (s) => {
var buf
if (typeof ArrayBuffer !== 'undefined') {
buf = new ArrayBuffer(s.length)
var view = new Uint8Array(buf)
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
return buf
} else {
buf = new Array(s.length)
for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff
return buf
}
}
\