SheetJS xlsx js库入门使用


最近在用SheetJS这个库,简单记录一下使用成果。
项目地址:

https://github.com/SheetJS/sheetjs

1.流式读取文件

我写的是网页而不是node脚本,所以配合了Antd的Upload组件来做文件上传和文件的流式读取,如果你想看整个的结合方式可以在目录里面跳转到附1部分。

        reader.readAsArrayBuffer(dataFileList[key].file);
        reader.onload = (e)=>{
          let data = 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 = wb.Sheets['数据表设定'][cell_ref].v
          }

搭配我们上面说到的!ref我们就可以循环遍历这个表了。
然后这里有一个你需要非常注意的点,我们来看一下cell的输出结构:
你会发现他是有一堆东西的,我现在只用到了vt
我这里要提醒你的是,读取完之后你只是获得了这个cell的对象,具体的数值你还需要往下调用一个.v,我这个记性不好,好几次都是这个问题。

t type: b Boolean, e Error, n Number, d Date, s Text, z Stub
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
在这里插入图片描述

3.修改单元格

文档链接:

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 = 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使用

<Dragger
	style={{width: '100%'}}
	{...uploadConfigProps}
>
    <p className="ant-upload-drag-icon">
    	<InboxOutlined />
    </p>
    <p className="ant-upload-text">点击或拖动文件至该区域上传</p>
</Dragger>

Upload的代码也是基本类似的,这里我加上了return Upload.LIST_IGNORE;这个返回值可以使得上传的文件不会出现在Upload的上传队列里面同时showUploadList={false}这个代码也是同样的效果,请注意甄别。

<Upload
	maxCount={1}
	showUploadList={false}
    beforeUpload={(file) => {
		console.log(file)
        return Upload.LIST_IGNORE;
       }}
>
	<a>重新上传</a>
</Upload>

附2:如何在多个文件全部读取完之后再进行下一步操作

这个功能可以查看我上一篇文章
React-js中等待多个回调全部完成后执行后续函数

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值