本文主要内容:用elementui的Upload 组件上传Excel文件,上传后的列表采用xlsx插件实现点击预览表格内容效果。
在项目中可能会有这样的需求,有很多种方法实现。但是不想要跳转外部地址,所以用了xlsx插件来解析表格,并展示表格内容。
1.安装或CDN引用xlsx插件
xlsx插件,通常指的是SheetJS/js-xlsx,是一个功能强大的JavaScript库,它允许开发者在浏览器或Node.js环境中读取、创建、编辑和导出Excel文件(包括.xls、.xlsx、.csv、.ods等多种格式)。这个库是由纯JavaScript编写的,不依赖于任何外部库,非常适合在前端应用中处理Excel数据,也适用于服务器端处理。
对于Vue开发者来说,vue-xlsx是一个专门为Vue框架设计的轻量级封装库,提供了Vue组件和更加Vue友好的API,它使得在Vue应用中处理Excel文件变得更加简单和直接。在这里我使用的是xlsx。
(1)在项目中安装xlsx
npm install vue-xlsx //安装的是vue-xlsx库,基于SheetJS/js-xlsx的Vue封装库,专门为Vue框架设计
yarn add vue-xlsx
npm install xlsx //安装的是SheetJS/js-xlsx库,纯JavaScript编写的库
yarn add xlsx
(2)CDN引入xlsx
直接添加script标签引入
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
动态添加script标签引入
mounted() {
// 引入xlsx插件
const script = document.createElement("script");
script.src = "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js";//使用.full.min.js引入成功,其他不行
script.onload = () =>{
console.log("xlsx脚本加载完成");
}
document.body.appendChild(script);
this.assignmentQueryForm()
},
这里的资源是从免费的开源CDN服务网站上copy下来的,cdnjs网站地址:https://cdnjs.com/libraries/xlsx(需要不同版本的请前往)或开发文档概述 | SheetJS 中文网 (nodejs.cn)
(3)CDN引入xlsx没有起作用的解决方法
我这里引入了xlsx的CDN链接,但是运用xlsx还是报错。经过解决,发现使用xlsx.full.min.js这个后缀的文件可以,也不知道为什么。SheetJS开发文档说xlsx.full.min.js是完整的独立脚本。
2.导入xlsx
(1)安装的需要在Vue组件中导入vue-xlsx
import { XlSX } from 'vue-xlsx';
import { XlSX } from 'xlsx';
(2)CDN引入的xlsx直接使用
3.利用vue组件上传Excel文件
ref: 为上传组件设置了一个引用名。
action: 上传地址的URL,但这里设置为#
,表明实际的上传逻辑将不会通过action
属性指定的URL进行,而是通过:http-request
属性自定义。
:on-preview: 点击已上传的文件链接时的回调。
:on-remove: 文件列表移除文件时的回调。
:file-list: 已经上传的文件列表,绑定到fileList
数据属性。
:auto-upload: 是否在选取文件后立即进行上传,这里设置为false
,表示需要手动触发上传。
:http-request: 覆盖默认的上传行为,可以自定义上传的实现。
:on-change: 文件状态改变时的回调。
multiple: 是否支持多文件上传。
因为只做了Excel文件解析,所以可以在upload组件中设置accept属性,限制只上传表格文件。
accept=".xls, .xlsx"
代码如下:
<el-dialog title="批量导入" :visible.sync="dialogVisible1" width="30%">
<el-form :model="importForm1" ref="removeControl" :rules="rules" label-position="right" label-width="auto"
style="width: 50%">
<el-form-item label="附件:" ref="myfile" style="background-color: #ffffff;">
<div style="display: flex">
<el-upload ref="upload" action="#" :on-preview="handleView" :on-remove="handleRemove" :file-list="fileList"
:auto-upload="false" :http-request="uploadFile" :on-change="onChange" multiple>
<el-button slot="trigger" size="small" type="primary" icon="el-icon-upload2"
style="padding: 10px 20px">上传文件</el-button>
</el-upload>
</div>
</el-form-item>
<span @click="down()" style="cursor: pointer; color: blue">下载模板</span>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible1 = false">取 消</el-button>
<el-button type="primary" @click="goUpload()">确 定</el-button>
</span>
</el-dialog>
4.解析并预览Excel文件
(1)文件上传成功后,点击解析文件
这里会用到upload组件的on-preview(点击已上传的文件链接时的回调)。
(2)解析Excel文件步骤
- 使用
new FileReader()
创建一个文件存储,用于异步读取用户的文件内容。 -
当文件读取操作成功完成时,触发
onload
事件。通过e.target.result
获取到文件的内容。 -
使用
XLSX.read(data, { type: 'array'
})
将array格式的数据解析为Excel工作簿对象。 -
通过
tablelook.SheetNames[0]
获取第一个工作表的名称,并通过tablelook.Sheets[firstSheetName]
获取该工作表的数据。 -
使用
XLSX.utils.sheet_to_json(tablesheet, { header: 1 })
将工作表的数据转换为JSON格式,其中{ header: 1 }
表示第一行作为表头。 -
使用FileReader接口的
readAsArrayBuffer()
方法用于开始读取指定Blob或File的内容。
(3)处理JSON数据(可根据自己需求)
- 使用
jsonData.shift()
移除并保存表头(即第一行数据) - 通过
filter
方法过滤掉包含空值(null
、undefined
、空字符串''
)的行 - 使用
map
方法将数据中的每一行数据转换为一个对象,对象的键是表头,值是对应的数据。
我这里处理成了elementui的table格式数据,点击文件列表就可以直接展示表格解析的内容。
代码如下:
handleView(file) {
const reader = new FileReader();
reader.onload = (e) => {
const data = e.target.result;
const tablelook = XLSX.read(data, { type: 'array' });
const firstSheetName = tablelook.SheetNames[0];
const tablesheet = tablelook.Sheets[firstSheetName];
const jsonData = XLSX.utils.sheet_to_json(tablesheet, { header: 1 });
this.whiteListHeaders = jsonData.shift();
// 过滤空数据
this.whiteListTable = jsonData.filter(row => {
return row.some(item => item !== null && item !== undefined && item !== '');
});
// 表格数据处理
this.tableData2 = this.whiteListTable.map(row => {
const obj = {};
this.whiteListHeaders.forEach((header, cellIndex) => {
obj[header] = row[cellIndex];
});
return obj;
});
console.log("表格头", this.whiteListHeaders);
console.log("表格数据", this.whiteListTable);
console.log("this.tableData2", this.tableData2);
}
reader.onerror = (error) => {
console.error('读取文件错误:', error);
};
reader.readAsArrayBuffer(file.raw)
this.dialogVisible2 = true;
},
预览文件表格展示
<el-dialog :visible.sync="dialogVisible2" title=" " width="50%">
<el-table :data="tableData2" style="width: 100%"
:cell-style="{ 'text-align': 'center' }"
:header-cell-style="{
background: '#E5F2FF',
color: '#000',
'text-align': 'center',
}">
<el-table-column
v-for="header in whiteListHeaders"
:key="header"
:prop="header"
:label="header"
width="140">
</el-table-column>
</el-table>
</el-dialog>
注意:对于大型的Excel文件或需要进行复杂数据处理的场景,可能需要使用后端API来接收上传的Excel文件,在后端解析文件数据后返回给前端在展示,这样有利于提高性能。