zoukankan      html  css  js  c++  java
  • sheetjs 使用简介

    xlsx js 的使用笔记

    最近项目需要前端导出excel,以及解析excel,使用了 xlsx 这个包。简单介绍一下遇到的问题和快速上手使用代码。

    • 先来段导出生产excel 的代码片段。我们演示如何把一个二维数组导入excel。代码如下,非常简单。
    import xlsx from 'xlsx';
    
    // write rows:any[][] to some sheet
    createSheetFromAoa(aoa: any[][]) {
        let ws = xlsx.utils.aoa_to_sheet(aoa);
        ws['!cols'] = this.fitToColumn(aoa);
        return ws;
      }
    
    // just make the cells auto-fit, make the width to the max width of same column
      fitToColumn(arrayOfArray: any[][]) {
        // get maximum character of each column
        return arrayOfArray[0].map((a, i) => ({
          wch:
            Math.max(
              ...arrayOfArray
                .map((a2) => a2[i]?.toString()?.length)
                .filter((it) => it > 0)
            ) + 3,
        }));
      }
    
    const rows=[
        ['head1','head2','head3'],
        [1,2,3],
        [4,5,6],
        [7,8,9]
    ]
    // create workbook first
    const wb: xlsx.WorkBook = xlsx.utils.book_new();
    const ws: xlsx.WorkSheet = createSheetFromAoa(rows);
    xlsx.utils.book_append_sheet(wb,ws,'TabName');
    xlsx.writeFile(wb, 'helloworld.xlsx');
    
    • 再来一段从excel 中读取的代码片段,代码如下。
    const reader = new FileReader();
    reader.onload = (e) => {
        var data = new Uint8Array(e.target.result as any);
        let wb = xlsx.read(data, {
            type: 'array',
        });
        this.parseWorkBook(wb);
    };
    reader.readAsArrayBuffer(this._uploadedFile as File);
    
    //parse workbook
    function parseWorkBook(wb:xlsx.WorkBook){
        const ws = wb.Sheets['TabName'];
        // mark the first row is header
        const rows = xlsx.utils.sheet_to_json(ws,{header:1});
        const header=rows[0];
        const body = rows.slice(1);
    }
    
    • 这个里面需要注意的几个问题,第一个是 类型转换,excel 认识int,double,boolean,Date.这个要注意了。看是不是你需要的,可以通过迭代,rows 来解析里面的内容。
    • 第二个问题就是Date,这个格式,excel 对于时间这个格式是有问题的,例如,我们再excel 里面写的是2021-8-5,当我们解析到内存里变成Date 后就变成了2020-8-4,为什么呢,因为来自于excel 的时间是一个很大的数字。这个数字换成时间后,会差1到几秒不等,所以就差了一天了。那么怎么解决. 用下面的toexcel fromexcel 来先做转换,然后在传给excel 或者, 解析excel 里面上来的值。
    getDateMapping() {
        return {
          toexcel: (val: string) => {
            try {
              return val?.length ? DateTime.fromISO(val).toJSDate() : null;
            } catch (ex) {
              return null;
            }
          },
          fromexcel: (val: number) => {
            try {
              //https://github.com/SheetJS/sheetjs/issues/1223
              return val > 0
                ? DateTime.fromMillis(Math.round((val - 25569) * 86400 * 1000))
                    .setZone('utc')
                    .toFormat('yyyy-MM-dd')
                : null;
            } catch (ex) {
              return null;
            }
          },
        };
      }
    
    • 最后一个问题,excel 里面我们可以给某一列添加个Data Validation, 这样,某一列的内容就是一个dropdown. 目前免费版的xlsx 里面不支持。但是网上大神给了解决方法。需要修改 xlsx 的源码。
      这个是修改后的npm, 修改如下:
      bits_wsxml.js function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)
      首先在这个方法前面添加一个这个方法。
    function write_ws_xml_datavalidation(validations) {
    	var o = '<dataValidations>';
    	for(var i=0; i < validations.length; i++) {
    		var validation = validations[i];
    		o += '<dataValidation type="list" allowBlank="1" sqref="' + validation.sqref + '">';
    		o += '<formula1>"'+validation.values+'"</formula1>';
    		o += '</dataValidation>';
    	}
    	o += '</dataValidations>';
    	return o;
    };
    

    然后在write_ws_xml 找到如下片段,做如下修改

        if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
    +	if(ws['!dataValidation']!=null && ws['!dataValidation'].length>0) o[o.length] = write_ws_xml_datavalidation(ws['!dataValidation']);
    
    
    • 最后提一下编译sheetjs 并且发布npm 的问题。在pakcage.json 里面scripts 添加了如下一个命令。 首先我们run npm run build,会编译生成.xlsx.js的文件,然后运行如下命令可以压缩这个文件到dist/xxx下面。
    "uglifyjs-xlsx": "uglifyjs xlsx.js -o ./dist/xlsx.min.js --source-map ./dist/xlsx.min.map"
    
    • 发布的时候,在有账号的前提下,run npm publish 如果是私有的仓储,run npm publish --registry="http://xxx..xxx/", 期间会报401,403 等错误,只要账号激活,没有重名,就可以解决这类错误。
    • 几个npm 的命令。
      npm login/logout 这个是用来登入以及登出的,可以添加 --registry 指定仓储,默认是npm
      npm adduser 这个是注册账号的。
    • 在往私有仓储推代码后,拉取的时候报错了。后来通过 npm config set @internal:registry http://xxx, 然后 npm install @internal/xlsx 就可以了,不明白,我通过npm install @internal/xlsx --registry http://xxxx 一直报403/401
  • 相关阅读:
    cocos2dx 菜鸟实习生学习篇(四) 锚点的理解
    cocos2dx 菜鸟进阶篇(三) scrollView(下)
    2012年终总结!
    cocos2dx 菜鸟进阶篇(二) 重力感应
    cocos2dx 菜鸟进阶篇(三) ScrollView(上)
    cocos2dx 菜鸟进阶篇(一) 在游戏中添加music
    Mobile Web项目中碰到的问题及解决
    struts验证框架的使用
    错误解决办法收集
    JSONP跨域访问实现登录验证
  • 原文地址:https://www.cnblogs.com/kongshu-612/p/15106858.html
Copyright © 2011-2022 走看看