如何使用JavaScript实现纯前端读取和导出excel文件

article/2025/3/5 4:35:22

js-xlsx 介绍

由SheetJS出品的js-xlsx是一款非常方便的只需要纯JS即可读取和导出excel的工具库,功能强大,支持格式众多,支持xlsxlsxods(一种OpenOffice专有表格文件格式)等十几种格式。本文全部都是以xlsx格式为例。

  • 官方github:GitHub - SheetJS/sheetjs: SheetJS Community Edition -- Spreadsheet Data Toolkit
  • 本文配套demo在线演示地址:JS读取和导出excel示例
  • 本文同步首发于我的个人博客和博客园。

1.1. 兼容性

兼容性如下图:

1.2. 如何使用

dist目录下有很多个JS文件,一般情况下用xlsx.core.min.js就够了,xlsx.full.min.js则是包含了所有功能模块。

直接script标签引入即可:

<script type="text/javascript" src="./js/xlsx.core.min.js"></script>

读取excel

读取excel主要是通过XLSX.read(data, {type: type});方法来实现,返回一个叫WorkBook的对象,type主要取值如下:

  • base64: 以base64方式读取;
  • binary: BinaryString格式(byte n is data.charCodeAt(n))
  • string: UTF8编码的字符串;
  • buffer: nodejs Buffer;
  • array: Uint8Array,8位无符号数组;
  • file: 文件的路径(仅nodejs下支持);

2.1. 获取workbook对象

2.1.1. 读取本地文件

直接上代码:

// 读取本地excel文件
function readWorkbookFromLocalFile(file, callback) {var reader = new FileReader();reader.onload = function(e) {var data = e.target.result;var workbook = XLSX.read(data, {type: 'binary'});if(callback) callback(workbook);};reader.readAsBinaryString(file);
}

2.1.2. 读取网络文件

// 从网络上读取某个excel文件,url必须同域,否则报错
function readWorkbookFromRemoteFile(url, callback) {var xhr = new XMLHttpRequest();xhr.open('get', url, true);xhr.responseType = 'arraybuffer';xhr.onload = function(e) {if(xhr.status == 200) {var data = new Uint8Array(xhr.response)var workbook = XLSX.read(data, {type: 'array'});if(callback) callback(workbook);}};xhr.send();
}

2.2. 详解 workbook

2.2.1. Workbook Object

workbook里面有什么东西呢,我们打印出来看一下:

可以看到,SheetNames里面保存了所有的sheet名字,然后Sheets则保存了每个sheet的具体内容(我们称之为Sheet Object)。每一个sheet是通过类似A1这样的键值保存每个单元格的内容,我们称之为单元格对象(Cell Object):

2.2.2. Sheet Object

每一个Sheet Object表示一张表格,只要不是!开头的都表示普通cell,否则,表示一些特殊含义,具体如下:

  • sheet['!ref']:表示所有单元格的范围,例如从A1到F8则记录为A1:F8
  • sheet[!merges]:存放一些单元格合并信息,是一个数组,每个数组由包含se构成的对象组成,s表示开始,e表示结束,r表示行,c表示列;
  • 等等;

关于单元格合并,看懂下面这张图基本上就没问题了:

结果如下:

2.2.3. 单元格对象

每一个单元格是一个对象(Cell Object),主要有tvrhw等字段(详见这里):

  • t:表示内容类型,s表示string类型,n表示number类型,b表示boolean类型,d表示date类型,等等
  • v:表示原始值;
  • f:表示公式,如B2+B3
  • h:HTML内容
  • w:格式化后的内容
  • r:富文本内容rich text
  • 等等

2.2.4. 读取workbook

普通方法:

// 读取 excel文件
function outputWorkbook(workbook) {var sheetNames = workbook.SheetNames; // 工作表名称集合sheetNames.forEach(name => {var worksheet = workbook.Sheets[name]; // 只能通过工作表名称来获取指定工作表for(var key in worksheet) {// v是读取单元格的原始值console.log(key, key[0] === '!' ? worksheet[key] : worksheet[key].v);}});
}

根据!ref确定excel的范围,再根据!merges确定单元格合并(如果有),最后输出整个table,比较麻烦,幸运的是,插件自身已经写好工具类XLSX.utils给我们直接使用,无需我们自己遍历,工具类输出主要包括如下:

