前端导出数据到Excel(Excel.js导出数据)

news2024/11/16 12:05:13

库:Excel.js(版本4.3.0) 和 FileSaver(版本2.0.5)

CDN地址:

<script src="https://cdn.bootcdn.net/ajax/libs/exceljs/4.3.0/exceljs.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.js"></script>

Excel.js 中文文档:https://gitee.com/alan_scut/exceljs

先看一下效果吧
在这里插入图片描述

代码:

使用方法: exportExcal()

// 住宿安排(动态列)
var stay_arr = ['27日晚', '28日晚'];
// 内容数据
var test_data = [
  {
    "guest": "生态伙伴",
    "name": "姓名一",
    "sex": "男",
    "company": "AAAAAA股份有限公司",
    "job": "业务部部长",
    "phone": "12345678912",
    "stay": ["28日晚"]
  },
  {
    "guest": "生态伙伴",
    "name": "姓名二",
    "sex": "女",
    "company": "AAAAAA股份有限公司",
    "job": "业务部部长",
    "phone": "12345678912",
    "stay": ["27日晚","28日晚",]
  }
];
// 导出Excel
function exportExcal() {
  // 文件名称
  var fileName = 'simple.xlsx';
  // 固定内容的列数
  var basic_col_num = 7;
  // 总列数(固定列+住宿动态列的长度)
  var all_column_num = basic_col_num + stay_arr.length;
  // 表单数据数组
  var data_arr = [];
  // 数据单元格起始行数
  var rowStart = 4;
  // 基础单元格边框样式
  var borderStyle = {
    top: { style: "thin", color: { argb: "FF000000" } },
    left: { style: "thin", color: { argb: "FF000000" } },
    bottom: { style: "thin", color: { argb: "FF000000" } },
    right: { style: "thin", color: { argb: "FF000000" } },
  }
  // 基础内容对齐方式
  var basicAlignment = { vertical: 'middle', horizontal: 'center', wrapText: true };
  // 新建工作簿
  var wb = new ExcelJS.Workbook();
  // 设置工作簿属性
  wb.creator = 'Me';                      // 作者
  wb.lastModifiedBy = 'Her';              // 最后修改人
  wb.created = new Date(2023, 10, 10);     // 创建时间
  wb.modified = new Date();               // 修改时间
  wb.lastPrinted = new Date(2023, 10, 10); // 上次打印文档时间
  wb.properties.date1904 = true;          // 将工作簿日期设置为1904日期系统

  // 向新的工作簿中增加一张工作表
  var ws = wb.addWorksheet('邀约名单');
  // 设置默认行高
  ws.properties.defaultRowHeight = 20;
  // 也可以在添加工作表的时候直接设置参数
  // var ws = wb.addWorksheet('邀约名单', {properties:{defaultRowHeight:20}});

  // 表头部分开始

  // 设置单元格第一行
  // 获取单元格内第一行
  var collectRow = ws.getRow(1);
  // 设置单行行高
  collectRow.height = 40;
  // 设置整行的文字样式
  collectRow.style.font = { name: 'Microsoft YaHei', size: 16, bold: true, color: { argb: "ffffffff" } };
  // 设置整行内容对齐方式
  collectRow.alignment = basicAlignment;
  // 获取A1单元格
  var collectcell = ws.getCell(`A1`);
  // 表格第一行标题内容,A1合并后填充的内容
  collectcell.value = `参会信息统计表`;
  // 设置单个单元格的背景色(这里不能设置整行,因为会超出数据的宽度)
  collectcell.fill = {
    type: "pattern",
    pattern: "solid",
    fgColor: { argb: "ff538dd5" },
  }
  // 设置单个单元格的边框样式
  collectcell.border = {
    top: { style: "thin", color: { argb: "FF000000" } },
    left: { style: "thin", color: { argb: "FF000000" } },
    right: { style: "thin", color: { argb: "FF000000" } },
  };
  // 合并单元格,将A1与H1合并(ws.mergeCells(`A1:H1`);)
  ws.mergeCells(`A1:${getLetter(all_column_num)}1`);

  // 设置单元格第二行
  // 获取单元格内第二行
  var collectRow = ws.getRow(2);
  // 设置单行行高
  collectRow.height = 26;
  // 获取A2单元格
  var collectcell2 = ws.getCell(`A2`);
  // 表格第二行标题内容,A2合并后填充的内容
  collectcell2.value = `活动时间:2023年10月10日        活动地点:XXXXXXX会议中心        住宿酒店:XXXX酒店`;
  // 单独设置单元格的文字样式
  collectcell2.font = { name: 'Microsoft YaHei', size: 10, bold: false, color: { argb: "ffffffff" } }; // 字体
  // 单独设置单元格的背景色
  collectcell2.fill = {
    type: "pattern",
    pattern: "solid",
    fgColor: { argb: "ff538dd5" },
  }
  // 单独设置单元格的内容对齐方式
  collectcell2.alignment = basicAlignment;
  // 单独设置单元格的边框样式
  collectcell2.border = {
    left: { style: "thin", color: { argb: "FF000000" } },
    bottom: { style: "thin", color: { argb: "FF000000" } },
    right: { style: "thin", color: { argb: "FF000000" } },
  };
  // 合并单元格,将A2与H2合并(ws.mergeCells(`A2:H2`);)
  ws.mergeCells(`A2:${getLetter(all_column_num)}2`);

  // 处理表单第三行第四行每个单元格表头内容
  for (let i = 1; i <= all_column_num; i++) {
    let r3cell = ws.getCell(`${getLetter(i)}3`); // 获取第三行的单元格
    let r4cell = ws.getCell(`${getLetter(i)}4`); // 获取第三行的单元格

    // 设置内容对齐方式
    r3cell.alignment = basicAlignment;
    r4cell.alignment = basicAlignment;

    // 前面部分固定内容的表头设置
    if (i <= basic_col_num) {
      // 设置单元格样式
      r3cell.border = borderStyle;
      r3cell.fill = {
        type: "pattern",
        pattern: "solid",
        fgColor: { argb: "ff808080" },
      }
      r3cell.font = { name: 'Microsoft YaHei', size: 11, bold: true, color: { argb: "ffffffff" } };

      switch (i) {
        case 1:
          ws.getCell(`${getLetter(i)}3`).value = "序号";
          // 设置单元格宽度(宽度单位是字符宽度,而不是像素宽度,中文是两个字符)
          ws.getColumn(i).width = 6;
          break;
        case 2:
          ws.getCell(`${getLetter(i)}3`).value = "嘉宾类别";
          ws.getColumn(i).width = 16;
          break;
        case 3:
          ws.getCell(`${getLetter(i)}3`).value = "姓名";
          ws.getColumn(i).width = 10;
          break;
        case 4:
          ws.getCell(`${getLetter(i)}3`).value = "性别";
          ws.getColumn(i).width = 6;
          break;
        case 5:
          ws.getCell(`${getLetter(i)}3`).value = "单位";
          ws.getColumn(i).width = 40;
          break;
        case 6:
          ws.getCell(`${getLetter(i)}3`).value = "职务";
          ws.getColumn(i).width = 24;
          break;
        case 7:
          ws.getCell(`${getLetter(i)}3`).value = "手机号";
          ws.getColumn(i).width = 15;
          break;
      }
      // 合并上下对应的单元格
      ws.mergeCells(`${getLetter(i)}3:${getLetter(i)}4`);
    } else {
      // 这部分是动态的单元格
      // 设置单元格宽度
      ws.getColumn(i).width = 12;
      // 住宿部分表头样式需要分开设置(因为不合并)
      r3cell.border = borderStyle;
      r3cell.fill = {
        type: "pattern",
        pattern: "solid",
        fgColor: { argb: "ffebf1de" },
      }
      r4cell.border = borderStyle;
      r4cell.fill = {
        type: "pattern",
        pattern: "solid",
        fgColor: { argb: "ffebf1de" },
      }
      r4cell.font = { name: 'Microsoft YaHei', size: 11, bold: true, color: { argb: "ff595959" } };

      // 住宿第三行的内容
      if (i == (basic_col_num + 1)) {
        ws.getCell(`${getLetter(i)}3`).value = "行程安排";
        // 合并单元格(行程安排)
        ws.mergeCells(`${getLetter(i)}3:${getLetter(i + stay_arr.length - 1)}3`);
      }
      // 设置住宿列第四行的动态内容
      ws.getCell(`${getLetter(i)}4`).value = stay_arr[i - basic_col_num - 1];
    }
  }
 
  // 处理表单数据
  for (let i = 0; i < test_data.length; i++) {
    // 序号,嘉宾类别,姓名,性别,单位,职务,手机号
    data_arr[i] = [
      i + 1,
      test_data[i].guest,
      test_data[i].name,
      test_data[i].sex,
      test_data[i].company,
      test_data[i].job,
      test_data[i].phone
    ]
    // 动态添加住宿(循环住宿内容数组)
    for (let j = 0; j < stay_arr.length; j++) {
      if (test_data[i].stay) {
        // 判断该值是否是列表中数据内存在的值
        if (test_data[i].stay.indexOf(stay_arr[j]) != -1) {
          data_arr[i].push("是");
        } else {
          data_arr[i].push("");
        }
      } else {
        // 如果没有住宿,直接添加空
        data_arr[i].push("");
      }
    }
  }
 
  // 将表单输入插入行
  for (let i = 0; i < data_arr.length; i++) {
    // 获取数据行
    let r_data = ws.getRow(i + rowStart + 1);
    // 设置整行单元格的内容对其方式
    r_data.alignment = basicAlignment;
    // 字体
    r_data.font = { name: 'Microsoft YaHei', size: 11, bold: false, color: { argb: "ff000000" } };
    // 设置整行的数据内容
    r_data.values = data_arr[i];
    // 循环本行插入的每个单元格,然后给单元格设置边框样式(注意,一定要插入数据后,才能循环设置)
    // 这里不能用 设置整行边框,因为单元格会超出,不好看了
    r_data.eachCell({ includeEmpty: true }, function (cell, colNumber) {
      ws.getCell(`${getLetter(colNumber)}${i + rowStart + 1}`).border = borderStyle
    });
  }
 
  // node端才能使用
  // wb.xlsx.writeFile(fileName).then(() => {
  //   console.log('file created');
  // }).catch(err => {
  //   console.log(err.message);
  // });

  wb.xlsx.writeBuffer().then(buffer => {
    // 这里之前是 FileSaver.saveAs 因为报错换成 window.saveAs 原因文章后面有说
    window.saveAs(new Blob([buffer], { type: 'application/octet-stream' }), `${fileName || 'excel.xlsx'}`);
  })
}

