---
title: "Excel Export - Multiple Sheets"
enterprise: true
framework: angular
version: "36.1.0"
---

# Excel Export - Multiple Sheets

Excel Export provides a way to export an Excel file with multiple sheets. This can be useful when you need to export data from different grids into a single Excel file.

## How it works

Exporting the grid into different sheets follows a specific process:

1. You start the process by calling the `getSheetDataForExcel` method on a grid instance to get the data exported for a specific sheet.
2. You call this method multiple times either on the same grid with different data (or different export params) or on different instances of the grid, and you store each exported data set as an element of an Array.
3. Once all the needed sheets have been stored in the Array, call the `exportMultipleSheetsAsExcel` or `getMultipleSheetsAsExcel` methods to package them in a single Excel workbook.

> **Warning**
>
> Calling `getSheetDataForExcel` starts a **Multiple Sheet** export process, that can only be ended by calling the `exportMultipleSheetsAsExcel` or `getMultipleSheetsAsExcel` methods. Until one of these two methods is called to complete the process, no data can be exported from the grid using `exportDataAsExcel` or `getDataAsExcel`.

## Using Selected Rows

In this example, we use the `onlySelected=true` property to segment the grid data into multiple sheets, each containing 100 data rows. Specifically:

1. We manually select 100 rows at a time using `setNodesSelected`.
2. We then use `getSheetDataForExcel` with the `onlySelected` option to generate sheet data for these selected nodes only.
3. We then deselect rows again to avoid affecting the UI.

Note the following:

- The header is exported on each page, so each page will contain 101 records (including the header).
- Because each export did not have a specified `sheetName`, they will be named `ag-grid`, `ag-grid_1`, `ag-grid_2` and so on.

#### Excel Export - Multiple Sheets with Data Selection

```ts
import { Component } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IRowNode,
  ModuleRegistry,
  NumberFilterModule,
  RowApiModule,
  RowSelectionModule,
  RowSelectionOptions,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
} from "ag-grid-enterprise";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  TextFilterModule,
  NumberFilterModule,
  RowSelectionModule,
  RowApiModule,
  ClientSideRowModelModule,
  ExcelExportModule,
  ColumnMenuModule,
  ContextMenuModule,
]);
import { IOlympicData } from "./interfaces";

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div class="container">
    <div>
      <button
        (click)="onBtExport()"
        style="margin-bottom: 5px; font-weight: bold"
      >
        Export to Excel
      </button>
    </div>
    <div class="grid-wrapper">
      <ag-grid-angular
        style="width: 100%; height: 100%;"
        [columnDefs]="columnDefs"
        [defaultColDef]="defaultColDef"
        [rowSelection]="rowSelection"
        [rowData]="rowData"
        (gridReady)="onGridReady($event)"
      />
    </div>
  </div> `,
})
export class AppComponent {
  private gridApi!: GridApi<IOlympicData>;

  columnDefs: ColDef[] = [
    { field: "athlete", minWidth: 200 },
    { field: "age" },
    { field: "country", minWidth: 200 },
    { field: "year" },
    { field: "date", minWidth: 150 },
    { field: "sport", minWidth: 150 },
    { field: "gold" },
    { field: "silver" },
  ];
  defaultColDef: ColDef = {
    filter: true,
    minWidth: 100,
    flex: 1,
  };
  rowSelection: RowSelectionOptions | "single" | "multiple" = {
    mode: "multiRow",
    checkboxes: false,
    headerCheckbox: false,
  };
  rowData!: IOlympicData[];

  constructor(private http: HttpClient) {}

  onBtExport() {
    const spreadsheets: string[] = [];
    let nodesToExport: IRowNode[] = [];
    this.gridApi.forEachNode((node, index) => {
      nodesToExport.push(node);
      if (index % 100 === 99) {
        this.gridApi.setNodesSelected({ nodes: nodesToExport, newValue: true });
        spreadsheets.push(
          this.gridApi.getSheetDataForExcel({
            onlySelected: true,
          })!,
        );
        this.gridApi.deselectAll();
        nodesToExport = [];
      }
    });
    // check if the last page was exported
    if (this.gridApi.getSelectedNodes().length) {
      spreadsheets.push(
        this.gridApi.getSheetDataForExcel({
          onlySelected: true,
        })!,
      );
      this.gridApi.deselectAll();
    }
    this.gridApi.exportMultipleSheetsAsExcel({
      data: spreadsheets,
      fileName: "ag-grid.xlsx",
    });
  }

