使用ExcelJS实现excel的前端导出功能(Vue3+TS)

这篇具有很好参考价值的文章主要介绍了使用ExcelJS实现excel的前端导出功能(Vue3+TS)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ExcelJS:读取,操作并写入电子表格数据和样式到 XLSX 和 JSON 文件。一个 Excel 电子表格文件逆向工程项目。
github中文文档:https://github.com/exceljs/exceljs/blob/master/README_zh.md

 封装excel.ts工具文件

import ExcelJS from 'exceljs'

// 导入参数数据类型
export interface importExcelType {
  // 第 i 张工作表
  i?: number;
  // 表格表头字段数组
  header: readonly any[];
}

// 导出参数数据类型
export interface exportExcelType {
  // 数据
  data: { [key: string]: any }[];
  // 文件名
  name: string;
  // 表头字段
  header: string[];
  // 表头字段对应中文
  customHeader: string[];
  // 工作表名
  sheetName?: string;
  // 标题
  title?: string;
  // 小标题
  subTitle?: string;
  // 工作表保护密码
  password?: string;
  // 对齐方式
  alignment?: Partial<ExcelJS.Alignment>;
  // 合并单元格
  mergeList?: mergeListType[];
  // 标题样式
  titleStyle?: Partial<ExcelJS.Row>;
  // 小标题样式
  subTitleStyle?: Partial<ExcelJS.Row>;
  // 表头样式
  headerStyle?: Partial<ExcelJS.Row>;
  // 单元格统一样式
  cellStyle?: Partial<ExcelJS.Row & ExcelJS.Column>;
}

// 合并单元格数据类型
export interface mergeListType {
  startRow: number;
  startColumn: number;
  endRow: number;
  endColumn: number;
}

// exceljs相关方法
export class Excel {
  blob?: Blob; // 导入的blob文件
  worksheet?: ExcelJS.Worksheet;  // 当前工作表
  header: string[]; // 表头字段数组
  constructor(blob?: Blob) {
    this.blob = blob;
    this.worksheet = undefined;
    this.header = [];
  }
  // blob转ArrayBuffer(用于后续生成文件数据)
  private readFile(): Promise<ArrayBuffer> {
    return new Promise<ArrayBuffer>((resolve, reject) => {
      let reader = new FileReader();
      if (!this.blob) {
        reject('上传文件异常!');
      } else {
        reader.readAsArrayBuffer(this.blob);
        reader.onload = (ev) => {
          resolve(ev.target!.result as ArrayBuffer);
        };
      }

    });
  }
  // 导入excel文件获取workbook(workbook属性方法参考exceljs文档)
  public async getWorkBook(): Promise<ExcelJS.Workbook> {
    let buffer = await this.readFile();
    const workbook = new ExcelJS.Workbook();
    return await workbook.xlsx.load(buffer);
  }

  // 获取第i张工作表  i 工作表序号
  public async getWorkSheet(i: number = 0): Promise<ExcelJS.Worksheet> {
    const workbook = await this.getWorkBook();
    return workbook.getWorksheet(i);
  }


  // 将 excel 第i张工作表的数据转为对象数据
  // {Promise<Record<(typeof header)[number], string>[]>}传入表头作为字段的对象数组(每个元素对象对应每一行)
  public async importExcel(options: importExcelType): Promise<Record<(typeof header)[number], string>[]> {
    const { i = 1, header } = options;
    const workbook = await this.getWorkBook();
    const worksheet = workbook.getWorksheet(i);
    // excel导入后返回的数组
    const excelList: Record<(typeof header)[number], string>[] = [];
    worksheet.getSheetValues().filter(temp => !!temp?.length).forEach(item => {  
      // 移除空行
      // 移除每行首个空元素
      (item as string[]).shift();
      // 定义临时对象存储每一行内容
      let tempObj: Record<(typeof header)[number], string> = {};
      (item as string[]).forEach((item2, index2) => {
        tempObj[header[index2]] = item2;
      })
      excelList.push(tempObj);
    })
    return excelList
  }

   // 导出excel,参数信息参考exceljs
   // data 数据
   // name 文件名
   // header 表头字段
   // customHeader 表头字段对应中文
   // sheetName 工作表名
   // title 标题
   // subTitle 副标题(日期)
   // password 冻结表格密码
   // mergeList 合并单元格数组
   // titleStyle 标题样式(按需补充方法)
   // subTitleStyle 小标题样式(按需补充方法)
   // headerStyle 表头字段样式(按需补充方法)
   // cellStyle 单元格样式(按需补充方法)