// 获取第N个字母
function getLetter(num) {
  return String.fromCharCode(64 + num);
}

代码中用到的方法总结:

新建工作簿 & 向工作簿中增加一张工作表

var workbook = new ExcelJS.Workbook();
var worksheet = workbook.addWorksheet(‘邀约名单’);

合并单元格(将A1与H1合并)

worksheet.mergeCells(‘A1:H1’);

获取行(第一行)

var collectRow = worksheet.getRow(1);

获取列(B或者3)

var collectcell = worksheet.getColumn(‘B’);
var collectcell = worksheet.getColumn(3);

获取单元格(A2)

var collectcell = worksheet.getCell(‘A2’);

设置单元格内容(行、列、单元格均可设置。行、列是赋值数组)

var collectcell = worksheet.getCell(‘A2’);
collectcell.value = ‘活动时间’;

设置单元格宽度(列、单元格均可设置。宽度单位是字符宽度,而不是像素宽度,中文是两个字符。)

var collectcell = worksheet.getCell(‘A2’);
collectcell.width = 6;

设置工作表的默认行高

worksheet.properties.defaultRowHeight = 20;

设置工作表的默认列宽

worksheet.properties.defaultColWidth = 50;

设置文字样式(行,列,单元格均可设置)

var collectcell = worksheet.getCell(‘A2’);
collectcell.font = { name: ‘Microsoft YaHei’, size: 10, bold: false, color: { argb: “ffffffff” } };

