发布于 2026-01-06 0 阅读
0

在Angular中将数据导出到Excel和CSV

在Angular中将数据导出到Excel和CSV

在开发Web应用程序时,我们经常需要允许用户将数据下载为他们指定的格式。其中一项需求是允许用户将数据导出为电子表格(Excel)或CSV文件。

这是一个非常常见的用例,因此我决定创建一个分步指南,帮助大家轻松完成此操作。我们将讨论导出到以下两个主要区域:

📝 注意:
我已经在 GitHub 上创建了一个关于此实现的仓库。

GitHub 标志 idris-rampurawala / ng-数据导出

演示如何使用 Angular 10 实现将数据导出到 Excel 和 CSV 的导出服务


导出到 Excel

将数据导出到 Excel 的功能不仅为用户提供了强大的功能,而且还能帮助我们创建一系列其他相关功能,从而帮助用户更好地理解数据。那么我们该如何开始呢?正如您所料,我们有一个 npm 包可以处理这个问题——xlsx (也称为 sheetjs) 😁

安装依赖项



# installing xlsx package
$ npm install xlsx
# installing file-saver - a solution to saving files on the client-side
$ npm install file-saver


Enter fullscreen mode Exit fullscreen mode

创建出口服务

在 Angular 中,创建常用功能的一种方法是为其创建服务。因此,我们创建了一个导出服务,该服务将包含导出所有类型信息(本文中为 Excel 和 CSV 格式)的功能。

使用 xlsx

xlsx它提供了一套非常丰富的实用工具,用于创建或解析电子表格。为了简单起见,我们这里只重点介绍其中几个实用工具。

1️⃣ 导出 HTML 表格

如果要将数据导出HTML table到 Excel,这非常简单,因为xlsxExcel 提供了相应的工具。假设我们有一个表格👇



<!-- app.component.html -->
<table class="table table-sm" #userTable> <!-- we will make use of this angular var as element reference -->
  <thead class="thead-dark">
    <tr>
      <th scope="col">#</th>
      ...
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let user of users">
      <td scope="row">{{ user.id }}</td>
      ...
    </tr>
    <tr>
  </tbody>
</table>


Enter fullscreen mode Exit fullscreen mode

现在,我们可以创建一个service函数来接收这个值HTML element reference并从中生成 Excel 文件(使用<thead><tbody>)。



/* export.service.ts */
import { Injectable, ElementRef } from '@angular/core';
import * as FileSaver from 'file-saver';
import * as XLSX from 'xlsx';

const EXCEL_EXTENSION = '.xlsx';

@Injectable()
export class ExportService {
  constructor() { }

  /**
   * Creates excel from the table element reference.
   *
   * @param element DOM table element reference.
   * @param fileName filename to save as.
   */
  public exportTableElmToExcel(element: ElementRef, fileName: string): void {
    const ws: XLSX.WorkSheet = XLSX.utils.table_to_sheet(element.nativeElement);
    // generate workbook and add the worksheet
    const workbook: XLSX.WorkBook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, ws, 'Sheet1');
    // save to file
    XLSX.writeFile(workbook, `${fileName}${EXCEL_EXTENSION}`);

  }
  ...
}


Enter fullscreen mode Exit fullscreen mode

我们component.ts只需创建一个处理程序,export button尝试将文件保存为客户端计算机上的 Excel 文件即可。



/* app.component.ts */
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { ExcelJson } from './interfaces/excel-json.interface';
import { ExportService } from './services/export.service';
...

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  ...
  /* the table reference */
  @ViewChild('userTable') userTable: ElementRef;
  ...

  constructor(
    private exportService: ExportService
  ) { }

  ngOnInit(): void {
    ...
  }

  /**
   * Function prepares data to pass to export service to create excel from Table DOM reference
   *
   */
  exportElmToExcel(): void {
    this.exportService.exportTableElmToExcel(this.userTable, 'user_data');
  }

  ...

}


Enter fullscreen mode Exit fullscreen mode

这很简单,对吧?😆 如果我们想导出更复杂的数据呢?🙄 让我们一起来看看👇

2️⃣ 导出更复杂的数据

xlsx它还提供了各种其他实用工具来自定义 Excel 中的数据(使用 Excel 列名进行标识)。例如,我曾在某个项目中创建了一个函数,用于将整个仪表板数据导出到 Excel。让我们也创建一个类似的A, B, C..函数。service



/* export.service.ts */
...

  /**
   * Creates XLSX option from the Json data. Use this to customize the sheet by adding arbitrary rows and columns.
   *
   * @param json Json data to create xlsx.
   * @param fileName filename to save as.
   */
  public exportJsonToExcel(json: ExcelJson[], fileName: string): void {
    // inserting first blank row
    const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(
      json[0].data,
      this.getOptions(json[0])
    );

    for (let i = 1, length = json.length; i < length; i++) {
      // adding a dummy row for separation
      XLSX.utils.sheet_add_json(
        worksheet,
        [{}],
        this.getOptions(
          {
            data: [],
            skipHeader: true
          }, -1)
      );
      XLSX.utils.sheet_add_json(
        worksheet,
        json[i].data,
        this.getOptions(json[i], -1)
      );
    }
    const workbook: XLSX.WorkBook = { Sheets: { Sheet1: worksheet }, SheetNames: ['Sheet1'] };
    // save to file
    XLSX.writeFile(workbook, `${fileName}${EXCEL_EXTENSION}`);
  }

  /**
   * Creates the XLSX option from the data.
   *
   * @param json Json data to create xlsx.
   * @param origin XLSX option origin.
   * @returns options XLSX options.
   */
  private getOptions(json: ExcelJson, origin?: number): any {
    // adding actual data
    const options = {
      skipHeader: true,
      origin: -1,
      header: []
    };
    options.skipHeader = json.skipHeader ? json.skipHeader : false;
    if (!options.skipHeader && json.header && json.header.length) {
      options.header = json.header;
    }
    if (origin) {
      options.origin = origin ? origin : -1;
    }
    return options;
  }