  public async exportExcel(options: exportExcelType): Promise<void> {
    const { 
        data, 
        name, 
        header, 
        customHeader, 
        sheetName = 'sheet1', 
        title = '', 
        subTitle = '', 
        password = '', 
        mergeList = [], 
        titleStyle, 
        subTitleStyle, 
        headerStyle, 
        cellStyle } = options;
    // 创建工作簿
    const workbook = new ExcelJS.Workbook();
    workbook.creator = '侃侃';
    workbook.created = new Date();
    // 添加sheet
    this.worksheet = workbook.addWorksheet(sheetName, { properties: { tabColor: { argb: 'FF00FF00' } } });
    this.header = header;
    // 表头行序号
    let headerRowId = 1;
    if (!!title) headerRowId++;
    if (!!subTitle) headerRowId++;
    // 插入单元格数据
    this.setCells(data, customHeader, cellStyle);
    // 插入大标题
    this.getTitle(title, titleStyle);
    // 插入小标题
    this.getSubTitle(subTitle, subTitleStyle);
    // 处理表头
    this.setHeaderStyle(headerRowId, data, headerStyle);
    // 更多处理
    this.handleDealExcel(password, mergeList, headerRowId);
    // 导出excel(此处也可用file-saver将blob导出到excel文件  fs.saveAs(blob, name+'.xlsx');)
    workbook.xlsx.writeBuffer().then((data) => {
      let blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = name + '.xlsx';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(a.href);
    });
  }

   // 合并单元格数组
   // merge1 需要合并的行/列起止对象数组1
   // 例:[{ startRow: 1, endRow: 1},{ startRow: 10, endRow: 10}]
   // merge2 需要合并的列/行起止对象数组2
   // 例:[{ startColumn: 1, endColumn: 2 }]
   // mergeArr 合并后数组
   // 例:[{ startRow: 1, endRow: 1, startColumn: 1, endColumn: 2},{ startRow: 10, endRow: 10, startColumn: 1, endColumn: 2}]
  public merge(merge1: Partial<mergeListType>[], merge2: Partial<mergeListType>[]): mergeListType[] {
    const mergeArr: any[] = [];
    merge1.forEach(item1 => {
      mergeArr.push(...merge2.map(item2 => {
        return { ...item2, ...item1 };
      }))
    })
    return mergeArr;
  }

   // 单元格数据处理 
   // data 表格数据
   // customHeader  表头中文字段

  private setCells(data: exportExcelType['data'], customHeader: string[], style?: Partial<ExcelJS.Row & ExcelJS.Column>): void {
    // 设置列,插入中文表头
    const column: Partial<ExcelJS.Column>[] = [];
    this.header.forEach((item, index) => {
      column.push({
        header: customHeader[index],
        key: item,
        width: style?.width || 25,
      })
    })
    this.worksheet!.columns = column;
    // 设置行,添加数据
    this.worksheet?.addRows(data);
    // 设置行高
    this.worksheet?.eachRow({ includeEmpty: true }, (row, rowNumber) => {
      row.height = style?.height || 20;
    })
    // 获取每一列数据,再依次对齐
    this.worksheet!.columns.forEach(column => {
        column.alignment = style?.alignment || { vertical: 'middle', horizontal: 'center', wrapText: true }
    })
  }

   // 添加大标题 
   // title 标题
   // style 标题样式
  private getTitle(title: string, style?: Partial<ExcelJS.Row>): void {
    if (!!title) {
      // 插入标题
      this.worksheet?.spliceRows(1, 0, [title]);
      this.worksheet?.mergeCells(1, 1, 1, this.header.length);
      // 调整标题样式
      const titleRow = this.worksheet!.getRow(1);
      // 高度
      titleRow.height = style?.height || 40;
      // 字体设置
      titleRow.font = style?.font || {
        size: 20,
        bold: true
      }
      // 背景色
      titleRow.fill = style?.fill || {
        bgColor: {
          'argb': 'FFFFFF00'
        },
        type: 'pattern',
        pattern: 'none'
      }
      // 对齐方式
      titleRow.alignment = style?.alignment || {
        horizontal: "center",
        vertical: "middle"
      };
    }
  }

   // 添加小标题 
   // subTitle 标题
   // style 小标题样式
  
  private getSubTitle(subTitle: string, style?: Partial<ExcelJS.Row>): void {
    if (!!subTitle) {
      this.worksheet?.spliceRows(2, 0, [subTitle]);
      this.worksheet?.mergeCells(2, 1, 2, this.header.length);
      // 调整标题样式
      const subtitleRow = this.worksheet!.getRow(2);
      // 高度
      subtitleRow.height = style?.height || 20;
      // 字体设置
      subtitleRow.font = style?.font || {
        size: 14,
      }
      // 背景色
      subtitleRow.fill = style?.fill || {
        bgColor: {
          'argb': 'FFFFFF00'
        },
        type: 'pattern',
        pattern: 'none'
      }
      // 对齐方式
      subtitleRow.alignment = style?.alignment || {
        horizontal: "right",
        vertical: "middle"
      };
    }
  }

   // 设置表头样式
   // num 表头在第几行
   // data 总数据
   // style 表头样式

  private setHeaderStyle(num: number, data: any, style?: Partial<ExcelJS.Row>): void {
    // 自动筛选器
    this.worksheet!.autoFilter = {
      from: {
        row: num,
        column: 1
      },
      to: {
        row: data.length,
        column: this.header.length
      }
    }
    // 给表头添加背景色
    let headerRow = this.worksheet!.getRow(num);
    headerRow!.height = style?.height || 30;
    // 通过 cell 设置背景色,更精准
    headerRow?.eachCell((cell) => {
      cell.fill = style?.fill || {
        type: 'pattern',
        pattern: 'solid',
        fgColor: { argb: 'dde0e7' },
      }
      cell.font = style?.font || {
        size: 12
      }
    })
  }
  
