基于vue 实现 excel导出导入功能
Posted 小羊卷
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于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 -D
UploadExcel它提供了两个回调函数: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的表格的导入导出总结完毕,学习愉快
Vue框架下实现导入导出Excel导出PDF
项目需求:开发一套基于Vue框架的工程档案管理系统,用于工程项目资料的填写、编辑和归档,经调研需支持如下功能:
- Excel报表的导入、导出
- PDF文件的导出
- 打印表格
经过技术选型,项目组一致决定通过表格组件SpreadJS 来实现。以下是实现Excel报表的导入导出、PDF导出、打印表格的一些思路,供大家参考:
环境介绍
1.后台:Spring Boot 2.x
2.前台:vue、vue-element、webpack、iview、Vuex.js 2.x
3.组件:SpreadJS V11
SpreadJS 组件下载地址:https://www.grapecity.com.cn/download/?pid=57
初始化Vue项目
这里,可以参考这篇技术博客: 3分钟创建 SpreadJS 的 Vue 项目
项目运行效果:
如下是本地的一个Excel文件:
通过SpreadJS,导入到项目中的效果:
我的项目中应用了SpreadJS V12.2.5的版本(目前官网SpreadJS的最新版本是V13),其中package.json 需要添加的引用如下:
"dependencies": { "@grapecity/spread-excelio": "12.2.5", "@grapecity/spread-sheets": "12.2.5", "@grapecity/spread-sheets-pdf": "^12.2.5", "@grapecity/spread-sheets-print": "12.2.5", "@grapecity/spread-sheets-resources-zh": "12.2.5", "@grapecity/spread-sheets-vue": "12.2.5", "@grapecity/spread-sheets-charts": "12.2.5" , "file-saver": "2.0.2", "jquery": "2.2.1", "vue": "^2.5.2", "vue-router": "^3.0.1" },
执行npm install 命令安装SpreadJS 组件
可以参考这篇技术博客:https://www.grapecity.com.cn/blogs/spread-sheets-v11sp1-support-npm
导入导出Excel报表
- 安装相关的资源包: "@grapecity/spread-excelio"、 "file-saver"
- 在页面中引入: import ExcelIO from ‘@grapecity/spread-excelio‘、import FaverSaver from ‘file-saver‘
- 如下代码可实现导入导出Excel:
exportXlsx () { let ex = new ExcelIO.IO() let json = this.spread.toJSON() ex.save(json, function (blob) { FaverSaver.saveAs(blob, ‘export.xlsx‘) }, function (e) { console.log(e) }) }, importXlsx(){ let self = this; var excelIO = new ExcelIO.IO(); console.log(excelIO); const excelFile = document.getElementById("fileDemo").files[0]; excelIO.open(excelFile, function (json) { let workbookObj = json; self.spread.fromJSON(workbookObj); }, function (e) { alert(e.errorMessage); }); }
导出PDF的注意事项
- 安装相同版本的 PDF包: "@grapecity/spread-sheets-pdf"
- 在需要打印的页面引入该包: import "@grapecity/spread-sheets-pdf";
- 引入该包需要注意引入顺序,先引入 @grapecity/spread-sheets和 grapecity/spread-sheets-print
- 需引入第三方插件file-saver : import FaverSaver from ‘file-saver‘
- 如下几行代码可实现导出PDF功能
savePdf(){ let self = this; let jsonString = JSON.stringify(self.spread.toJSON()); let printSpread = new GC.Spread.Sheets.Workbook(); printSpread.fromJSON(JSON.parse(jsonString)); printSpread.savePDF(function(blob) { // window.open(URL.createObjectURL(blob)) FaverSaver.saveAs(blob, ‘Hello.pdf‘) }, function(error) { console.log(error); }, { title: ‘Print‘, }); }
示例代码下载
大家可下载下方的示例代码,实现导出PDF、导入导出Excel功能。
以上是关于基于vue 实现 excel导出导入功能的主要内容,如果未能解决你的问题,请参考以下文章