Vue3 exceljs库实现前端导入导出Excel

这篇具有很好参考价值的文章主要介绍了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库的关键特性和功能:

  1. 创建和修改Excel文件:ExcelJS允许你创建新的Excel工作簿,并在其中添加工作表、行和单元格。你可以设置单元格的值、样式、数据类型以及其他属性。
  2. 读取和解析Excel文件:ExcelJS支持读取和解析现有的Excel文件。你可以将Excel文件加载到工作簿中,然后访问工作表、行和单元格的数据。
  3. 导出和保存Excel文件:ExcelJS可以将工作簿保存为Excel文件,支持多种格式,如XLSX、XLS和CSV。你可以将工作簿保存到本地文件系统或将其发送到客户端以供下载。
  4. 处理复杂的Excel功能:ExcelJS支持处理复杂的Excel功能,如公式、图表、数据验证、条件格式和保护工作表等。你可以根据需要设置和操作这些功能。
  5. 支持自定义样式和格式: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库将缓冲区数据保存到文件中。

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 导出数据列表
  const data = [
    {"姓名": "张三", "年龄": 18, "身高": 175, "体重": 74},
    {"姓名": "李四", "年龄": 22, "身高": 177, "体重": 84},
    {"姓名": "王五", "年龄": 53, "身高": 155, "体重": 64}
  ]
  // 获取表头所有键
  const headers = Object.keys(data[0])
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row) => {
    const values = Object.values(row)
    sheet1.addRow(values);
  });
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}
</script>

<style scoped lang="scss">

</style>

当我们点击导出excel按钮时,调用exportFile函数,完成excel文件下载,下载后的文件内容如下:
Vue3 exceljs库实现前端导入导出Excel,前端,excel

导入Excel

导入excel文件时,同样使用FileReader的readAsArrayBuffer方法,将文件转换为二进制字符串,然后从buffer中加载数据并解析。

<template>
  <input
      type="file"
      accept=".xls,.xlsx"
      class="upload-file"
      @change="importExcel($event)"/>
</template>

<script setup>
import ExcelJS from "exceljs";
// 导出excel文件
const importExcel = (event) => {
  //获取选择的文件
  const files = event.target.files
  //创建Workbook实例
  const workbook = new ExcelJS.Workbook();
  // 使用FileReader对象来读取文件内容
  const fileReader = new FileReader()
  // 二进制字符串的形式加载文件
  fileReader.readAsArrayBuffer(files[0])
  fileReader.onload = ev => {
    console.log(ev)
    // 从 buffer中加载数据解析
    workbook.xlsx.load(ev.target.result).then(workbook => {
      // 获取第一个worksheet内容
      const worksheet = workbook.getWorksheet(1);
      // 获取第一行的标题
      const headers = [];
      worksheet.getRow(1).eachCell((cell) => {
        headers.push(cell.value);
      });
      console.log("headers", headers)
      // 创建一个空的JavaScript对象数组,用于存储解析后的数据
      const data = [];
      // 遍历工作表的每一行(从第二行开始,因为第一行通常是标题行)
      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)
    })
  }
}
</script>

<style scoped lang="scss">

</style>

上传文件后,解析内容如下所示:
Vue3 exceljs库实现前端导入导出Excel,前端,excel

进阶操作

添加数据

我们可以通过columns方法添加列标题并定义列键和宽度,设置好表头后,我们可以直接通过addRow方法,根据key值去添加每一行的数据。
参考文档:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E5%88%97
完整代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 添加表头列数据
  sheet1.columns = [
    {header: "姓名", key: "name", width: 20},
    {header: "年龄", key: "age", width: 10},
    {header: "身高", key: "height", width: 10},
    {header: "体重", key: "weight", width: 10},
  ];
  // 添加内容列数据
  sheet1.addRow({sort: 1, name: "张三", age: 18, height: 175, weight: 74});
  sheet1.addRow({sort: 2, name: "李四", age: 22, height: 177, weight: 88});
  sheet1.addRow({sort: 3, name: "王五", age: 53, height: 155, weight: 62});
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}