有些不常用,常用的主要是:

  • XLSX.utils.sheet_to_csv:生成CSV格式
  • XLSX.utils.sheet_to_txt:生成纯文本格式
  • XLSX.utils.sheet_to_html:生成HTML格式
  • XLSX.utils.sheet_to_json:输出JSON格式

常用的主要是sheet_to_csv或者sheet_to_html,转csv的话会忽略格式、单元格合并等信息,所以复杂表格可能不适用。转html的话会保留单元格合并,但是生成的是<html></html>代码,而不是<table></table>,需要对表格进行一些定制时不太方便,所以具体还是要视情况来采用合适的工具类。

这里写一个采用转csv方式输出结果的简单示例,可点击这里查看在线DEMO:

function readWorkbook(workbook)
{var sheetNames = workbook.SheetNames; // 工作表名称集合var worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheetvar csv = XLSX.utils.sheet_to_csv(worksheet);document.getElementById('result').innerHTML = csv2table(csv);
}// 将csv转换成简单的表格,会忽略单元格合并,在第一行和第一列追加类似excel的索引
function csv2table(csv)
{var html = '<table>';var rows = csv.split('\n');rows.pop(); // 最后一行没用的rows.forEach(function(row, idx) {var columns = row.split(',');columns.unshift(idx+1); // 添加行索引if(idx == 0) { // 添加列索引html += '<tr>';for(var i=0; i<columns.length; i++) {html += '<th>' + (i==0?'':String.fromCharCode(65+i-1)) + '</th>';}html += '</tr>';}html += '<tr>';columns.forEach(function(column) {html += '<td>'+column+'</td>';});html += '</tr>';});html += '</table>';return html;
}

导出excel

导出分为2种,一种是基于现有excel修改,一种是全新生成,前者比较简单,我们这里着重讲后者。

3.1. 自己手写代码生成

导出excel文件,主要是如何生成一个sheet,我们这里写一个最简单的csv转excel示例:

// csv转sheet对象
function csv2sheet(csv) {var sheet = {}; // 将要生成的sheetcsv = csv.split('\n');csv.forEach(function(row, i) {row = row.split(',');if(i == 0) sheet['!ref'] = 'A1:'+String.fromCharCode(65+row.length-1)+(csv.length-1);row.forEach(function(col, j) {sheet[String.fromCharCode(65+j)+(i+1)] = {v: col};});});return sheet;
}// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(sheet, sheetName) {sheetName = sheetName || 'sheet1';var workbook = {SheetNames: [sheetName],Sheets: {}};workbook.Sheets[sheetName] = sheet;// 生成excel的配置项var wopts = {bookType: 'xlsx', // 要生成的文件类型bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性type: 'binary'};var wbout = XLSX.write(workbook, wopts);var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});// 字符串转ArrayBufferfunction s2ab(s) {var buf = new ArrayBuffer(s.length);var view = new Uint8Array(buf);for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;return buf;}return blob;
}

拿到上面的blob对象就可以直接下载了,参考我之前在JS弹出下载对话框里面封装好的openDownloadDialog方法:

