热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaScript纯前端解析Excel文件

最近在开发时候遇到了这样的一个需求:需要在前端通过解析Excel将Excel中的值进行回传填入。我想在实际的开发过程中,肯定大家也会遇到这样的需求&#x

        最近在开发时候遇到了这样的一个需求:需要在前端通过解析Excel将Excel中的值进行回传填入。我想在实际的开发过程中,肯定大家也会遇到这样的需求,在这介绍一个比较不错的JS工具库:js-xlsx,及该库的简单使用方法。

1、js-xlsx简介

        js-xlsx是由SheetJs出品的纯JS即可实现读取和导出Excel的工具库,功能强大,使用方便,支持格式多,官方Git地址: https://github.com/SheetJS/js-xlsx

1.1、兼容性

1.2 使用方式

        支持直接使用标签进行引用:


         也支持CDN引用:

CDNURL
unpkgUNPKG - xlsxhttps://jsdelivr.com/package/npm/xlsxUNPKG - xlsx
jsDelivrxlsx CDN by jsDelivr - A CDN for npm and GitHub
CDNjsxlsx - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
packd

https://bundle.run/xlsx@latest?name=XLSX

        使用npm安装

$ npm install xlsx

        使用bower安装

$ bower install js-xlsx
2、读取excle文件

        读取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 读取本地文件

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

2.2 读取workbook

        不处理合并单元格

function readWorkbook(workbook) {var sheetContent = []// 遍历每张表读取for (var sheet in workbook.Sheets) {if (workbook.Sheets.hasOwnProperty(sheet)) {fromTo = workbook.Sheets[sheet]['!ref'];sheetContent.push(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]))// break; // 如果只取第一张表,就取消注释这行}}return sheetContent
}

        处理合并单元格

// 读取 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格式

3、导出excel

3.1 手写代码实现

// 将一个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;
}

3.2 利用官方工具类

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

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

 3.3 处理单元格合并

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');

4、样例 

        最后,上一段直接读取本地文件后返回Json格式的代码,方便进行参考

//读取本地Excel表格
function readWorkbookFromLocalFile(files) {var fileReader = new FileReader()fileReader.readAsBinaryString(files[0])return new Promise(function(resolve, reject) {fileReader.onload = function (ev) {try {var data = ev.target.resultvar workbook = XLSX.read(data, {type: 'binary'}) // 以二进制流方式读取得到整份excel表格对象var fromTo = '';var sheetContent = []// 遍历每张表读取for (var sheet in workbook.Sheets) {if (workbook.Sheets.hasOwnProperty(sheet)) {fromTo = workbook.Sheets[sheet]['!ref'];sheetContent.push(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]))// break; // 如果只取第一张表,就取消注释这行}}respondBody = {code: 100,msg: '文件解析成功',body: sheetContent}resolve(respondBody)} catch (e) {respondBody = {code: 500,msg: '文件类型不正确',body: ''}reject(respondBody)}}})
}

tips:多看书,多总结,少写代码!


推荐阅读
author-avatar
mobiledu2502870133
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有