vue导出excel文件 linux系统打不开(基于vue 实现 excel导出导入功能)
第一步下包
excel导入导出功能需要我们下载哪些包?
在vue-element-admin中有着详细的文档查看:
Excel 导出
Excel 的导入导出都是依赖于js-xlsx来实现的 。
在 js-xlsx的基础上又封装了Export2Excel.js来方便导出数据 。
#使用
由于 Export2Excel不仅依赖js-xlsx还依赖file-saver和script-loader。
所以我们需要下载三个包 ,和一个js文件 Export2Excel
npm install xlsx file-saver -S npm install script-loader -S -D第二步:各种功能的实现
1.1:基本表头导出功能
1.2:复杂表头导出功能
1.3:excel表格导入功能
1.1.1:excel导出逻辑
逆向思维思考:
1-最终要拿到的是一个充满数据的文件
2-如何导出一个文件:用到excel.export_json_to_excel
3-export_json_to_excel方法需要那些参数:
multiHeader:// 多级表头 header:, //表头 必填 data: //具体数据 必填 filename: //表格名字 merges: //合并单元格 autoWidth: true, // 是否自适应宽度 bookType: xlsx, //导出格式4-了解参数的数据类型 ,接下来将数据转成能够导出的数据类型 ,也就是处理数据
5-先有数据才能处理数据 ,所以应该是要拿数据
到现在导出的逻辑已经清楚,那么开始正向梳理一下逻辑
1-发请求拿数据
2-定义方法处理数据
3-调用export_json_to_excel方法导出表格
4-查看导出的表格是否满意
接下来我将用后台人资项目来演示基本的数据导出excel表格
// 1- 获取数据并且处理完的数据 async onExportFn() { // 1-请求获取所有的数据 // {data} 是对请求拿到的数据进行结构 const { data } = await FindStaffList({ page: 1, size: this.total }) // 1-1 此时list里面保存的是所有的员工列表信息 const list = data.rows console.log(list) // 2-2 对数据进行处理 此时FilnalData 拿到的就我们要的数据格式 // 此处我封装成了一个函数 onSortList 并且将拿到的list数据传入该方法 return this.onSortList(list) },注意一点在这里需要data的数据类型是一个二维数组[[],[],[],....[]] 在vue-element-admin 中有详细的文档 ,搜索“导出 ” 或者搜索xlsx即可
// 2-2 对数据进行处理 在这里只是讲获取数据的方法 ,这是最简单的一种 ,也可以用map对数据进行处理 ,方法不一 ,只列出最简单易理解的 onSortList(list) { // 2-1 先定义排列顺序 这里通常有一个学术名叫做对照表 const sortOrder = [ username, mobile, timeOfEntry, formOfEmployment, correctionTime, workNumber, departmentName, ] // FilnalData 用来存放最后的数据 const FilnalData = [] list.forEach((item) => { const arr = [] sortOrder.forEach((obj) => { if (obj === formOfEmployment) { arr.push(item[obj] === 1 ? 正式 : 非正式) } else { arr.push(item[obj]) } }) FilnalData.push(arr) }) return FilnalData }, // 3- 此时数据已经处理完毕,那么就可以调用export_json_to_excel方法来进行导出表格 async onOrdinaryExport() { this.ExportLoading = true // onExportFn() 这里是一个primise异步方法 ,所以要用await const FilnalData = await this.onExportFn() // import(@/vendor/Export2Excel) 懒加载 导入后 ,拿到excel对象 的对象中有export_json_to_excel 方法 import(@/vendor/Export2Excel).then((excel) => { excel.export_json_to_excel({ header: [ 姓名, 手机号, 入职日期, 聘用形式, 转正日期, 工号, 部门, ], //表头 必填 data: FilnalData, //具体数据 必填 filename: 员工信息表格, autoWidth: true, bookType: xlsx, }) }) this.ExportLoading = false },如上操作,即可完美导出一份普通的带有表头的表格
1.2.1复杂表头导出功能
复杂表头和基本表头的导出 ,思考的逻辑是一样的 ,所以不再赘述
复杂表头的导出,相比基本表头导出 ,只有在export_json_to_excel中传递的参数多了两个 一个是 multiHeader(多级表头) ,一个是merges(合并)
通过分析export_json_to_excel.js文件的源代码 ,我们可以分析出 ,multiHeader是二维数组 ,merges是一维数组 ,数组中的内容是字符串 ,而且是带有:的字符串
所以 ,根据要求 ,我们可以自由合并单元格
filename = filename || excel-list data = [...data] data.unshift(header) for (let i = multiHeader.length - 1; i > -1; i--) { data.unshift(multiHeader[i]) }部分源码如图 。
data中的数据,首先会先把传过来的数据data解构后放入data中 ,然后对多级表头进行循环 ,循环结束,将每个数据push到data中 ,因为data中的数据是个数组中放的每一个元素是数组
所以multiHeader[i]是数组 ,所以multiHeader 是二维数组
复杂表头代码如下,与一般表头只有在导出的时候有差别
async onComplexExport() { this.ComplexExportLoading = true // 调用onExportFn方法获取处理完成后的数据 该方法 ,上面有 const FilnalData = await this.onExportFn() import(@/vendor/Export2Excel).then((excel) => { excel.export_json_to_excel({ multiHeader: [[姓名, 主要信息, , , , , 部门]], header: [ username, mobile, timeOfEntry, formOfEmployment, correctionTime, workNumber, departmentName, ], //表头 必填 data: FilnalData, //具体数据 必填 filename: 复杂表头的员工信息表格, // 要合并的单元格 merges: [A1:A2, B1:F1, G1:G2], autoWidth: true, bookType: xlsx, }) }) this.ComplexExportLoading = false },1.3.1:excel表格导入功能
Excel 导入
封装了UploadExcelExcel 导入组件 ,支持点击和拖拽上传 ,同样它也是依赖js-xlsx的 。
所以要实现导入功能
需要下载三个包 ,和一个vueUploadExcel组件
npm install xlsx file-saver -S npm install script-loader -S -DUploadExcel它提供了两个回调函数:beforeUpload:你可以在上传之前做一些自己的特殊判断 ,如判断文件的大小是否大于 1 兆?若大于 1 兆则停止解析并提示错误信息 。
onSuccess 解析成功时候会触发的回调函数 ,它会返回表格的表头和内容 。
handleSuccess({ results, header }) { this.tableData = results this.tableHeader = header }导入的功能 ,总体来说 ,要比导出简单一些 ,更加容易理解一下
总结思路
反向思考
1-最终要实现的效果,给当前页面添加几行数据
2-要实现给当前页面添加几行数据 ,并且是我们看的到数据 ,因为只有数据才能改变视图,所以我们一定要发请求 ,才能够将数据添加上
3--发请求 ,必然要牵扯到请求的参数,那么就要看参数是什么格式的
4-有了参数的格式 ,那么我们就需要将一个方法 ,用来将我们得到的数据 ,转变成参数需要的数据类型
5-要转变 ,首先要先拿到表格里面的数据 ,所以这就需要用到我们的UploadExcel组件给我们提供的一个方法onSuccess
到现在导出的逻辑已经清楚,那么开始正向梳理一下逻辑‘
1-下载组件 ,在页面中导入 ,使用onSuccess方法 ,拿到表格的数据 tableData
2-定义一个方法 ,对拿到的数据进行处理,将数据处理成我们发请求需要的数据
3-定义接口 ,导入接口 ,发请求
4-调用接口,重新获取数据 ,渲染视图
逻辑清楚 ,代码开始
以下是我对UploadExcel组件的一些源码的分析与整理,只有简单的标注和样式的修改
<template> <div class="upload-excel"> <div class="btn-upload"> <el-button :loading="loading" size="mini" type="primary" @click="handleUpload" > 点击上传 </el-button> </div> <!-- 隐藏域 --> <!-- 2-监听表单的change事件 ,点击了button按钮 ,触发 表单点击事件 当选中了文件后 ,会触发change事件 --> <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick" /> <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover" > <i class="el-icon-upload" /> <span>将文件拖到此处</span> </div> </div> </template> <script> import * as XLSX from xlsx export default { props: { beforeUpload: Function, // eslint-disable-line onSuccess: Function, // eslint-disable-line }, data() { return { loading: false, excelData: { header: null, results: null, }, } }, methods: { // 8-1 generateData 方法 ,接收两个参数 ,一个是处理完的表格头数据 ,一个是表格内容数据 generateData({ header, results }) { this.excelData.header = header this.excelData.results = results // 8-2 数据处理完成 ,进入逻辑判断 ,父传入onSuccess方法 则调用方法 ,并且传入读取后的表格数据 this.onSuccess && this.onSuccess(this.excelData) }, handleDrop(e) { e.stopPropagation() e.preventDefault() if (this.loading) return const files = e.dataTransfer.files if (files.length !== 1) { this.$message.error(Only support uploading one file!) return } const rawFile = files[0] // only use files[0] if (!this.isExcel(rawFile)) { this.$message.error( Only supports upload .xlsx, .xls, .csv suffix files ) return false } this.upload(rawFile) e.stopPropagation() e.preventDefault() }, handleDragover(e) { e.stopPropagation() e.preventDefault() e.dataTransfer.dropEffect = copy }, handleUpload() { // 1- 当点击button按钮的时候触发表单的点击事件 this.$refs[excel-upload-input].click() }, handleClick(e) { // 3-1 选中的文件的数组 const files = e.target.files //3-2 拿到具体的文件 const rawFile = files[0] if (!rawFile) return // 3-3 触发upload方法 同时把当前拿到的文件传过去 this.upload(rawFile) }, upload(rawFile) { // 4-1 参数rawFile是当前选中的文件 表单清空 this.$refs[excel-upload-input].value = null // 4-2 this.beforeUpload prop传入的方法 表示加载前 有没有选中文件 if (!this.beforeUpload) { this.readerData(rawFile) return } // 4-3 将选中的文件,传给父 父可以做一些拦截操作 ,可以限制文件的大小 ,类型等等 如果不满足条件返回false 默认返回true const before = this.beforeUpload(rawFile) if (before) { this.readerData(rawFile) } }, // 5-1 满足条件,进入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[0] const worksheet = workbook.Sheets[firstSheetName] const header = this.getHeaderRow(worksheet) const results = XLSX.utils.sheet_to_json(worksheet) // 7- 在这一步 ,确认数据已经处理完成 跳转到新的方法generateData()中 ,并且把处理完的数据{ header, results } 解构后传给这个方法 this.generateData({ header, results }) this.loading = false resolve() } reader.readAsArrayBuffer(rawFile) }) }, // 6 这一块是处理数据 不用详细深究 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 }, isExcel(file) { return /\.(xlsx|xls|csv)$/.test(file.name) }, }, } </script> <style scoped lang="scss"> .upload-excel { display: flex; justify-content: center; margin-top: 100px; .excel-upload-input { display: none; z-index: -9999; } .btn-upload, .drop { border: 1px dashed #bbb; width: 350px; height: 160px; text-align: center; line-height: 160px; } .drop { line-height: 80px; color: #bbb; i { font-size: 60px; display: block; } } } </style>接受onSuccess回调函数中,对数据进行处理
onSuccess(excelData) { // console.log(excelData) 在这里打印的是除了表头之外的数据 也就是我们需要的数据 // 定义一个数据对照表 const contrastObj = { 入职日期: timeOfEntry, 姓名: username, 手机号: mobile, 工号: workNumber, 转正日期: correctionTime, } // 定义一个空数组 ,用来保存最后需要发请求的数据 const excelList = [] // 对拿到的数据进行遍历 excelData.results.forEach((item) => { const obj = {} for (const key in item) { if (key === 转正日期 || key === 入职日期) { obj[contrastObj[key]] = formatDate(item[key], -) } else { obj[contrastObj[key]] = item[key] } } excelList.push(obj) }) // console.log(excelList) // 在这里已经完成数据的整理 ,调接口 ,发送请求 },至此一个完整体系 的 基于vue的表格的导入导出总结完毕 ,学习愉快
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!