设置背景色(行,列,单元格均可设置)

var collectcell = worksheet.getCell(‘A2’);
collectcell.fill = { type: “pattern”, pattern: “solid”, fgColor: { argb: “ff538dd5” } };

设置内容对齐方式(行,列,单元格均可设置)

var collectcell = worksheet.getCell(‘A2’);
collectcell.alignment = {
top: { style: “thin”, color: { argb: “FF000000” } },
left: { style: “thin”, color: { argb: “FF000000” } },
bottom: { style: “thin”, color: { argb: “FF000000” } },
right: { style: “thin”, color: { argb: “FF000000” } },
}

循环行内的每一个单元格(包括空单元格)

let r_data = ws.getRow(i + rowStart + 1);
// 循环本行插入的每个单元格,然后给单元格设置边框样式(注意,一定要插入数据后,才能循环设置)
r_data.eachCell({ includeEmpty: true }, function (cell, colNumber) {
console.log('Cell ’ + colNumber + ’ = ’ + cell.value);
});

遇见的一些问题:

1. 报错:FileSaver.saveAs is not a function.saveAs is not a function
解决方法: 将 FileSaver.saveAs 改成 window.saveAs 即可(原因是 FileSaver 是全局引用了)

2. 为什么不直接用 wb.xlsx.writeFile
答:因为 wb.xlsx.writeFile 只能 node 用,所以需要用 FileSaver

3. eachCell 为什么会无效(不进入循环)
答:一定要插入数据后,才能循环,没有插入数据的时候是无法进入循环的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1116236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RHCE---搭建博客网站

一.实验要求&#xff1a; Server-NFS-DNS主机配置NFS服务器&#xff0c;将博客网站资源文件共享给Server-web主机&#xff0c;Server-NFS-DNS主机配置DNS Server-web主机配置web服务&#xff0c;通过域名www.openlab.com可以访问到自建的博客网站 二.准备工作 创建两台虚拟机…

C++设计模式_09_Abstract Factory 抽象工厂

与上篇介绍的Factory Method工厂方法模式一样&#xff0c;Abstract Factory 抽象工厂模式也属于典型的“对象创建模式”模式&#xff0c;解决的问题也极其相似&#xff0c;在理解了Factory Method工厂方法模式的基础上再去理解Abstract Factory 抽象工厂模式就会变得更加容易。…

飞书-多维文档-计算时间差

1. 选择字段类型 如图所示&#xff0c;字段类型选择 公式 2. 编辑公式 单击 公式编辑器 在弹出的公式编辑框中输入公式 TEXT([终结时间]-[开始时间],"HH:MM") [终结时间] 和 [开始时间] 请替换成你的表格中对应的字段名称HH:MM 表示输出的时间格式为 时:分其中 “…

如何理解TCP/IP协议?

一、是什么 TCP/IP&#xff0c;传输控制协议/网际协议&#xff0c;是指能够在多个不同网络间实现信息传输的协议簇 TCP&#xff08;传输控制协议&#xff09; 一种面向连接的、可靠的、基于字节流的传输层通信协议 IP&#xff08;网际协议&#xff09; 用于封包交换数据网…

npm常用命令与操作篇

npm简介 npm是什么 npm 的英文是&#xff0c;node package manager&#xff0c;是 node 的包管理工具 为什么需要npm 类比建造汽车一样&#xff0c;如果发动机、车身、轮胎、玻璃等等都自己做的话&#xff0c;几十年也做不完。但是如果有不同的厂商&#xff0c;已经帮我们把…

《windows核心编程》第1章 错误处理

一、错误信息的获取 1.1 C库错误信息 1、获取错误信息 #include <stdio.h> #include <stdlib.h> #include <string.h>int main() {fopen("D:\\ASC", "r");printf("%s\n", strerror(errno));getchar();return 0; } 2、设置错…

nodejs+vue 校园通勤车-计算机毕业设计

在此情况下开发一款校园通勤车可视化系统小程序&#xff0c;于是乎变得非常合乎时宜。 经过网上调查和搜集数据,我们可以发现校园通勤车可视化管理方面的小程序在并不是相当普及,同时在校园通勤车可视化管理方面的可以有许多改进。目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪…

Android切换主题生命周期流程与onSaveInstanceState和onRestoreInstanceState,Kotlin

Android切换主题生命周期流程与onSaveInstanceState和onRestoreInstanceState&#xff0c;Kotlin import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivityclass MainActivity : AppCompatActivity() {private val TAG "fly&…

基于nodejs+vue 校园通勤车系统

但是管理好校园通勤车可视化又面临很多麻烦需要解决, 信息化已经成为主流,开发一个校园通勤车可视化系统小程序一方面的可能会更合乎时宜,困扰管理层的许多问题当中,校园通勤车 管理也是不敢忽视的一块。另一方面来说也可以提高在校园通勤车可视化管理方面的效率给相关管理人员…

【力扣周赛】第 367 场周赛(⭐二维数组当成一维数组,前后缀分解)

文章目录 竞赛链接Q1&#xff1a;100096. 找出满足差值条件的下标 I竞赛时代码——暴力双循环 Q2&#xff1a;100084. 最短且字典序最小的美丽子字符串竞赛时代码——双指针 Q3&#xff1a;100101. 找出满足差值条件的下标 II竞赛时代码——记录可用最大最小值下标 Q4&#xff…

MATLAB模拟的电磁学时域有限差分法(电子书PDF)

摘要: MATLAB语言具有编程简单&#xff0c;并可以给出精美图像的特点&#xff0c;它已成为理工科大学生必备的系统工具平台。其完备的工具箱功能&#xff0c;使得MATLAB日益受到大学生和工程师们的喜爱。《MATLAB模拟的电磁学时域有限差分法》 目录 第1章 FDTD简介 1.1 时域有限…

Bootstrap的列表组相关知识

目录 01-列表组的相关基础知识02-一个简单的列表组示例03-激活或禁用列表组的一行或多行04-设置列表项的颜色05-给列表项添加徽章 01-列表组的相关基础知识 Bootstrap的list-group是一个用于创建列表组件的CSS类&#xff0c;通常用于显示一个项目列表&#xff0c;如导航菜单或…

Spark内核

环境准备及提交流程 底层通信协议 Akka通信协议&#xff0c;收发邮箱是一体的Netty通信协议&#xff0c;收发邮箱是分开的 任务调度 任务的最小单位是线程。失败重试&#xff0c;会记录失败的次数&#xff0c;如果超过最大重试次数&#xff0c;宣告Application失败。失败的…

knife4j-openapi3 无法使用swagger注解@ApiModelProperty

问题描述 当使用knife4j springboot3&#xff0c; 发现无法使用 swagger注解ApiModelProperty需要单独导入一个包但是即使导入这个包也不生效&#xff0c;即使配置了description也为空 原因 简单来说&#xff1a;swagger2 > swagger3的时候出现了破坏性的更新 将ApiMode…

Docker(五)、容器间数据共享~volume

容器间数据共享&#xff5e;volume 一、简单了解二、有两种通过命令设置数据卷的方法一&#xff09;、方式1. 通过 -v 挂载宿主机目录1、格式2、浅实践下 二&#xff09;、方式2.实现形式&#xff1a;通过共享容器内挂载点--volumes-from&#xff0c;其他容器指定此挂载点1、格…

基于nodejs+vue中学信息技术线上学习系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Java操作Elasticsearch(新增数据)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

vscode使用CSScomb插件

1. 安装 在设置中搜索csscomb&#xff0c;把Csscomb: Format On Save勾上 然后去edit in settings.json配置 2.使用 2.1 用官网提供的三种方法 https://github.com/csscomb/csscomb.js/tree/master/config 2.2 自定义 CSS 书写顺序规则可以参考这个荐腾讯 AollyTeam 团队的…

CI2454 2.4g无线MCU芯片应用

Ci2454集成MCU芯片 | Ci2454是一款集成无线收发器和 8 位 RISC&#xff08;精简指令集&#xff09;MCU 的SOC芯片。 #Ci2454芯片 集成MCU芯片# 中国芯片# 无线收发器特性&#xff1a; 工作在 2.4GHz ISM 频段 调制方式&#xff1a;GFSK/FSK 数据速率&#xff1a;2Mbps/1Mbps…

交换机控制在同一个网段内的终端,用hybrid接口实现不同的IP通和不通。

实验效果&#xff1a;pc1和pc2不能通&#xff0c;但pc1和pc2分别可以和pc3通。 通过这个实验可以彻底掌握数据包在交换机上的进去的类型状态。 sw1配置&#xff1a; [sw1]dis current-configuration sysname sw1 vlan batch 10 20 100 interface GigabitEthernet0/0/1 port h…