JavaScript纯前端解析Excel文件
最近在开发时候遇到了这样的一个需求:需要在前端通过解析Excel将Excel中的值进行回传填入。我想在实际的开发过程中,肯定大家也会遇到这样的需求,在这介绍一个比较不错的JS工具库:js-xlsx,及该库的简单使用方法。1、js-xlsx简介js-xlsx是由SheetJs出品的纯JS即可实现读取和导出Excel的工具库,功能强大,使用方便,支持格式多,官方Git地址:https://github
最近在开发时候遇到了这样的一个需求:需要在前端通过解析Excel将Excel中的值进行回传填入。我想在实际的开发过程中,肯定大家也会遇到这样的需求,在这介绍一个比较不错的JS工具库:js-xlsx,及该库的简单使用方法。
1、js-xlsx简介
js-xlsx是由SheetJs出品的纯JS即可实现读取和导出Excel的工具库,功能强大,使用方便,支持格式多,官方Git地址: https://github.com/SheetJS/js-xlsx
1.1、兼容性
1.2 使用方式
支持直接使用标签进行引用:
<script lang="javascript" src="dist/xlsx.full.min.js"></script>
也支持CDN引用:
使用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"});
// 字符串转ArrayBuffer
function 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.result
var 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:多看书,多总结,少写代码!
更多推荐
所有评论(0)