</script>

<style scoped lang="scss">

</style>

添加数据后导出文件效果如下:
Vue3 exceljs库实现前端导入导出Excel,前端,excel

读取数据

我们可以使用getRow方法,传入指定行参数读取行数据。
使用getColumn方法,传入键、字母、id参数读取列数据。
使用eachCell方法可以遍历每个单元格内容。
参考文档:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E8%A1%8C
代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 添加表头列数据
  sheet1.columns = [
    {header: "姓名", key: "name", width: 20},
    {header: "年龄", key: "age", width: 10},
    {header: "身高", key: "height", width: 10},
    {header: "体重", key: "weight", width: 10},
  ];
  // 添加内容列数据
  sheet1.addRow({sort: 1, name: "张三", age: 18, height: 175, weight: 74});
  sheet1.addRow({sort: 2, name: "李四", age: 22, height: 177, weight: 88});
  sheet1.addRow({sort: 3, name: "王五", age: 53, height: 155, weight: 62});
  // 读取行数据
  sheet1.getRow(1).eachCell((cell, rowIdx) => {
    console.log("行数据", cell.value, rowIdx);
  });
  // 读取列数据,可以通过键(name),字母(B)和基于id(1)的列号访问单个列
  sheet1.getColumn("name").eachCell((cell, rowIdx) => {
    console.log("列数据", cell.value, rowIdx);
  });
}

</script>

<style scoped lang="scss">

</style>

效果
Vue3 exceljs库实现前端导入导出Excel,前端,excel

样式

在导出excel文件时,默认没有任何样式的,为了美观我们需要添加样式,而exceljs支持修改表格样式,具体内容可参考文档https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E6%A0%B7%E5%BC%8F
例如,我们需要设置所有单元格居中对齐,并添加边框。并分别指定标题行和内容行字体大小、背景颜色、行高属性,代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 导出数据列表
  const data = [
    {"姓名": "张三", "年龄": 18, "身高": 175, "体重": 74},
    {"姓名": "李四", "年龄": 22, "身高": 177, "体重": 84},
    {"姓名": "王五", "年龄": 53, "身高": 155, "体重": 64}
  ]
  // 获取表头所有键
  const headers = Object.keys(data[0])
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row) => {
    const values = Object.values(row)
    sheet1.addRow(values);
  });
  // 修改所有单元格样式
  // 遍历每一行
  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);
  // 设置行高为30
  titleCell.height = 30
  // 设置标题行单元格样式
  titleCell.eachCell((cell) => {
    // 设置标题行背景颜色为黄色
    cell.fill = {
      type: 'pattern',
      pattern: 'solid',
      fgColor: {argb: 'FFFF00'}
    };
    // 设置标题行字体
    cell.font = {
      color: {argb: 'FF0000'}, //颜色为红色
      bold: true,// 字体粗体
      size: 18 // 设置字体大小为18
    };
  })
  // 获取第二行到最后一行的内容数据
  const bodyRows = sheet1.getRows(2, sheet1.rowCount);
  // 处理内容行的数据
  bodyRows.forEach((bodyRow) => {
    // 设置行高为20
    bodyRow.height = 20
    bodyRow.eachCell((cell) => {
      cell.font = {
        size: 16 // 设置内容行字体大小为16
      };
    });
  });
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}

</script>

<style scoped lang="scss">

</style>

导出Excel样式效果如下所示,已经成功按我们指定的样式导出了文件:
Vue3 exceljs库实现前端导入导出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
代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 导出数据列表
  const data = [
    {"姓名": "张三", "年龄": 18, "身高": 175, "体重": 74},
    {"姓名": "李四", "年龄": 22, "身高": 177, "体重": 84},
    {"姓名": "王五", "年龄": 53, "身高": 155, "体重": 64}
  ]
  // 获取表头所有键
  const headers = Object.keys(data[0])
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row) => {
    const values = Object.values(row)
    sheet1.addRow(values);
  });
  // 单列筛选
  // sheet1.autoFilter = "A1";
  // 多个列筛选
  sheet1.autoFilter = "A1:C1";
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}