/*** 通用的打开下载对话框方法,没有测试过具体兼容性* @param url 下载地址,也可以是一个blob对象,必选* @param saveName 保存文件名,可选*/
function openDownloadDialog(url, saveName)
{if(typeof url == 'object' && url instanceof Blob){url = URL.createObjectURL(url); // 创建blob地址}var aLink = document.createElement('a');aLink.href = url;aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效var event;if(window.MouseEvent) event = new MouseEvent('click');else{event = document.createEvent('MouseEvents');event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);}aLink.dispatchEvent(event);
}

所以,最终下载实现如下:

// 传入csv,执行后就会弹出下载框
function exportExcel(csv) {var sheet = csv2sheet(csv);var blob = sheet2blob(sheet);openDownloadDialog(blob, '导出.xlsx');
}

3.2. 利用官方工具类生成

其实上面这些代码都不需要我们手写,官方已经提供好了现成的工具类给我们使用,主要包括:

  • aoa_to_sheet: 这个工具类最强大也最实用了,将一个二维数组转成sheet,会自动处理number、string、boolean、date等类型数据;
  • table_to_sheet: 将一个table dom直接转成sheet,会自动识别colspanrowspan并将其转成对应的单元格合并;
  • json_to_sheet: 将一个由对象组成的数组转成sheet;

aoa_to_sheet示例:

var aoa = [['姓名', '性别', '年龄', '注册时间'],['张三', '男', 18, new Date()],['李四', '女', 22, new Date()]
];
var sheet = XLSX.utils.aoa_to_sheet(aoa);
openDownloadDialog(sheet2blob(sheet), '导出.xlsx');

table_to_sheet就更简单了,直接XLSX.utils.table_to_sheet($('table')[0])即可;

3.3. 处理单元格合并

一般来说,前端生成excel而不是csv最主要目的都是为了解决csv不能实现单元格合并的问题,要不然直接导出csv文件就好了,何必引入几百kb的插件。

假设我们要生成如下格式的excel文件,其中A1-C1进行单元格合并:

代码如下:

var aoa = [['主要信息', null, null, '其它信息'], // 特别注意合并的地方后面预留2个null['姓名', '性别', '年龄', '注册时间'],['张三', '男', 18, new Date()],['李四', '女', 22, new Date()]
];
var sheet = XLSX.utils.aoa_to_sheet(aoa);
sheet['!merges'] = [// 设置A1-C1的单元格合并{s: {r: 0, c: 0}, e: {r: 0, c: 2}}
];
openDownloadDialog(sheet2blob(sheet), '单元格合并示例.xlsx');

需要注意的地方就是被合并的单元格要用null预留出位置,否则后面的内容(本例中是第四列其它信息)会被覆盖。


http://chatgpt.dhexx.cn/article/tawEObJW.shtml

相关文章

使用JavaScript实现纯前端读取excel文件并与后台进行交互

下载SheetJS文件 GitHub下载地址&#xff1a;https://github.com/SheetJS/sheetjs 下载之后打开其中的dist文件目录&#xff0c;能看到其中有xlsx.core.min.js和xlsx.full.min.js两个JS文件&#xff0c;使用其中一个文件就行&#xff0c;一般情况下使用xlsx.core.min.js就可以…

学习写需求分析

笔者本身是软件工程专业出身&#xff0c;但是对如何写需求分析仍然是一知半解&#xff0c;拿到需求&#xff0c;仍然不知道如何下手&#xff0c;才能达到写需求分析的目的。 今天看到一篇文章&#xff0c;让我受益良多&#xff0c;同时参考此文&#xff0c;笔者也尝试写了一个…

Java Web 课程设计需求分析文档

企业办公软件管理需求分析 一、引言 1.1编写目的 软件需求分析是为了使用户和软件开发人员双方对该软件的初始规定有一个共同的理解,使之成为整个软件开发工作的基础.就本项目而言&#xff0c;编写需求分析报告的主要目的是明确系统各部分需要完成的功能&#xff0c;了解系统…

易语言游戏辅助开发原理分析

外挂现在大体上来讲分为三种&#xff0c;分别是模拟按键&#xff0c;WPE封包和内存挂。比如模拟键盘的&#xff0c;鼠标的&#xff0c;这种就叫做按键模拟&#xff0c;也叫脚本精灵&#xff1b;还有修改数据包的&#xff0c;这种就叫做WPE封包外挂&#xff0c;这种外挂相对而言…

Python新手开发的飞机大战

飞机大战import pygame import random import math # 数学模块# 初始化界面 pygame.init() # 设置窗口大小 windows pygame.display.set_mode((800, 600)) # 设置窗口标题 pygame.display.set_caption("小赵同学") # 引入图片 logo icon pygame.image.load(logo.j…

【Python游戏开发】百行Python代码开发出飞机大战小游戏,原来Python可以这么强大

大家好&#xff0c;今天给大家介绍一个小项目&#xff0c;只用一百行代码就可以开发出的游戏。 安装pygame 下载对应python版本的pygame 运行以下命令 创建Pygame窗口及响应用户输入 新建一个文件夹alien_invasion&#xff0c;并在文件夹中新建alien_invasion.py文件&#x…

终极PK | Python相较于Java的优势在哪里?

首先为避免引战&#xff0c;我要强调&#xff0c;“无论是Python还是Java都是目前主流的编程语言&#xff0c;没有好坏之分&#xff0c;有的只是应用场景不同&#xff0c;Python和Java都是世界上最好的语言&#xff01;” 接下来我们从语言本身、应用场景以及流行趋势等多个方…

【编程项目开源】仿微信飞机大战(Python版)

背景 前面已输出多个系列&#xff1a; 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 《N种编程语言做个记事本》 《N种编程语言做个应用市场(appstore)》 《N种编程语…

Java太难,我选python?一个工具,带你开启新世界大门

前不久&#xff0c;4月份十大编程语言排行榜新鲜出炉。据TIOBE公布的数据来看&#xff0c;较上个月&#xff0c;TOP5基本没什么变化。Java稳居第一&#xff0c;随后是C、python、C、C#。 可是&#xff0c;有研究表明&#xff0c;十大难学编程语言中&#xff0c;Java排第3&…

用python编写飞机大战

博主介绍&#xff1a;是一名刚来到CSDN的小萌新 飞机大战 效果显示代码实现领取代码资源 效果显示 代码实现 领取代码资源 效果显示 代码实现 # -*- coding: utf-8 -*- import pygame # 导入pygame库 from pygame.locals import * # 导入pygame库中的一些常量 …

python云计算有哪些岗位,华为python教程下载

本篇文章给大家谈谈华为python语言通用编程规范&#xff0c;以及python云计算有哪些岗位&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 摘要&#xff1a;以 相反的顺序反转和处理字符串可能是编程中的一项常见任务。Python 提供了一组工具和技术&#xff0c…

java和python哪个功能更好,java和python哪个更有前景

大家好&#xff0c;本文将围绕java和python哪个更有发展前景展开说明&#xff0c;java和python哪个功能更好是一个很多人都想弄明白的事情&#xff0c;想搞清楚java和python哪个更有前景需要先了解以下几个事情。 java语言和python语言发展前景哪个好? 【导语】众所周知&#…

用Python写了一个网易云,太强了(附源码)

前言 今天的项目太强了&#xff0c;用 Python 整出一个网易云来&#xff0c;实现音乐自由&#xff01; 环境 Python3.6.8 PyCharm 依赖包 PyQt5&#xff1a;用于图形界面的开发 shelve&#xff1a;用于序列化对象 requests&#xff1a;爬取数据 功能展示 根据关键词&…

java和python哪个更有前景,java和python哪个有前途

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;java和python哪个更有前景&#xff0c;java和python哪个有前途&#xff0c;今天让我们一起来看看吧&#xff01; 前言 如今开发编程行业的发展迅猛&#xff0c;it技术的更新迭代十分快速&#xff0c;社会发展的方方面面…

【Python】Java工程师学Python之一分钟了解Python

文章目录 为何要学习PythonPython概述编译和运行过程Python主要应用的领域Python的特点Python优点与Java的区别最后 为何要学习Python 鲁迅先生说的好&#xff0c;不爱学习的开发不是好开发&#xff08;帮我压下先生的棺材板~&#xff09;&#xff0c;开个玩笑&#xff0c;主要…

Python---实现飞机大战源码

plane_main.py import pygame from plane_sprites import *class PlaneGame(object):"""飞机大战主游戏"""def __init__(self):print("游戏初始化")# 1.创建游戏的窗口self.screen pygame.display.set_mode(SCREEN_RECT.size)# 2.创…

Python项目——飞机大战!

文章目录 一、项目介绍——飞机大战实战步骤确认模块 —— pygame安装 pygame验证安装 二、pygame 快速入门项目准备1. 使用 pygame 创建图形窗口小节目标1.1 游戏的初始化和退出1.2 理解游戏中的坐标系案例演练 1.3 创建游戏主窗口1.4 简单的游戏循环 2. 理解 **图像** 并实现…

python和java哪个更有前景,python和java哪个更有前途

大家好&#xff0c;小编为大家解答python和java哪个好学,零基础的问题。很多人还不知道python和java哪个更容易入门&#xff0c;现在让我们一起来看看吧&#xff01; 进入编程行业是很多人的梦想&#xff0c;现在越来越多的人都想要通过培训的方式进入IT行业中&#xff0c;但是…

Python项目实战之《飞机大战游戏》

目录 一、Pygame库包简介 二、Pygame安装 三、项目开发思路 3.1前言 3.2飞机大战开发步骤 一、Pygame库包简介 Pygame是一个基于python的游戏开发库&#xff0c;它提供一系列的工具和接口&#xff0c;使开发人员能够轻松的创建各种类型的游戏&#xff0c;包括2D游戏和简单…

Java调用Python语言及第三方Python库

#pic_center 400x 系列文章&#xff1a; 文章目录 1、导入依赖 <!--Python&Java--><dependency><groupId>org.python</groupId><artifactId>jython-standalone</artifactId><version>2.7.2</version></dependency>…