  onGridReady(params: GridReadyEvent<IOlympicData>) {
    this.gridApi = params.api;

    this.http
      .get<
        IOlympicData[]
      >("https://www.ag-grid.com/example-assets/olympic-winners.json")
      .subscribe((data) => (this.rowData = data));
  }
}
```

[Live example: Excel Export - Multiple Sheets with Data Selection](https://www.ag-grid.com/examples/excel-export-multiple-sheets/excel-export-multiple-sheets-selected/angular)

## Using Data Filtering

In this example, we filter on the sport column to segment the grid data into multiple sheets, each containing all the data for a specific sport value.

Note the following:

- The exported Excel file will contain one sheet for each sport result.
- Each sheet was exported using the sport name as the name of the sheet.

#### Excel Export - Multiple Sheets with Filtered Data

```ts
import { Component } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberFilterModule,
  RowApiModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
  SetFilterModule,
} from "ag-grid-enterprise";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  NumberFilterModule,
  RowApiModule,
  ClientSideRowModelModule,
  ExcelExportModule,
  ColumnMenuModule,
  ContextMenuModule,
  SetFilterModule,
]);
import { IOlympicData } from "./interfaces";

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div class="container">
    <div>
      <button
        (click)="onBtExport()"
        style="margin-bottom: 5px; font-weight: bold"
      >
        Export to Excel
      </button>
    </div>
    <div class="grid-wrapper">
      <ag-grid-angular
        style="width: 100%; height: 100%;"
        [columnDefs]="columnDefs"
        [defaultColDef]="defaultColDef"
        [rowData]="rowData"
        (gridReady)="onGridReady($event)"
      />
    </div>
  </div> `,
})
export class AppComponent {
  private gridApi!: GridApi<IOlympicData>;

  columnDefs: ColDef[] = [
    { field: "athlete", minWidth: 200 },
    { field: "age" },
    { field: "country", minWidth: 200 },
    { field: "year" },
    { field: "date", minWidth: 150 },
    { field: "sport", minWidth: 150 },
    { field: "gold" },
    { field: "silver" },
  ];
  defaultColDef: ColDef = {
    filter: true,
    minWidth: 100,
    flex: 1,
  };
  rowData!: IOlympicData[];

  constructor(private http: HttpClient) {}

  onBtExport() {
    const sports: Record<string, boolean> = {};
    this.gridApi.forEachNode(function (node) {
      if (!sports[node.data!.sport]) {
        sports[node.data!.sport] = true;
      }
    });
    let spreadsheets: string[] = [];
    const performExport = async () => {
      for (const sport in sports) {
        await this.gridApi.setColumnFilterModel("sport", { values: [sport] });
        this.gridApi.onFilterChanged();
        if (this.gridApi.getColumnFilterModel("sport") == null) {
          throw new Error("Example error: Filter not applied");
        }
        const sheet = this.gridApi.getSheetDataForExcel({
          sheetName: sport,
        });
        if (sheet) {
          spreadsheets.push(sheet);
        }
      }
      await this.gridApi.setColumnFilterModel("sport", null);
      this.gridApi.onFilterChanged();
      this.gridApi.exportMultipleSheetsAsExcel({
        data: spreadsheets,
        fileName: "ag-grid.xlsx",
      });
      spreadsheets = [];
    };
    performExport();
  }

  onGridReady(params: GridReadyEvent<IOlympicData>) {
    this.gridApi = params.api;

    this.http
      .get<
        IOlympicData[]
      >("https://www.ag-grid.com/example-assets/olympic-winners.json")
      .subscribe((data) => (this.rowData = data));
  }
}
```