</script>

<style scoped lang="scss">

</style>

导入后的效果如下,在姓名、年龄、身高列添加了筛选按钮:
Vue3 exceljs库实现前端导入导出Excel,前端,excel

公式值

参考文档:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E5%80%BC%E7%B1%BB%E5%9E%8B
我们可以直接对表格中的数据进行公式计算,比如 求和(SUM),平均数(AVERAGE) 等。
例如我们需要计算平均值、最大值、指定公式时,代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 导出数据列表
  const data = [
    {"姓名": "张三", "年龄": 18, "身高": 1.75, "体重": 74},
    {"姓名": "李四", "年龄": 22, "身高": 1.77, "体重": 84},
    {"姓名": "王五", "年龄": 53, "身高": 1.55, "体重": 64}
  ]
  // 获取表头所有键
  const headers = Object.keys(data[0])
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row) => {
    const values = Object.values(row)
    sheet1.addRow(values);
  });
  // 添加单元格
  sheet1.getCell("E1").value = "BMI指数";
  sheet1.getCell("F1").value = "平均身高";
  sheet1.getCell("G1").value = "最大体重";
  // 计算平均身高
  sheet1.getCell("F2").value = {formula: "=AVERAGE(C2:C4)"};
  // 计算最大体重
  sheet1.getCell("G2").value = {formula: "=MAX(D2:D4)"};
  // 计算BMI指数
  // 获取第5列对象
  const BMIRange = sheet1.getColumn(5)
  BMIRange.eachCell((cell) => {
    console.log("cell", cell)
    console.log(cell.row)
    // 从第二列开始添加计算公式
    if (cell.row >= 2) {
      sheet1.getCell("E" + cell.row).value = {formula: "D" + cell.row + "/" + "(C" + cell.row + "*" + "C" + cell.row + ")"};
    }
  })
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}

</script>

<style scoped lang="scss">

</style>

导出Excel文件效果如下,E列已经自动替换为公式计算。
Vue3 exceljs库实现前端导入导出Excel,前端,excel

合并单元格

表格的合并应该是业务需求中最频繁的功能。当然这一功能使用 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
具体代码实现如下所示:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 导出数据列表
  const data = [
    {"姓名": "张三", "年龄": 18, "身高": 175, "体重": 74},
    {"姓名": "李四", "年龄": 18, "身高": '未知', "体重": '未知'},
    {"姓名": "王五", "年龄": 53, "身高": '未知', "体重": '未知'},
    {"姓名": "赵六", "年龄": 12, "身高": '未知', "体重": '未知'}
  ]
  // 获取表头所有键
  const headers = Object.keys(data[0])
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row) => {
    const values = Object.values(row)
    sheet1.addRow(values);
  });
  // 上下合并单元格
  sheet1.mergeCells("B2:B3");
  // 左右合并单元格
  sheet1.mergeCells("C3:D3");
  // 范围合并单元格
  sheet1.mergeCells("C4:D5");
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}

</script>

<style scoped lang="scss">

</style>

单元格合并后导出文件效果如下:
Vue3 exceljs库实现前端导入导出Excel,前端,excel

数据验证

有时候我们需要为某个单元格添加数据可以方便直接下拉选择指定的值,此时就需要使用数据验证功能,传入可填写的选项列表。
参考文档:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E6%95%B0%E6%8D%AE%E9%AA%8C%E8%AF%81
例如我们对是否注册列添加数据验证,可填值为"是、否、未知",具体代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 导出数据列表
  const data = [
    {"姓名": "张三", "年龄": 18, "身高": 1.75, "体重": 74, "是否注册": ''},
    {"姓名": "李四", "年龄": 22, "身高": 1.77, "体重": 84, "是否注册": ''},
    {"姓名": "王五", "年龄": 53, "身高": 1.55, "体重": 64, "是否注册": ''}
  ]
  // 获取表头所有键
  const headers = Object.keys(data[0])
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row) => {
    const values = Object.values(row)
    sheet1.addRow(values);
  });
  // 获取第5列对象
  const VerificationRange = sheet1.getColumn(5)
  VerificationRange.eachCell((cell) => {
    // 从第二列开始添加数据验证规则
    if (cell.row >= 2) {
      sheet1.getCell("E" + cell.row).dataValidation = {
        type: "list",
        allowBlank: true,
        formulae: ['"是,否,未知"']
      };
    }
  })
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}

