ps:在若依框架的导入功能上增加 预览功能。
目录
实现效果及源码
实现效果如下图:
实现思路:
- 动态表格:定义表头数组,表格遍历表头生成表格列
- 读取excel文件内容,封装表头,绑定表格数据
先上源码:
1.上传组件
<el-dialog :title="upload.title" :visible.sync="upload.open" width="800px" append-to-body>
<el-upload
name="file"
ref="upload"
:limit="1"
:file-list="fileList"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:on-change="handleChange"
:on-exceed="handleExceed"
:auto-upload="false"
:show-file-list="false"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">
仅允许导入xls、xlsx格式文件。
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<el-row class="mt"
><span class="mg">已存在数据处理</span>
<el-radio v-model="upload.updateSupport" label="1">覆盖</el-radio>
<el-radio v-model="upload.updateSupport" label="2">追加</el-radio>
</el-row>
<el-row class="mb8"><h4>预览</h4> </el-row>
<el-table :data="tableData" border>
<el-table-column
v-for="items in tableCol"
:prop="items.colProp"
:label="items.colLable"
width="180"
:key="items.colLable"
:show-overflow-tooltip="true"
>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</el-dialog>
2.动态表格
<el-table :data="tableData" border>
<el-table-column
v-for="items in tableCol"
:prop="items.colProp"
:label="items.colLable"
width="180"
:key="items.colLable"
:show-overflow-tooltip="true"
>
</el-table-column>
</el-table>
3.读取excel文件方法
//选取文件
async handleChange(file, fileList) {
this.loading = true
let _this = this
let reader = new FileReader()
reader.onload = function (e) {
let data = e.target.result
this.wb = XLSX.read(data, {
type: 'binary',
cellDates: true,
})
console.log(this.wb.Sheets[this.wb.SheetNames[0]])
/**
* wb.SheetNames[0]是获取Sheets中第一个Sheet的名字
* wb.Sheets[Sheet名]获取第一个Sheet的数据
*/
let excelJson = XLSX.utils.sheet_to_json(this.wb.Sheets[this.wb.SheetNames[0]], {
defval: null,
raw: false
})
console.log(excelJson)
//表头
for (var item in excelJson[0]) {
_this.tableCol.push({
colProp: item,
colLable: item,
})
}
excelJson.forEach((element) => {
element['日期'] = formatDate(element['日期'])
element['预计开始时间'] = formatDate(element['预计开始时间'])
element['预计结束时间'] = formatDate(element['预计结束时间'])
element['实际开始时间'] = formatDate(element['实际开始时间'])
element['实际结束时间'] = formatDate(element['实际结束时间'])
})
_this.tableData = excelJson
_this.loading = false
}
reader.readAsBinaryString(file.raw)
},
第一个问题:字段缺失
发现转成json 后,打印excelJson ,发现比表格里的少了十几个字段
打开表格,发现缺失的字段都是没有值的。
查找资料发现,如果defval
未指定,则正常跳过空值和未定义值。如果指定,所有空点和未定义点将被填充defval
在sheet_to_json函数里传入defval参数
let excelJson = XLSX.utils.sheet_to_json(this.wb.Sheets[this.wb.SheetNames[0]],{
defval:null
})
把excelJson 打印到控制台,可以看到单元格为空的字段 都为null
表头也正常显示出来了。
* 这里,其实是因为表头是从 exceljson 里读取的,所以字段不能少了。如果表头是后端传过来的,就不存在这个问题了。
第二个问题:日期格式的列显示为数字
接下来检查表格数据,发现日期字段的值不对。
查阅官网资料 ,发现 SheetJS 处理日期和时间时,默认行为是生成数字单元, 日期单元格会自动转换回具有适当数字格式的数字单元格
函数接受一个参数,该参数指示应如何处理日期。在read函数里传入cellDates
this.wb = XLSX.read(data, {
type: 'binary',
cellDates: true
})
修改完后,重新导入数据。按日期格式显示出来了。
第三个问题:显示的时间和原始数据有差异
时间和excel表格里不一致。
查看控制台打印出来的表格数据。发现时间都会相差43秒 或者 44秒
console.log(this.wb.Sheets[this.wb.SheetNames[0]])
在sheet_to_json函数,把raw设为false,读取原始值
let excelJson = XLSX.utils.sheet_to_json(this.wb.Sheets[this.wb.SheetNames[0]], {
defval: null,
raw: false
})
重新导入,这时,字段的格式和值都和excel表格里 一致了。
sheetJS官网地址:Sheet Objects | SheetJS Community Edition