...


Enter fullscreen mode Exit fullscreen mode

然后component.ts,我们创建所需格式的数据xlsx,以便将其传递给此服务函数。



/* app.component.ts */
...

/**
   * Function prepares data to pass to export service to create excel from Json
   *
   */
  exportToExcel(): void {

    const edata: Array<ExcelJson> = [];
    const udt: ExcelJson = {
      data: [
        { A: 'User Data' }, // title
        { A: '#', B: 'First Name', C: 'Last Name', D: 'Handle' }, // table header
      ],
      skipHeader: true
    };
    this.users.forEach(user => {
      udt.data.push({
        A: user.id,
        B: user.firstName,
        C: user.lastName,
        D: user.handle
      });
    });
    edata.push(udt);

    // adding more data just to show "how we can keep on adding more data"
    const bd = {
      data: [
        // chart title
        { A: 'Some more data', B: '' },
        { A: '#', B: 'First Name', C: 'Last Name', D: 'Handle' }, // table header
      ],
      skipHeader: true
    };
    this.users.forEach(user => {
      bd.data.push({
        A: String(user.id),
        B: user.firstName,
        C: user.lastName,
        D: user.handle
      });
    });
    edata.push(bd);
    this.exportService.exportJsonToExcel(edata, 'user_data_customized');
  }

...


Enter fullscreen mode Exit fullscreen mode
解释

感到困惑?😕 让我解释一下我们刚才做了什么。

  • xlsx(或电子表格)有一个workbook(这是一个实际的文件),我们可以在其中sheets添加多个。
  • xlsx它提供了一个实用函数sheet_add_json(),可以将对象数组转换为带有额外 xlsx 选项的 Excel 数据。因此,我们为其创建了一个包装器,service通过该包装器可以传递具有不同 xlsx 选项的多个对象。这样,我们的导出服务就处理了复杂性,我们只需要创建一个对象数组传递给它即可。
  • xlsx期望对象数组的形式为{cell: value },因此{A: 'value'}意味着我们要将其放入Excel 的value单元格(列)中。A
  • skipHeader目的是跳过传递给函数的对象中自动生成的标头。sheet_add_json()
  • origin: -1是将数据追加到工作表的底部,从第一列开始。
  • 此外,ExcelJson还有一个自定义接口(是我创建的),用于定义服务函数期望的数据类型。它代表一个有效的对象数据xlsx

有关更多信息,请阅读xlsx文档和github 上的示例实现

如何设置Excel样式?🧐

xlsx其开源版本不提供样式设置。您可以选择其他方案pro version来获得样式设置和专门的支持。

或者,xlsx-style是其一个分支,xlsx它在其基础上提供了样式。

另一个非常流行的替代方案xlsxExcelJS。它也包含了样式功能,但与相比,提供的实用功能较少xlsx


导出为 CSV

现在我们继续导出的第二部分,即 CSV 文件。

别担心😟,这很简单。我们只需要在代码中添加一个函数,export service该函数接受一个对象数组和一个列标题,然后根据数组内容创建一个 CSV 文件。



/* export.service.ts */
...
 /**
   * Saves the file on the client's machine via FileSaver library.
   *
   * @param buffer The data that need to be saved.
   * @param fileName File name to save as.
   * @param fileType File type to save as.
   */
  private saveAsFile(buffer: any, fileName: string, fileType: string): void {
    const data: Blob = new Blob([buffer], { type: fileType });
    FileSaver.saveAs(data, fileName);
  }

  /**
   * Creates an array of data to CSV. It will automatically generate a title row based on object keys.
   *
   * @param rows array of data to be converted to CSV.
   * @param fileName filename to save as.
   * @param columns array of object properties to convert to CSV. If skipped, then all object properties will be used for CSV.
   */
  public exportToCsv(rows: object[], fileName: string, columns?: string[]): string {
    if (!rows || !rows.length) {
      return;
    }
    const separator = ',';
    const keys = Object.keys(rows[0]).filter(k => {
      if (columns?.length) {
        return columns.includes(k);
      } else {
        return true;
      }
    });
    const csvContent =
      keys.join(separator) +
      '\n' +
      rows.map(row => {
        return keys.map(k => {
          let cell = row[k] === null || row[k] === undefined ? '' : row[k];
          cell = cell instanceof Date
            ? cell.toLocaleString()
            : cell.toString().replace(/"/g, '""');
          if (cell.search(/("|,|\n)/g) >= 0) {
            cell = `"${cell}"`;
          }
          return cell;
        }).join(separator);
      }).join('\n');
    this.saveAsFile(csvContent, `${fileName}${CSV_EXTENSION}`, CSV_TYPE);
  }

...


Enter fullscreen mode Exit fullscreen mode

这段代码几乎一目了然🤓,它检查传入的数据中是否存在指定列的数据,并据此生成一个 CSV 文件。我们可以,根据需要随时更改分隔符。需要file-saver包才能将文件保存到客户端计算机上。


是不是很简单?🙌 你可以查看我的GitHub 代码库,那里有本文的完整实现。

如果您觉得这篇文章有用或有任何建议,欢迎留言。如果您喜欢我的帖子,也别忘了点赞❤️或🦄哦!

下次见!😋

文章来源:https://dev.to/idrisrampurawala/exporting-data-to-excel-and-csv-in-angular-3643