</script>

<style scoped lang="scss">

</style>

导出的excel文件效果如下:
Vue3 exceljs库实现前端导入导出Excel,前端,excel

条件格式化

我们可以为指定单元格添加条件格式,对满足条件的单元格设置指定的样式。
参考文档:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E6%9D%A1%E4%BB%B6%E6%A0%BC%E5%BC%8F%E5%8C%96
例如为年龄大于18岁单元格进行红色标注,代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
</template>

<script setup>
import ExcelJS from "exceljs";
import FileSaver from "file-saver";
// 导出excel文件
const exportExcel = () => {
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 添加工作表,名为sheet1
  const sheet1 = workbook.addWorksheet("sheet1");
  // 导出数据列表
  const data = [
    {"姓名": "张三", "年龄": 18, "身高": 1.75, "体重": 74},
    {"姓名": "李四", "年龄": 22, "身高": 1.77, "体重": 84},
    {"姓名": "王五", "年龄": 53, "身高": 1.55, "体重": 64}
  ]
  // 获取表头所有键
  const headers = Object.keys(data[0])
  // 将标题写入第一行
  sheet1.addRow(headers);
  // 将数据写入工作表
  data.forEach((row) => {
    const values = Object.values(row)
    sheet1.addRow(values);
  });
  // 年龄大于18岁红色标注
  sheet1.addConditionalFormatting({
    ref: "B2:B4",
    rules: [
      {
        type: "cellIs",
        operator: "greaterThan",
        priority: 1,
        formulae: [18],
        style: {
          fill: {
            type: "pattern",
            pattern: "solid",
            bgColor: { argb: "FFFFC0CB" },
          },
        },
      },
    ],
  });
  // 导出表格文件
  workbook.xlsx.writeBuffer().then((buffer) => {
    let file = new Blob([buffer], {type: "application/octet-stream"});
    FileSaver.saveAs(file, "ExcelJS.xlsx");
  }).catch(error => console.log('Error writing excel export', error))
}

</script>

<style scoped lang="scss">

</style>

导出后的文件效果如下:
Vue3 exceljs库实现前端导入导出Excel,前端,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文件导入与导出,代码如下:

