tips:
文件地址(按需自己改造去)
xlsx.js读取日期时,如果默认转成js日期的话,会比正常的时间少43秒,设置日期读取时,直接转成字符串即可,如下图所示,那么转换后的数据就是字符串型日期:"2022-05-09",如果需要到具体时分秒,请自行减43秒。
//转换数据
//let tempSheetData = _this.handleGetData(XLSX.utils.sheet_to_json(workSheet))
let tempSheetData = XLSX.utils.sheet_to_json(workSheet, {
defval: null //单元格为空时的默认值
, raw: false //使用w的值而不是v
, dateNF: 'yyyy-MM-dd' //日期格式
})
1 需要安装如下依赖内容,该依赖也可以导出excel
npm install -S file-saver
npm install -S xlsx
npm install -S xlsx-style
npm install -D script-loader
2 读取excel内容
说明:
- excel表必须要有工作表(sheet),且隐藏的工作表也会一起读取
- 结果会以对象形式导出
- 我用的组件是ant-vue
- 注意,你的上传组件方法,传参中一定要有file,el-element可用on-change,且注意ACTIONS要为空,否则只能读取一次
组件如下:
<template>
<div class="excel-reader">
<a-upload name="avatar" class="avatar-uploader" v-loading="loading" :show-upload-list="false"
:before-upload="handleBeforeUpload">
<a-button title="读取Excel">
<a-icon type="file-excel" /> Excel Reader
</a-button>
</a-upload>
</div>
</template>
<script>
var XLSX = require('xlsx')
import { readFile } from './excelRreadFile.js'; //读取excel文件方法
export default {
name: 'ViExcelReader',
props: {
allowed: {
type: Array,
default () {
//类型列表
return [
'xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xls', "application/vnd.ms-excel",
'csv', "text/csv"]
},
},
},
data () {
return {
loading: false
}
},
// 定义引入的组件
components: {},
//变量监听
watch: {},
// 页面初始化
created () { },
// 页面DOM加载完成
mounted () {
},
//离开页面时执行
destroyed () { },
// 页面方法
methods: {
async handleBeforeUpload (file) {
//选择文件后
let _this = this
_this.showLoading(true)
//检测文件类型
if (!_this.checkFileType(file)) {
_this.$common.showMsg({
type: 'error',
content: `抱歉,请选择excel文件`,
})
_this.showLoading(false)
return false
}
//选择excel文件后,并读取其内容(文件流)
let dataBinary = await readFile(file)
if (dataBinary != null) {
// 将整个文件以二进制形式读取
let workBook = XLSX.read(dataBinary, { type: 'binary', cellDates: true })
// 工作表数量
let workBookLen = workBook.SheetNames.length
// excel工作簿内容
let excelBook = []
//读取每个sheets表
for (let i = 0; i < workBookLen; i++) {
let workSheet = workBook.Sheets[workBook.SheetNames[i]]
excelBook.push({
sheetName: workBook.SheetNames[i],
data: XLSX.utils.sheet_to_json(workSheet, {
defval: null //单元格为空时的默认值
, raw: false //使用w的值而不是v
, dateNF: 'yyyy-MM-dd' //日期格式
})
})
}
_this.showLoading(false)
console.log({
name: file.name,
length: workBookLen,
data: excelBook
})
//导出工作表内容
_this.$emit("onChange", {
name: file.name,
length: workBookLen,
data: excelBook
})
}
},
showLoading (val) {
let _this = this
_this.loading = val
},
checkFileType (file) {
let _this = this
let flog = false
//得到上传文件的值
let fileName = file.name
//取其类型
let fileType = fileName.lastIndexOf('.')
//返回位于String对象中指定位置的子字符串并转换为小写.
let extension = fileName
.substring(fileType)
.toLowerCase()
.replace('.', '')
//判断允许上传的文件格式
if (_this.allowed.includes(extension)) {
flog = true
} else {
flog = false
}
return flog
}
},
}
</script>
<style lang="less" scoped>
.excel-reader {
display: inline-block;
.ant-upload-text {
}
}
</style>
excelRreadFile.js
export const readFile = (file) => {
return new Promise((resolve) => {
if (window.FileReader) {
let reader = new FileReader()
//将文件读取为二进制码
reader.readAsBinaryString(file)
//文件读取成功完成时,若失败,结果为null,否则为读取的结果
reader.onload = (ev) => {
resolve(ev.target.result)
}
} else {
//不支持,返回结果为null
alert('抱歉,您的浏览器,无法支持读取文件功能!')
resolve(null)
}
})
}
只有一张工作表的excel,及结果
有多张工作表的excel,及结果
自动转数据格式版本
<template>
<div class="excel-reader">
<a-upload name="avatar" class="avatar-uploader" v-loading="loading" :show-upload-list="false"
:before-upload="handleBeforeUpload">
<a-button title="读取Excel">
<a-icon type="file-excel" /> Excel Reader
</a-button>
</a-upload>
</div>
</template>
<script>
var XLSX = require('xlsx')
import { readFile } from './excelRreadFile.js'; //读取excel文件方法
export default {
name: 'ViExcelReader',
props: {
allowed: {
type: Array,
default () {
//类型列表
return [
'xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xls', "application/vnd.ms-excel",
'csv', "text/csv"]
},
},
transFiled: {
type: Object,
default () {
return {
origin: 'zh',
target: 'field'
}
}
},
header: {
type: Array,
default () {
return [{
field: 'no',//字段列
zh: '序号',//excel的标题
en: 'No',//转换的列名
},
{
field: 'student_name',//字段列
zh: '姓名',//excel的标题
en: 'student name',//转换的列名
},
{
field: 'chinese',//字段列
zh: '语文',//excel的标题
en: 'chinese',//转换的列名
},
{
field: 'math',//字段列
zh: '数学',//excel的标题
en: 'math',//转换的列名
},
{
field: 'english',//字段列
zh: '英语',//excel的标题
en: 'english',//转换的列名
},
{
field: 'exam_date',//字段列
zh: '考试日期',//excel的标题
en: 'exam date',//转换的列名
},
]
},
},
field: {
type: Array,
default () {
return []
},
},
},
data () {
return {
loading: false
}
},
// 定义引入的组件
components: {},
//变量监听
watch: {},
// 页面初始化
created () { },
// 页面DOM加载完成
mounted () {
},
//离开页面时执行
destroyed () { },
// 页面方法
methods: {
async handleBeforeUpload (file) {
//选择文件后
let _this = this
_this.showLoading(true)
//检测文件类型
if (!_this.checkFileType(file)) {
_this.$common.showMsg({
type: 'error',
content: `抱歉,请选择excel文件`,
})
_this.showLoading(false)
return false
}
//选择excel文件后,并读取其内容(文件流)
let dataBinary = await readFile(file)
if (dataBinary != null) {
// 将整个文件以二进制形式读取
let workBook = XLSX.read(dataBinary, { type: 'binary', cellDates: true, cellText: false })
// 工作表数量
let workBookLen = workBook.SheetNames.length
// excel工作簿内容
let excelBook = []
//读取每个sheets表
for (let i = 0; i < workBookLen; i++) {
let workSheet = workBook.Sheets[workBook.SheetNames[i]]
//转换数据
let tempSheetData = []
if (Object.keys(_this.transFiled).length == 0 || _this.header.length == 0) {
//默认导出,不转换
tempSheetData = XLSX.utils.sheet_to_json(workSheet, {
defval: null //单元格为空时的默认值
, raw: false //使用w的值而不是v
, dateNF: 'yyyy-MM-dd' //日期格式
})
} else {
//根据实际情况导出
tempSheetData = _this.handleGetData(XLSX.utils.sheet_to_json(workSheet, {
defval: null //单元格为空时的默认值
, raw: false //使用w的值而不是v
, dateNF: 'yyyy-MM-dd' //日期格式
}))
}
excelBook.push({
sheetName: workBook.SheetNames[i],
data: tempSheetData
})
}
_this.showLoading(false)
console.log({
name: file.name,
length: workBookLen,
data: excelBook
})
//导出工作表内容
_this.$emit("onChange", {
name: file.name,
length: workBookLen,
data: excelBook
})
}
},
handleGetData (data) {
//转换数据
let _this = this
if (data.length == 0) {
return []
}
let resultArr = []
data.filter(item => {
let row = {}
for (let i in item) {
for (let m = 0; m < _this.header.length; m++) {
let mItem = _this.header[m]
if (mItem[_this.transFiled.origin] == i) {
row[mItem[_this.transFiled.target]] = item[i]
break
}
}
}
resultArr.push(row)
})
return resultArr
},
showLoading (val) {
let _this = this
_this.loading = val
},
checkFileType (file) {
let _this = this
let flog = false
//得到上传文件的值
let fileName = file.name
//取其类型
let fileType = fileName.lastIndexOf('.')
//返回位于String对象中指定位置的子字符串并转换为小写.
let extension = fileName
.substring(fileType)
.toLowerCase()
.replace('.', '')
//判断允许上传的文件格式
if (_this.allowed.includes(extension)) {
flog = true
} else {
flog = false
}
return flog
}
},
}
</script>
<style lang="less" scoped>
.excel-reader {
display: inline-block;
.ant-upload-text {
}
}
</style>
结论:
千万要注意,隐藏的sheet表也会被读取出来的,且转换后的数据,会以中文为标题出现,有需要的朋友可以转换下对象,否则可能会有问题。