[Live example: Excel Export - Multiple Sheets with Filtered Data](https://www.ag-grid.com/examples/excel-export-multiple-sheets/excel-export-multiple-sheets-by-filter/angular)

## Multiple Grids to Multiple Sheets

In this example, we export two grids, each into a separate sheet of the same Excel file. Drag a few rows from the grid on the left into the grid on the right and click the export button above the grid.

Note the following:

- The contents of the `Athletes` grid will be exported to the `Athletes` sheet.
- The contents of the `Selected Athletes` grid will be exported to the `Selected Athletes` sheet.
- Only the `onExcelExport` method is relevant to **Excel Export**

#### Excel Export - Multiple Sheets with Multiple Grids

```ts
import { HttpClient } from "@angular/common/http";
import { ChangeDetectionStrategy, Component, ViewChild } from "@angular/core";

import type { ICellRendererAngularComp } from "ag-grid-angular";
import { AgGridAngular } from "ag-grid-angular";
import type {
  ColDef,
  GetRowIdParams,
  GridApi,
  GridReadyEvent,
  ICellRendererParams,
  RowSelectionOptions,
} from "ag-grid-community";
import {
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
  ModuleRegistry,
  RowDragModule,
  RowSelectionModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
  exportMultipleSheetsAsExcel,
} from "ag-grid-enterprise";

import "./styles.css";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  RowDragModule,
  ClientSideRowModelApiModule,
  TextFilterModule,
  RowSelectionModule,
  ClientSideRowModelModule,
  ExcelExportModule,
  ColumnMenuModule,
  ContextMenuModule,
]);

@Component({
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <i
      class="far fa-trash-alt"
      style="cursor: pointer"
      (click)="applyTransaction()"
    ></i>
  `,
})
export class SportRenderer implements ICellRendererAngularComp {
  private params!: ICellRendererParams;

  agInit(params: ICellRendererParams): void {
    this.params = params;
  }

  applyTransaction() {
    this.params.api.applyTransaction({ remove: [this.params.node.data] });
  }

  refresh() {
    return false;
  }
}

@Component({
  standalone: true,
  imports: [AgGridAngular],
  selector: "my-app",
  template: ` <div class="top-container">
    <div>
      <button
        type="button"
        class="btn btn-default excel"
        style="margin-right: 5px;"
        (click)="onExcelExport()"
      >
        <i
          class="far fa-file-excel"
          style="margin-right: 5px; color: green;"
        ></i
        >Export to Excel
      </button>
      <button type="button" class="btn btn-default reset" (click)="reset()">
        <i class="fas fa-redo" style="margin-right: 5px;"></i>Reset
      </button>
    </div>
    <div class="grid-wrapper">
      <div class="panel panel-primary" style="margin-right: 10px;">
        <div class="panel-heading">Athletes</div>
        <div class="panel-body">
          <div id="eLeftGrid">
            <ag-grid-angular
              style="height: 100%;"
              [defaultColDef]="defaultColDef"
              [rowSelection]="rowSelection"
              [rowDragMultiRow]="true"
              [getRowId]="getRowId"
              [rowDragManaged]="true"
              [suppressMoveWhenRowDragging]="true"
              [rowData]="leftRowData"
              [columnDefs]="leftColumns"
              (gridReady)="onGridReady($event, 0)"
            />
          </div>
        </div>
      </div>
      <div class="panel panel-primary" style="margin-left: 10px;">
        <div class="panel-heading">Selected Athletes</div>
        <div class="panel-body">
          <div id="eRightGrid">
            <ag-grid-angular
              style="height: 100%;"
              [defaultColDef]="defaultColDef"
              [getRowId]="getRowId"
              [rowDragManaged]="true"
              [rowData]="rightRowData"
              [columnDefs]="rightColumns"
              (gridReady)="onGridReady($event, 1)"
            />
          </div>
        </div>
      </div>
    </div>
  </div>`,
})
export class AppComponent {
  rawData: any[] = [];
  leftRowData: any[] = [];
  rightRowData: any[] = [];
  leftApi!: GridApi;
  rightApi!: GridApi;

  defaultColDef: ColDef = {
    flex: 1,
    minWidth: 100,
    filter: true,
  };

  rowSelection: RowSelectionOptions = {
    mode: "multiRow",
  };

