Vue3 exceljs库实现前端导入导出Excel
前言
需求场景
最近在开发项目时需要批量导入和导出Excel数据,在实现这个需求时,我们既可以在前端完成数据解析和文件生成工作,也可以通过前端发起导入以及导出请求后,后端实现解析文件流解析文件内容以及生成文件并提供下载链接的功能。
相较于后端处理Excel数据而言,使用前端导入导出可以提供更高的实时性,用户可以直接在浏览器中触发导出操作,无需等待后端处理。且可以在前端完成数据生成以及数据校验处理工作,大大减轻后端服务器的压力,大幅增强用户体验。
具体的技术方案选型主要看业务场景,如果对于小型数据集、实时性需求较高的导入导出操作,优先考虑前端实现。而对于大型数据集、需要业务逻辑处理、以及安全性要求高的场景,则后端处理更为合适。
技术方案
xlsx与xlsx-style组合方案:xlsx 是目前前端最常用的Excel解决方案,又叫做SheetJS,但社区版不支持修改Excel的样式,需要购买Pro版才可以,如果需要修改导出的Excel文件样式,需要结合xlsx-style库一起使用。但遗憾的是xlsx库已经两年多不更新,而xlsx-style上一个版本更是8年前发布,目前已经不再推荐使用该方案。
exceljs与file-saver方案:exceljs是一款免费开源支持导入导出Excel 操作工具,并且可以实现样式的修改以及 Excel 的高级功能,是非常值得推荐的一个处理 Excel 的库,file-saver可以实现保存文件到本地。本文以exceljs与file-saver操作xlsx格式文件为例介绍如何具体上手使用。
exceljs介绍
ExcelJS是一个用于在Node.js和浏览器中创建、读取和修改Excel文件的强大JavaScript库。它提供了丰富的功能和灵活的API,使你能够在你的应用程序中处理和操作Excel文件。
下面是一些ExcelJS库的关键特性和功能:
- 创建和修改Excel文件:ExcelJS允许你创建新的Excel工作簿,并在其中添加工作表、行和单元格。你可以设置单元格的值、样式、数据类型以及其他属性。
- 读取和解析Excel文件:ExcelJS支持读取和解析现有的Excel文件。你可以将Excel文件加载到工作簿中,然后访问工作表、行和单元格的数据。
- 导出和保存Excel文件:ExcelJS可以将工作簿保存为Excel文件,支持多种格式,如XLSX、XLS和CSV。你可以将工作簿保存到本地文件系统或将其发送到客户端以供下载。
- 处理复杂的Excel功能:ExcelJS支持处理复杂的Excel功能,如公式、图表、数据验证、条件格式和保护工作表等。你可以根据需要设置和操作这些功能。
- 支持自定义样式和格式:ExcelJS允许你自定义单元格、行、列和工作表的样式和格式。你可以设置字体、颜色、填充、边框、对齐方式以及数字和日期格式等。
参考文档
npm仓库地址:
https://www.npmjs.com/package/exceljs
官方中文文档地址:
https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md
快速上手
安装依赖
exceljs用于Excel数据处理,file-sever用于保存到本地文件。
npm i exceljs
npm i file-saver
导出Excel
让我们先从简单的数据导出开始,快速体验如何使用exceljs导出Excel文件,需要注意的是在浏览器环境中运行 JavaScript,浏览器的安全策略通常不允许直接访问读写本地文件系统。在这种情况下,需要通过其他方式将文件转换为buffer数据,在导出Excel时使用FileSaver.js库将缓冲区数据保存到文件中。
导出excel
当我们点击导出excel按钮时,调用exportFile函数,完成excel文件下载,下载后的文件内容如下:
导入Excel
导入excel文件时,同样使用FileReader的readAsArrayBuffer方法,将文件转换为二进制字符串,然后从buffer中加载数据并解析。
上传文件后,解析内容如下所示:
进阶操作
添加数据
我们可以通过columns方法添加列标题并定义列键和宽度,设置好表头后,我们可以直接通过addRow方法,根据key值去添加每一行的数据。
参考文档:
https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E5%88%97
完整代码如下:
导出excel
添加数据后导出文件效果如下:
读取数据
我们可以使用getRow方法,传入指定行参数读取行数据。
使用getColumn方法,传入键、字母、id参数读取列数据。
使用eachCell方法可以遍历每个单元格内容。
参考文档:
https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E8%A1%8C
代码如下:
导出excel
效果
样式
在导出excel文件时,默认没有任何样式的,为了美观我们需要添加样式,而exceljs支持修改表格样式,具体内容可参考文档
https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E6%A0%B7%E5%BC%8F
例如,我们需要设置所有单元格居中对齐,并添加边框。并分别指定标题行和内容行字体大小、背景颜色、行高属性,代码如下:
导出excel
导出Excel样式效果如下所示,已经成功按我们指定的样式导出了文件:
筛选
在很多的时候我们需要对表格中每一列的数据进行筛选,比如直接筛选姓名等列信息,我们可以通过 autoFilter 来添加筛选。参考文档:
https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#
%E8%87%AA%E5%8A%A8%E7%AD%9B%E9%80%89%E5%99%A8
代码如下:
导出excel
导入后的效果如下,在姓名、年龄、身高列添加了筛选按钮:
公式值
参考文档:exceljs/README_zh.md at
5bed18b45e824f409b08456b59b87430ded023ab · exceljs/exceljs · GitHub
我们可以直接对表格中的数据进行公式计算,比如 求和(SUM),平均数(AVERAGE) 等。
例如我们需要计算平均值、最大值、指定公式时,代码如下:
导出excel
导出Excel文件效果如下,E列已经自动替换为公式计算。
合并单元格
表格的合并应该是业务需求中最频繁的功能。当然这一功能使用 xlsx 也可以实现,我们只需要使用mergeCells方法,传入合并单元格范围参数即可。
参考文档:
https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#
%E5%90%88%E5%B9%B6%E5%8D%95%E5%85%83%E6%A0%BC
具体代码实现如下所示:
导出excel
单元格合并后导出文件效果如下:
数据验证
有时候我们需要为某个单元格添加数据可以方便直接下拉选择指定的值,此时就需要使用数据验证功能,传入可填写的选项列表。
参考文档:
https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#
%E6%95%B0%E6%8D%AE%E9%AA%8C%E8%AF%81
例如我们对是否注册列添加数据验证,可填值为"是、否、未知",具体代码如下:
导出excel
导出的excel文件效果如下:
条件格式化
我们可以为指定单元格添加条件格式,对满足条件的单元格设置指定的样式。
参考文档:exceljs/README_zh.md at
5bed18b45e824f409b08456b59b87430ded023ab · exceljs/exceljs · GitHub
例如为年龄大于18岁单元格进行红色标注,代码如下:
导出excel
导出后的文件效果如下:
封装exceljs
封装导入导出函数
为了提高项目代码的复用性,通常会将excel导入导出功能封装到单独的函数中方便调用,封装后的函数如下:
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
import {timeFile} from "@/utils/timeFormat";
// 导出excel文件
export function exportFile(export_data, filename) {
// 创建工作簿
const workbook = new ExcelJS.Workbook();
// 添加工作表,名为sheet1
const sheet1 = workbook.addWorksheet("sheet1");
// 获取表头所有键
const headers = Object.keys(export_data[0])
// 将标题写入第一行
sheet1.addRow(headers);
// 将数据写入工作表
export_data.forEach((row) => {
const values = Object.values(row)
sheet1.addRow(values);
});
// 设置默认宽高属性
sheet1.properties.defaultColWidth = 20
sheet1.properties.defaultRowHeight = 20
// 修改所有单元格样式
// 遍历每一行
sheet1.eachRow((row, rowNumber) => {
// 遍历每个单元格
row.eachCell((cell) => {
// 设置边框样式
cell.border = {
top: {style: 'thin'},
left: {style: 'thin'},
bottom: {style: 'thin'},
right: {style: 'thin'}
};
// 设置居中对齐
cell.alignment = {
vertical: 'middle',
horizontal: 'center'
};
});
});
// 获取标题行数据
const titleCell = sheet1.getRow(1);
// 设置标题行单元格样式
titleCell.eachCell((cell) => {
// 设置标题行背景颜色
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: {argb: '3498db'}
};
// 设置标题行字体
cell.font = {
bold: true,// 字体粗体
};
})
// 导出表格文件
workbook.xlsx.writeBuffer().then((buffer) => {
let file = new Blob([buffer], {type: "application/octet-stream"});
FileSaver.saveAs(file, filename + timeFile() + ".xlsx");
}).catch(error => console.log('Error writing excel export', error))
}
// 导入excel文件
export function importFile(content) {
return new Promise((resolve, reject) => {
// 创建一个空的JavaScript对象数组,用于存储解析后的数据
const data = [];
//创建Workbook实例
const workbook = new ExcelJS.Workbook();
workbook.xlsx.load(content).then(workbook => {
// 获取第一个worksheet内容
const worksheet = workbook.getWorksheet(1);
// 获取第一行的标题
const headers = [];
worksheet.getRow(1).eachCell((cell) => {
headers.push(cell.value);
});
// console.log("headers", headers)
// 遍历工作表的每一行(从第二行开始,因为第一行通常是标题行)
for (let rowNumber = 2; rowNumber <= worksheet.rowCount; rowNumber++) {
const rowData = {};
const row = worksheet.getRow(rowNumber);
// 遍历当前行的每个单元格
row.eachCell((cell, colNumber) => {
// 获取标题对应的键,并将当前单元格的值存储到相应的属性名中
rowData[headers[colNumber - 1]] = cell.value;
});
// 将当前行的数据对象添加到数组中
data.push(rowData);
}
// console.log("data", data)
resolve(data);
}).catch(error => {
reject(error);
});
})
}
vue组件调用
以element plus为例,调用函数完成Excel文件导入与导出,代码如下:
导出excel
导入excel
导入数据预览
{{ uploadData}}
点击下载
将文件拖到此处,或点击上传
请上传.xls,.xlsx格式文件,文件最大为500kb
页面效果
封装后的页面效果如下,至此,一个简单的vue前端实现Excel文件导入导出功能便开发完成了。
完整代码
gitee:https://gitee.com/cuiliang0302/vue3_vite_element-plus
github:https://github.com/cuiliang0302/vue3-vite-template
查看更多
微信公众号
微信公众号同步更新,欢迎关注微信公众号《崔亮的博客》第一时间获取最近文章。
博客网站
崔亮的博客-专注devops自动化运维,传播优秀it运维技术文章。更多原创运维开发相关文章,欢迎访问
https://www.cuiliangblog.cn