文章目录
- 1.流式读取文件
- 2.读取单元格
- 3.修改单元格
- 4.保存文件
- 结语
- 附1:搭配ANTD的Upload实现流式上传读取
- 附2:如何在多个文件全部读取完之后再进行下一步操作
最近在用SheetJS这个库,简单记录一下使用成果。
项目地址:
https://github.com/SheetJS/sheetjs1.流式读取文件 我写的是网页而不是node脚本,所以配合了Antd的Upload组件来做文件上传和文件的流式读取,如果你想看整个的结合方式可以在目录里面跳转到附1部分。
reader.readAsArrayBuffer(dataFileList[key].file);
reader.onload = (e)=>{
let data = https://www.it610.com/article/e.target.result;
let wb = Xlsx.read(data);
console.log(wb);
};
reader.onerror = (e) => {
isReadFileError = true
};
文章图片
看一下文件读取的输出结果,Sheets里面包含的是他的全部工作表(Sheet)的数据。里面A1,B1这些对应的都是每个格子的数据,唯独有一个key比较特殊,就是这个
!ref
。这个代表的是这个工作表的数据范围,然后使用数据的时候就可以这样用:let range = Xlsx.utils.decode_range(wb.Sheets['数据表设定']["!ref"])
range经过解码后可以获得开始单元格(cell)和结束单元格的坐标(说实话这个库的api设计的还是比较随便,名字都是起的怪怪的)。
看下面这个图:
文章图片
s(start_cell):{c(col):0 , r(row):0}
e(end_cell):{c(col):6 , r(row):42}
这个表的数据范围就很清楚了,左上角就是A1,0行0列单元格。右下角就是42行6列单元格(当然,数据下标从0开始是我们程序员的思维,如果你需要把这个设定数据传达给一般使用者,记得加一)。
那有了一个表的范围后我们就可以遍历这些个表格了。
2.读取单元格 现在你回想一下上面我们输出的工作表格式,你就会知道我们在读取单元格的时,需要输入他在Excel里面对应的编码,比如读取1行1列的格子,我们就需要输入’A1’这个key来读取。那一个字符串显然是难以进行遍历操作的,XLSX库里面就给我们提供了一个转换的工具类。
for(let C = range.s.c;
C <= range.e.c;
++C) {
// c col r row
let cell_address = {c:C, r:1};
// 将坐标转换成EXCEL的坐标比如{1, 1}转为A1
let cell_ref = Xlsx.utils.encode_cell(cell_address);
let value = https://www.it610.com/article/wb.Sheets['数据表设定'][cell_ref].v
}
搭配我们上面说到的!ref我们就可以循环遍历这个表了。
然后这里有一个你需要非常注意的点,我们来看一下cell的输出结构:
你会发现他是有一堆东西的,我现在只用到了
v
和t
。我这里要提醒你的是,读取完之后你只是获得了这个cell的对象,具体的数值你还需要往下调用一个.v,我这个记性不好,好几次都是这个问题。
t type: b Boolean, e Error, n Number, d Date, s Text, z Stub3.修改单元格 文档链接:
v raw value (see Data Types section for more info)
r rich text encoding (if applicable)
h HTML rendering of the rich text (if applicable)
w formatted text (if applicable)
直接访问下面的链接可以看到全部的数据信息
https://github.com/SheetJS/sheetjs#cell-object
文章图片
https://github.com/SheetJS/sheetjs#modifying-cell-values这个我主要是用到
XLSX.utils.sheet_add_aoa
这个函数。当你修改单个单元格:
XLSX.utils.sheet_add_aoa(worksheet, [[new_value]], { origin: address });修改多个单元格:
XLSX.utils.sheet_add_aoa(worksheet, aoa, opts);说实话他这个文档写的我是真看不懂,我们直接来研究他给的代码实例:
XLSX.utils.sheet_add_aoa(worksheet, [
[1],// <-- 把1写入到B3里面
,// <-- 第4行啥也不做
[/*B5*/, /*C5*/, /*D5*/, "abc"]// <-- 把abc写到E5里面
], { origin: "B3" });
聪明的你一看这个代码就能看懂了吧,也明白了为什么单个单元格用的是
[[new_value]]
。4.保存文件 文档链接:
https://github.com/SheetJS/sheetjs#parsing-workbooks保存文件目前我只测试了最简单的这个
writeFile
就是直接将wb写成xlsx的,保存文件后会自动弹出下载窗口。Xlsx.writeFile(configWb, 'test.xlsx')
后续在使用过程中遇到解决一些问题可能会持续更新。
结语 毕竟用js来做数据分析的人比较少,所以库的使用比起pandas那是不方便多了。但是python的传播行在非IT公司还是比较麻烦的,环境打包运行也很慢,所以还是尝试用js来做这个,看看后续能不能将一些简答的pandas的功能稍微实现一下。
顺便在这里记录一个库,https://github.com/davidchambers/string-format。可以让js比较像python一样使用formate字符串拼接,这点也是我想不明白的,python的formate这么好用,为啥js的原生的这么难用,不学习一下吗?
写代码有所进步真的能令人开心呢,我是llsxily,你可以叫我橘子。
附1:搭配ANTD的Upload实现流式上传读取 简单来说思路就是调用Upload的
beforeUpload
方法,在文件上传前获取到文件,获取到文件后就可以将数据读取到Buffer然后调用Xlsx.read
解析xlsx文件。const uploadConfigProps = {
name: 'file',
maxCount: 1,
beforeUpload: file => {
console.log(file)
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = (e) => {
console.log('read_file')
let data = https://www.it610.com/article/e.target.result;
console.log(data)
let wb = Xlsx.read(data)
console.log(wb)
// !ref获取的是表格的规模大小
let range = Xlsx.utils.decode_range(wb.Sheets['数据表设定']["!ref"])
console.log(range)
...
}
}
return false;
}
}
这个是配合Dragger使用
点击或拖动文件至该区域上传
Upload的代码也是基本类似的,这里我加上了
return Upload.LIST_IGNORE;
这个返回值可以使得上传的文件不会出现在Upload的上传队列里面同时showUploadList={false}
这个代码也是同样的效果,请注意甄别。 {
console.log(file)
return Upload.LIST_IGNORE;
}}
>
重新上传
附2:如何在多个文件全部读取完之后再进行下一步操作 【网页|SheetJS xlsx js库入门使用】这个功能可以查看我上一篇文章
React-js中等待多个回调全部完成后执行后续函数
推荐阅读
- 单线程的 JavaScript 是怎么实现异步的?
- React|Redux中间件及其开发者工具
- 熊猫周刊|《熊猫周刊》-2022/03/25
- js|阿里开源项目LowCodeEngine低代码开发引擎
- React 性能调优记录(下篇),如何写高性能的代码
- java|看看人家那物流系统,那叫一个优雅(附源码)
- java|javascrip基本知识总结
- 前端设计|Vue Element 安装与使用
- js原型和原型链疑问