<template>
  <el-button type="primary" @click="exportExcel">导出excel</el-button>
  <el-button type="success" @click="importExcel">导入excel</el-button>
  <p>导入数据预览</p>
  {{ uploadData}}
  <el-dialog
      v-model="uploadDialogVisible"
      title="批量添加数据"
      width="40%"
  >
    <el-form label-width="120px">
      <el-form-item label="模板下载:">
        <el-button type="info" @click="downloadTemplate">
          <el-icon>
            <Download/>
          </el-icon>
          点击下载
        </el-button>
      </el-form-item>
      <el-form-item label="文件上传:">
        <el-upload drag accept=".xls,.xlsx" :auto-upload="false" :on-change="handleChange">
          <el-icon class="el-icon--upload">
            <upload-filled/>
          </el-icon>
          <div class="el-upload__text">
            将文件拖到此处,或<em>点击上传</em>
          </div>
          <template #tip>
            <div class="el-upload__tip">
              请上传.xls,.xlsx格式文件,文件最大为500kb
            </div>
          </template>
        </el-upload>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="uploadDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitUpload">
          导入
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>
import {ref} from "vue";
import {ElMessage} from "element-plus";
import {Download, UploadFilled} from "@element-plus/icons-vue"
import {getDemo} from "@/api/home";
import {timeFormatConversion} from "@/utils/timeFormat";
import {exportFile, importFile} from "@/utils/excel";
// 表格字段配置
const fieldConfig = ref([
  {
    'label': 'ID', // 标签
    'model': 'id',// 字段名
    'is_export': true,// 是否导出该字段
  },
  {
    'label': '用户名', // 标签
    'model': 'username',// 字段名
    'is_export': true, // 是否导出该字段
  },
  {
    'label': '省份', // 标签
    'model': 'province',// 字段名
    'is_export': true // 是否导出该字段
  },
  {
    'label': '性别', // 标签
    'model': 'sex_name',// 字段名
    'is_export': true // 是否导出该字段
  },
  {
    'label': '生日', // 标签
    'model': 'birthday',// 字段名
    'is_export': true, // 是否导出该字段
  },
  {
    'label': '身高(cm)', // 标签
    'model': 'height',// 字段名
    'is_export': true, // 是否导出该字段
  },
  {
    'label': '体重(kg)', // 标签
    'model': 'weight',// 字段名
    'is_export': true,// 是否导出该字段
  },
  {
    'label': '注册时间', // 标签
    'model': 'created_time',// 字段名
    'is_export': true, // 是否导出该字段
  },
  {
    'label': '个人介绍', // 标签
    'model': 'introduction',// 字段名
    'is_export': true,// 是否导出该字段
  }
])
// 导出Excel事件
const exportExcel = () => {
  ElMessage({
    message: '开始导出数据,请稍候!',
    type: 'success',
  })
  // 导出数据查询参数
  const printParams = {
    'size': 1000,
    'page': 1,
  }
  // 获取需要导出的字段配置
  const export_fields = fieldConfig.value
      .filter(obj => obj['is_export'])
      .map(({label, model}) => ({[model]: label}))
  // 处理数据结构
  getDemo(printParams).then((response) => {
    // console.log(response.results)
    const export_data = response.results.map(obj => {
      const newObj = {};
      export_fields.forEach(field => {
        const [key, value] = Object.entries(field)[0];
        if (key === 'created_time') {
          newObj[value] = timeFormatConversion((obj[key]), 'YYYY-MM-DD HH:mm:ss');
        } else {
          newObj[value] = obj[key];
        }
      });
      return newObj;
    });
    let filename = '示例用户'
    exportFile(export_data, filename);
  }).catch(response => {
    //发生错误时执行的代码
    console.log(response)
    ElMessage.error('获取列表数据失败!')
  });
}
// 导入excel弹窗是否显示
const uploadDialogVisible = ref(false)
// 点击导入excel按钮事件
const importExcel = () => {
  uploadDialogVisible.value = true
}
// 下载模板文件
const downloadTemplate = () => {
  window.open('https://api.cuiliangblog.cn/static/demo-template.xlsx')
}
// 文件数据
const uploadData=ref([])
// 文件上传事件
const handleChange = (file) => {
  const reader = new FileReader();
  reader.onload = () => {
    const content = reader.result;
    importFile(content).then((data) => {
      console.log(data)
      uploadData.value = data
    }).catch(response => {
      //发生错误时执行的代码
      console.log(response)
      ElMessage.error('获取列表数据失败!')
    });
  };
  reader.readAsBinaryString(file.raw);
};
// 点击导入excel提交数据事件
const submitUpload = () => {
  uploadDialogVisible.value =false
}
</script>

<style scoped lang="scss">

</style>

页面效果

封装后的页面效果如下,至此,一个简单的vue前端实现Excel文件导入导出功能便开发完成了。
Vue3 exceljs库实现前端导入导出Excel,前端,excel

完整代码

gitee:https://gitee.com/cuiliang0302/vue3_vite_element-plus
github:https://github.com/cuiliang0302/vue3-vite-template

查看更多

微信公众号

微信公众号同步更新,欢迎关注微信公众号《崔亮的博客》第一时间获取最近文章。

博客网站

崔亮的博客-专注devops自动化运维,传播优秀it运维技术文章。更多原创运维开发相关文章,欢迎访问https://www.cuiliangblog.cn文章来源地址https://www.toymoban.com/news/detail-839847.html