   // 其他内容处理
   // password 密码
   // mergeList 合并行列数组
   // headerRowId  表头行序号

  private handleDealExcel(password: string, mergeList: mergeListType[], headerRowId: number) {
    // 添加工作表保护
    if (!!password) {
      this.worksheet?.protect(password, {
        autoFilter: true,
        selectLockedCells: false,
      });
    }
    // 合并单元格
    mergeList.forEach(item => {
      // 行数为表格数据所在行行数+表头行序号headerRowId
      const startRow = item.startRow + headerRowId;
      const endRow = item.endRow + headerRowId;
      this.worksheet?.mergeCells(startRow, item.startColumn, endRow, item.endColumn);
    })
    // 冻结前几行
    this.worksheet!.views = [
      { state: 'frozen', xSplit: 0, ySplit: headerRowId }
    ];
  }
}

表格页面调用excel工具文件 文章来源地址https://www.toymoban.com/news/detail-626027.html

// export.vue
<template>
  <div class="export">
    <button @click="exportExcel">导出</button>
  </div>
</template>

<script setup lang="ts">
import { Excel, type mergeListType } from '@/utils/excel';
import { reactive } from 'vue';
const tableData = reactive([
  { id: 1, name: "张三", age: 18 },
  { id: 2, name: "张三", age: 18 }
])
const header = ['id', 'name', 'age'];
const customHeader = ['id', '姓名', '年龄'];
const mergeList: mergeListType[] = reactive([
    { startRow: 1, endRow: 2, startColumn: 3, endColumn: 3 }, 
    { startRow: 3, endRow: 5, startColumn: 3, endColumn: 3 }
])
const exportExcel = () => {
  const excel = new Excel();
  excel.exportExcel({
    name: '表格文件名称',
    title: '表格标题',
    data: tableData,
    header,
    customHeader,
    mergeList
  })
}

</script>

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

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

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

相关文章

  • #vue3 实现前端下载excel文件模板功能

    一、需求: 前端无需通过后端接口,即可实现模板下载功能。 通过构造一个 JSON 对象,使用前端常用的 第三方库 xlsx ,可以直接将该 JSON 对象转换成 Excel 文件,让用户下载模板 二、效果: 三、源码如下:

    2024年01月19日
    浏览(42)
  • vue3 excel 导出功能

    1.安装 xlsx 库 2.创建导出函数 src/utils/excelUtils.js 3.在组件中调用导出函数 4.补充: 列名替换成中文

    2024年02月13日
    浏览(25)
  • vue3中的excel表导出功能(选中导出或导出所有,也可支持vue2)

    1.安装模块 npm install xlsx file-saver -S 2.文件导入 import * as XLSX from \\\"xlsx\\\"; import FileSaver from \\\"file-saver\\\" 3.整体代码(可选中导出或导出所有) id绑定表格全部导出 4.效果如下        

    2024年02月17日
    浏览(29)
  • 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日
    浏览(30)
  • vue 实现导出 Excel功能

    例如,创建一个文件夹命名为 utils ,再创建一个导出Excel的js文件 exportExcel.js 当渲染的table数据中有操作按钮或者有一些不需要的字段的话,可以写一个打印模板,用作导出Excel功能

    2024年02月12日
    浏览(27)
  • vue 实现前端处理 “数组数据“ 转excel格式文件,并导出excel表格

    一、安装插件 XLSX 二、页面引入        希望我的愚见能够帮助你哦~,若有不足之处,还望指出,你们有更好的解决方法,欢迎大家在评论区下方留言支持,大家一起相互学习参考呀~

    2024年01月18日
    浏览(39)
  • vue+xlsx实现前端模版下载、导入和导出excel文件

    产品需求:后端不想写下载,导入和导出的接口,让我们前端自己实现。 这里我们就可以用xlsx插件来实现,我们不多说了,先放一下实现的图片,下面我们分别把模版下载、导入和导出的代码放上来,想用的话,直接复制粘贴即可! 模版下载图片 导出图片: 好了,下面我

    2024年02月13日
    浏览(34)
  • 后端接口返回文件流,前端实现docx/pdf/excel等类型文件的导出功能

    最近遇到一个需求,在后端返回文件流后前端需要实现导出docx类型的文件。在网上查看了一些资料总结了两种比较常用的方法。 1、封装接口 注意:接口需要添加 responseType: “blob”,否则会出现文件下载后无法打开或者损坏的情况。 2、转换数据格式 导出word文件,需要在创

    2024年01月21日
    浏览(31)
  • Node.js @zurmokeeper/exceljs 如何快速导出多表头的excel文件

    Node.js 如何快速导出嵌套列(多表头)的excel文件。效果图如下: 1:使用 @zurmokeeper/exceljs, V4.4.1以上 安装: npm i @zurmokeeper/exceljs 2: 有一个 worksheet.makeColumns 方法,API文档: 代码示例:

    2024年02月10日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包