在Angular中使用SheetJS导入导出excel表格

导入本地excel表格

首先在终端使用npm命令安装SheetJS插件。SheetJS是个常用的xlsx交互库

npm install xlsx -s

而后,在angular前端的HTML页面上创建一个input元素和一个按钮,用来执行导入操作。这个按钮要跟后台的importExcel($event)函数绑定,这样当点击时触发这个函数,可以执行一系列后续操作

<input
	   style="display: none"
	   type="file"
	   (change)="importExcel($event)"
	   accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
       #fileInput/>
<button nz-button (click)="fileInput.click()">导入数据</button>

在后台的component部分,首先在开头从xlsx库引入一系列需要的组件。为方便跟页面数据绑定,再新建一个全局变量excelData用来存储序列化的excel数据,一个全局变量excelHeadData用来存储表头数据,并和前端绑定

import { read, utils, WorkBook, WorkSheet, writeFile } from 'xlsx';

然后写好importExcel函数

  importExcel(evt: any) {

    /* 初始化相关参数 */

    const target: DataTransfer = <DataTransfer>evt.target;
    if (target.files.length !== 1) throw new Error('不支持多文件上传');
    const reader: FileReader = new FileReader();
    reader.onload = (e: any) => {

      /* 我这里因为还打算加一个处理文件名的函数,所以添加了这步 */
      let name = target.files[0].name;
      this.fileName = name.substring(0, name.lastIndexOf('.'));

      /* 读入工作簿 */
      const bstr: string = e.target.result;
      const wb: WorkBook = read(bstr, { type: 'binary' });
  
      /* 抓取第一个(序号为0)表 */
      const wsname: string = wb.SheetNames[0];
      const ws: WorkSheet = wb.Sheets[wsname];


      /* 保存表格数据标签与数据内容*/
      let tmpColumnLabelList = utils.sheet_to_json(ws, {
        header: 1,
      })[0] as string[];
      this.excelHeadData=tmpColumnLabelList;
      this.excelData = utils.sheet_to_json(ws, { header: 0 });
      evt.target.value = ''; // 清空

    };

    /* 读入数据 */
    reader.readAsBinaryString(target.files[0]);
  }

在前端准备好数据展示的表格组件,我这里因为比较熟悉,用了Zorro的Table组件

<!--数据区域-->
<div nz-row nzJustify="center" style="margin-top: 15px; margin-bottom: 10px">
  <div nz-col nzSpan="22">
    <nz-table #basicTable [nzData]="excelData">
      <thead>
        <tr>
          <ng-container *ngFor="let label of excelHeadData">
            <th>{{ label }}</th>
          </ng-container>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let valueData of basicTable.data">
          <ng-container *ngFor="let value of excelHeadData">
            <td>
              <span [innerHtml]="valueData[value]"></span>
            </td>
          </ng-container>
        </tr>
      </tbody>
    </nz-table>
  </div>
</div>

如上,当我们点击按钮导入表格后,就可以通过前端的表格组件载入excel数据了。

这里有一点值得注意:表格在遍历数据时,是通过访问表头值(excelHeadData)的形式实现的。因此如果我们有时候不需要一次性载入太多列,又不想引用更重量级的表格组件甚至在线办公套件,其实在析出表头数据时就可以做取舍,只取那些有用的列,或者再设计几个函数,添加一个把所有列都附上CheckBox让用户选择显隐的功能。

导出网页上的表格数据到本地

与导入同理。不过前端得再写一个按钮调用后端的outputExcel函数。如上所述,我在自己的程序里搞了点自选动作,对表格列进行了取舍,所以这里不选择直接导出excelData,而是通过一个pick函数从excelData中遴选自己所需的表格列,然后再导出

  /* 一个便捷的pick函数,方便遴选所需列 */
  pick(obj: { [x: string]: any }, keys: any[]) {
    return keys
      .map((k) => (k in obj ? { [k]: obj[k] } : {}))
      .reduce((res, o) => Object.assign(res, o), {});

  }
  /* 导出至本地excel */
  outputExcel() {
    const outputArr: any[] = [];
    this.excelData.forEach((element: any) => {
      let tmpStruct = this.pick(element, this.columnLabelList);
      outputArr.push(tmpStruct);
    });

    const ws: WorkSheet = utils.json_to_sheet(outputArr, {
      header: this.columnLabelList,
    });

    const wb: WorkBook = utils.book_new();
    utils.book_append_sheet(wb, ws, 'Sheet1');
    writeFile(wb, this.fileName + '保留列.xlsx');
  }
posted @ 2022-10-06 14:11  启真湖畔的佐时雨  阅读(631)  评论(0编辑  收藏  举报