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
posted @ 2021-08-06 07:21  kongshu  阅读(720)  评论(0编辑  收藏  举报