  leftColumns: ColDef[] = [
    {
      rowDrag: true,
      maxWidth: 50,
      suppressHeaderMenuButton: true,
      suppressHeaderFilterButton: true,
      rowDragText: (params, dragItemCount) => {
        if (dragItemCount > 1) {
          return dragItemCount + " athletes";
        }
        return params.rowNode!.data.athlete;
      },
    },
    { field: "athlete" },
    { field: "sport" },
  ];

  rightColumns: ColDef[] = [
    {
      rowDrag: true,
      maxWidth: 50,
      suppressHeaderMenuButton: true,
      suppressHeaderFilterButton: true,
      rowDragText: (params, dragItemCount) => {
        if (dragItemCount > 1) {
          return dragItemCount + " athletes";
        }
        return params.rowNode!.data.athlete;
      },
    },
    { field: "athlete" },
    { field: "sport" },
    {
      suppressHeaderMenuButton: true,
      suppressHeaderFilterButton: true,
      maxWidth: 50,
      cellRenderer: SportRenderer,
    },
  ];

  @ViewChild("eLeftGrid") eLeftGrid: any;
  @ViewChild("eRightGrid") eRightGrid: any;

  constructor(private http: HttpClient) {
    this.http
      .get("https://www.ag-grid.com/example-assets/olympic-winners.json")
      .subscribe((data) => {
        const athletes: any[] = [];
        let i = 0;
        const dataArray = data as any[];
        while (athletes.length < 20 && i < dataArray.length) {
          var pos = i++;
          if (athletes.some((rec) => rec.athlete === dataArray[pos].athlete)) {
            continue;
          }
          athletes.push(dataArray[pos]);
        }
        this.rawData = athletes;
        this.loadGrids();
      });
  }

  loadGrids = () => {
    this.leftRowData = [...this.rawData.slice(0, this.rawData.length / 2)];
    this.rightRowData = [...this.rawData.slice(this.rawData.length / 2)];
  };

  reset = () => {
    this.loadGrids();
  };

  getRowId = (params: GetRowIdParams) => params.data.athlete;

  onGridReady(params: GridReadyEvent, side: number) {
    if (side === 0) {
      this.leftApi = params.api;
    }

    if (side === 1) {
      this.rightApi = params.api;
      this.addGridDropZone();
    }
  }

  addGridDropZone() {
    const dropZoneParams = this.rightApi.getRowDropZoneParams({
      onDragStop: (params) => {
        const nodes = params.nodes;

        this.leftApi.applyTransaction({
          remove: nodes.map(function (node) {
            return node.data;
          }),
        });
      },
    });

    this.leftApi.addRowDropZone(dropZoneParams!);
  }

  onExcelExport() {
    const spreadsheets = [];

    spreadsheets.push(
      this.leftApi.getSheetDataForExcel({ sheetName: "Athletes" })!,
      this.rightApi.getSheetDataForExcel({ sheetName: "Selected Athletes" })!,
    );

    exportMultipleSheetsAsExcel({
      data: spreadsheets,
      fileName: "ag-grid.xlsx",
    });
  }
}
```

[Live example: Excel Export - Multiple Sheets with Multiple Grids](https://www.ag-grid.com/examples/excel-export-multiple-sheets/excel-export-multiple-sheets-multiple-grids/angular)

## API

### API Methods

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getSheetDataForExcel` | `Function` |  |  | This is method to be used to get the grid's data as a sheet, that will later be exported either by `getMultipleSheetsAsExcel()` or `exportMultipleSheetsAsExcel()`. Module: [`ExcelExportModule`](https://www.ag-grid.com/angular-data-grid/modules/). |
| `exportMultipleSheetsAsExcel` | `Function` |  |  | Downloads an Excel export of multiple sheets in one file. Module: [`ExcelExportModule`](https://www.ag-grid.com/angular-data-grid/modules/). |
| `getMultipleSheetsAsExcel` | `Function` |  |  | Similar to `exportMultipleSheetsAsExcel`, except instead of downloading a file, it will return a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) to be processed by the user. Module: [`ExcelExportModule`](https://www.ag-grid.com/angular-data-grid/modules/). |