到了这里,关于Vue3 exceljs库实现前端导入导出Excel的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3导入文件夹、导入文件、导出zip、导出

    记录一下之前项目用到的 导入文件夹 和 导入文件 出现的一些注意的点,直接上代码 注意:在传相同的文件时,会发现无法触发change事件    前端导出zip压缩包 我就用了最原始的方法axios 导出zip   因为之前也没有这样的需求 遇到过一个小问题就是,我的项目在config.js中判

    2024年02月20日
    浏览(40)
  • Vue3 导入导出Excel

    提供一个 Excel 文件,将里面的内容导出成 JSON 数组 提供一个 JSON 数组,生成 Excel 文件并下载 表格 1. 安装步骤 2.使用 3.导出 导出之后发现数据结构不是我们想要的那种,此时就能通过以下方法转换。 更改列宽 4.导入 如果excel中含有日期,需要解析时间格式的内容。 XLSL.re

    2024年02月14日
    浏览(44)
  • 基于Luckysheet实现的协同编辑在线表格支持在线导入数据库,前端导出,前端导入,后端导出

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:这里可以添加本文要记录的大概内容: 这两年,在线表格协作工具越来越火,但开源界一直没有相关的实现,被垄断在几个大厂手上,随着Luckysheet 的横空出世,开源界终于也有一个漂亮能打的在

    2024年02月11日
    浏览(59)
  • vue3前端excel导出;组件表格,自定义表格导出;Vue3 + xlsx + xlsx-style

    当画面有自定义的表格或者样式过于复杂的表格时,导出功能可以由前端实现 1. 使用的插件 : sheet.js-xlsx 文档地址:https://docs.sheetjs.com/ 中文地址:https://geekdaxue.co/read/SheetJS-docs-zh/README.md xlsx-style:https://www.npmjs.com/package/xlsx-style 2. 安装引用 安装插件-vue3 引用插件 3. 组件表格

    2024年04月26日
    浏览(39)
  • 纯前端实现 导入 与 导出 Excel

    最近经常在做 不规则 Excel 的导入,或者一些普通 Excel 的导出,当前以上说的都是纯前端来实现;下面我们来聊聊经常用到的Excel导出与导入的实现方案,本文实现技术栈以 Vue2 + JS 为例 导入分类: 调用 API 完全由后端来解析数据,清洗数据,前端只负责调用 API ; 前端解析

    2024年02月09日
    浏览(43)
  • xlsx库实现纯前端导入导出Excel

    最近做了前端导入、导出 Excel 的需求,用到了 js-xlsx 这个库,该库文档提供的用例很少,并不是很友好。本文总结一下我是如何实现需求的。 提供一个 Excel 文件,将里面的内容转成 JSON 导入数据 提供一个 JSON 文件,生成 Excel 文件并导出 导入与导出既可以前端做,也可以后

    2023年04月08日
    浏览(52)
  • Vue中如何实现Excel导入导出

    在前面员工的添加是一个一个进行的,如果一次性添加多个员工信息,这时候就会很繁琐 因此需要我们开发一个批量导入的功能,将用户的信息存储到 excel 中然后进行批量导入 1. 分析 vue-element-admin 中的导入方案 在vue-element-admin中,大佬已经封装好了Excel的导入导出方案,我

    2023年04月14日
    浏览(51)
  • SpringBoot和Vue实现Excel导入导出

    hutool工具 hutool工具 浏览器格式 打开浏览器能下载Excel即成功。 3.1 测试: 通过postman测试,send之后返回true测试成功。 在Navicat刷新,可以看到新写入的数据。

    2024年03月17日
    浏览(67)
  • vue2项目导出操作实现(后端接口导出、前端直接做导出)

    实现效果:导出列表数据 导出的内容: 后台相对来说比较简单一点,只要后端配合写接口即可 代码:放在导出事件里进行调整即可完成导出效果 效果如上:个人认为调接口导出的表格更美观一点 操作如下: 首先安装我们需要的xlxs库: 接着在我们项目文件夹/src/assets/js创建

    2024年04月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包