Excel exporting in Angular Grid component

17 Sep 202524 minutes to read

The Syncfusion Angular Grid allows exporting data to Excel or CSV formats, making it easy to share or analyze data in spreadsheets.

To enable Excel export, set the allowExcelExport property to true on the Grid. Initiate export with the excelExport method. To use export features, inject ExcelExportService in your AppModule.

To perform a CSV export, use the csvExport method.

Example: Perform Excel or CSV export in the grid:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { GridComponent, ToolbarItems } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid #grid id='Grid' [dataSource]='data' [toolbar]='toolbarOptions' 
               height='272px' [allowExcelExport]='true' (toolbarClick)='toolbarClick($event)'>
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    width=120></e-column>
                    <e-column field='CustomerID' headerText='Customer ID' width=150>
                    </e-column>
                    <e-column field='ShipCity' headerText='Ship City' width=150></e-column>
                    <e-column field='ShipName' headerText='Ship Name' width=150></e-column>
                </e-columns>
                </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[]; 
    public toolbarOptions?: ToolbarItems[];
    @ViewChild('grid') public grid?: GridComponent;

    ngOnInit(): void {
        this.data = data;
        this.toolbarOptions = ['ExcelExport', 'CsvExport'];
    }
    toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === 'Grid_excelexport') { 
            // 'Grid_excelexport' -> Grid component id + _ + toolbar item name
            (this.grid as GridComponent).excelExport();
        }
        else if (args.item.id === 'Grid_csvexport') { 
            // 'Grid_csvexport' -> Grid component id + _ + toolbar item name
            (this.grid as GridComponent).csvExport();
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Show spinner while exporting

Showing a spinner while exporting in the Grid enhances the experience by displaying a spinner during the export process. This feature provides a visual indication of the export progress, improving the understanding of the exporting process.

To show or hide a spinner while exporting the grid, you can utilize the showSpinner and hideSpinner methods provided by the Grid within the toolbarClick event.

The toolbarClick event is triggered when a toolbar item in the Grid is clicked. Within the event handler, the code checks if the clicked item is related with Excel or CSV export, specifically the Grid_excelexport or Grid_csvexport item. If a match is found, the showSpinner method is used on the Grid instance to display the spinner.

To hide the spinner after the exporting is completed, bind the excelExportComplete event and use the hideSpinner method on the Grid instance to hide the spinner.

Example: Show/hide spinner during Excel export:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { GridComponent, ToolbarItems } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid #grid id='Grid' [dataSource]='data'
               [toolbar]='toolbarOptions' height='272px'  [allowExcelExport]='true'
                (excelExportComplete)='excelExportComplete()' 
                (toolbarClick)='toolbarClick($event)'>
                    <e-columns>
                        <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                        width='90'></e-column>
                        <e-column field='ProductName' headerText='Product Name' width='100'>
                        </e-column>
                        <e-column field='ProductID' headerText='Product ID' textAlign='Right' 
                        width='80'></e-column>
                        <e-column field='CustomerName' headerText='Customer Name' width='120'>
                        </e-column>
                    </e-columns>
                </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public toolbarOptions?: ToolbarItems[];
    @ViewChild('grid')  public grid?: GridComponent;

    ngOnInit(): void {
        this.data = data;
        this.toolbarOptions = ['ExcelExport'];
    }
    toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === 'Grid_excelexport') {
            (this.grid as GridComponent).showSpinner();
            (this.grid as GridComponent).excelExport();
        }
    }
    excelExportComplete(): void {
        (this.grid as GridComponent).hideSpinner();
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Binding custom data source while exporting

Export custom data to Excel or CSV—even if not currently used in the Grid—by specifying the dataSource property in the excelExportProperties object.

Example: Export dynamically defined data:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { GridComponent, ToolbarItems, ExcelExportProperties } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid #grid id='Grid' [dataSource]='data' [toolbar]='toolbarOptions' 
               height='272px' [allowExcelExport]='true' 
               (toolbarClick)='toolbarClick($event)'>
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    width=120></e-column>
                    <e-column field='CustomerID' headerText='Customer ID' width=150>
                    </e-column>
                    <e-column field='ShipCity' headerText='Ship City' width=150></e-column>
                    <e-column field='ShipName' headerText='Ship Name' width=150></e-column>
                </e-columns>
                </ejs-grid>`
})

export class AppComponent implements OnInit {

    public data?: object[];
    public toolbarOptions?: ToolbarItems[];
    @ViewChild('grid') public grid?: GridComponent;

    ngOnInit(): void {
        this.data = data;
        this.toolbarOptions = ['ExcelExport'];
    }
    toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === 'Grid_excelexport') { 
            // 'Grid_excelexport' -> Grid component id + _ + toolbar item name
            const excelExportProperties: ExcelExportProperties = {
                dataSource: data
            };
            (this.grid as GridComponent).excelExport(excelExportProperties);
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Exporting with custom aggregate

Export custom aggregate data by setting type to Custom and providing your calculation with customAggregate.

Example: Count the “Brazil” occurrences in the ShipCountry column during export:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService,AggregateService } from '@syncfusion/ej2-angular-grids'

import { Component, ViewChild } from '@angular/core';
import { data } from './datasource';
import { GridComponent } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-navigations';

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService,AggregateService],
standalone: true,
  selector: 'app-root',
  template:`<div class="control-section">
              <ejs-grid #grid id="DefaultExport" [dataSource]="data" [toolbar]="toolbar"
                (toolbarClick)="toolbarClick($event)" [allowExcelExport]="true">
                <e-columns>
                  <e-column field='OrderID' headerText='Order ID' textAlign='right' width=120>
                  </e-column>
                  <e-column field='CustomerID' headerText='Customer ID' width=150></e-column>      
                  <e-column field="Freight" headerText="Freight" width="150" format="C2" 
                    textAlign="Right"></e-column>
                  <e-column field="OrderDate" headerText="Order Date" width="150"
                  format="yMd" textAlign="Right"></e-column>
                  <e-column field="ShipCountry"  headerText="Ship Country" width="150">
                  </e-column>
                </e-columns>
                <e-aggregates>
                  <e-aggregate>
                    <e-columns>
                      <e-column columnName="ShipCountry" type="Custom"
                      [customAggregate]="customAggregateFn">
                        <ng-template #footerTemplate let-data> {{ data.Custom }}</ng-template>
                      </e-column>
                    </e-columns>
                  </e-aggregate>
                </e-aggregates>
              </ejs-grid>
            </div>`
})

export class AppComponent {
  
  public data?: Object[];
  public toolbar?: string[];
  @ViewChild('grid')
  public grid?: GridComponent;

  public ngOnInit(): void {
    this.data = data.slice(0, 20);
    this.toolbar = ['ExcelExport'];
  }
  toolbarClick(args: ClickEventArgs): void {
    if (args.item.id=='DefaultExport_excelexport') {
        (this.grid as GridComponent).excelExport();
    }
  }
  public customAggregateFn = (customData: any) => {
      const brazilCount=customData.result ? customData.result.filter(
        (item: object) => (item as any)['ShipCountry'] === 'Brazil'
      ).length:
    customData.filter(
        (item: object) => (item as any)['ShipCountry'] === 'Brazil'
      ).length;
  return `Brazil Count::${brazilCount}`;
  };
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Exporting with cell and row spanning

Maintain merged cells and rows in your exported Excel using rowSpan and colSpan in the queryCellInfo event. Further customize cell exports with excelQueryCellInfo.

Example: Export a grid with merged cells and rows:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data, columnDataType } from './datasource';
import { GridComponent, ToolbarItems,ExcelQueryCellInfoEventArgs, QueryCellInfoEventArgs, Column, ExcelCell } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

 

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,
    selector: 'app-root',
    template: `<ejs-grid #grid id='Grid'  [dataSource]='data' [toolbar]='toolbarOptions' height='272px' 
               allowExcelExport='true' (toolbarClick)='toolbarClick($event)' 
               (excelQueryCellInfo)="excelQueryCellInfo($event)" (queryCellInfo)="queryCellInfoEvent($event)">
                    <e-columns>
                        <e-column field='OrderID' headerText='Order ID' textAlign='Right' width=90></e-column>
                        <e-column field='CustomerID' headerText='Customer ID' width=100></e-column>
                        <e-column field='Freight' headerText='Freight' width=80></e-column>
                        <e-column field='ShipCity' headerText='Ship City' width=100></e-column>
                        <e-column field='ShipCountry' headerText='Ship Country' width=100></e-column>
                    </e-columns>
                </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public toolbarOptions?: ToolbarItems[];
    public message?: string;
    @ViewChild('grid') public grid?: GridComponent;

    ngOnInit(): void {
        this.data = data;
        this.toolbarOptions=['ExcelExport'];
    }
    toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === 'Grid_excelexport') {
            (this.grid as GridComponent).excelExport();
        }
    }
    queryCellInfoEvent = function (args: QueryCellInfoEventArgs) {

        switch ((args.data as columnDataType).OrderID) {
            case 10248:
                if ((args.column as Column).field === 'CustomerID') {
                    args.rowSpan = 2;
                }
                break;
            case 10250:
                if ((args.column as Column).field === 'CustomerID') {
                    args.colSpan = 2;
                }
                break;
            case 10252:
                if ((args.column as Column).field === 'OrderID') {
                    args.rowSpan = 3;
                }
                break;
            case 10256:
                if ((args.column as Column).field === 'CustomerID') {
                    args.colSpan = 3;
                }
                break;
            case 10261:
                if ((args.column as Column).field === 'Freight') {
                    args.colSpan = 2;
                }
                break;
        }
    }
    excelQueryCellInfo = function ({data,cell,colSpan,column}:ExcelQueryCellInfoEventArgs) {

        switch ((data as columnDataType).OrderID) {
            case 10248:
                if ((column as Column).field === 'CustomerID') {
                   (cell as ExcelCell).rowSpan = 2;
                }
                break;
            case 10250:
                if ((column as Column).field === 'CustomerID') {
                    colSpan = 2;
                }
                break;
            case 10252:
                if ((column as Column).field === 'OrderID') {
                    (cell as ExcelCell).rowSpan  = 3;
                }
                break;
            case 10256:
                if ((column as Column).field === 'CustomerID') {
                    (cell as ExcelCell).colSpan = 3;
                }
                break;
            case 10261:
                if ((column as Column).field === 'Freight') {
                    (cell as ExcelCell).colSpan = 2;
                }
                break;
        }
    };
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

The updateCell method does not support row and column spanning.

Exporting with custom date format

Apply a custom date format to exported columns by setting columns.format.

Example: The OrderDate column is exported as “Sun, May 8, ‘23”:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild  } from '@angular/core';
import { data } from './datasource';
import { GridComponent } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-navigations'

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,
    selector: 'app-root',
    template: `<div class="control-section">
                    <ejs-grid #grid [dataSource]='data' allowPaging='true' 
                    [pageSettings]='pageSettings' [toolbar]='toolbar' 
                    (toolbarClick)='toolbarClick($event)' [allowExcelExport]='true' 
                    [allowPdfExport]='true'>
                        <e-columns>
                            <e-column field='OrderID' headerText='Order ID' width='120' 
                            textAlign='Right' isPrimaryKey='true'></e-column>
                            <e-column field='OrderDate' headerText='Order Date' width='130' 
                            [format]="formatOption" textAlign='Right'></e-column>
                            <e-column field='CustomerID' headerText='Customer ID' width='120'>
                            </e-column>
                            <e-column field='Freight' headerText='Freight' [allowGrouping]="false" 
                            width='120' format='C2' textAlign='Right'></e-column>            
                            <e-column field='ShipCountry' headerText='Ship Country' width='150'>
                            </e-column>
                        </e-columns>
                    </ejs-grid>
                </div>`
})

export class AppComponent  implements OnInit {

    public data?: Object[];
    public toolbar?: string[];
    public pageSettings?: Object;
    public refresh?: Boolean;
    public formatOption?: Object;
    @ViewChild('grid')
    public grid?: GridComponent;

    public ngOnInit(): void {
        this.data = data;
        this.formatOption = { type: 'date', format:"EEE, MMM d, ''yy"};
        this.toolbar = ['ExcelExport'];
        this.pageSettings = { pageCount: 5 };
    }
    toolbarClick(args: ClickEventArgs): void {
         if(args.item.text ==='Excel Export') {
                (this.grid as GridComponent).excelExport();
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Merge duplicate cells in a specific column before exporting

Merge duplicate cells in a column using dataBound for the Grid and excelQueryCellInfo event for export. This improves readability and visual grouping.

Example: Merge duplicate cells in OrderID column:

import { GridModule, ToolbarService, ExcelExportService, FilterService, ExcelQueryCellInfoEventArgs, ExcelExportCompleteArgs } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { GridComponent, ToolbarItems } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
    imports: [GridModule],
    providers: [ExcelExportService, ToolbarService, FilterService],
    standalone: true,
    selector: 'app-root',
    template: `<ejs-grid #grid id='Grid' [dataSource]='data' [toolbar]='toolbarOptions' 
               height='272px' [allowExcelExport]='true' (toolbarClick)='toolbarClick($event)'
               (dataBound)="onDataBound()" (excelQueryCellInfo)="excelQueryCellInfo($event)" (excelExportComplete)="excelExportComplete($event)"
               >
                <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    width=120></e-column>
                    <e-column field='CustomerID' headerText='Customer ID' width=150>
                    </e-column>
                    <e-column field='City' headerText='Ship City' width=150></e-column>
                </e-columns>
                </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public toolbarOptions?: ToolbarItems[];
    public gridcells: HTMLElement | null = null;
    public currentOrderID: number | null = null;
    public rowspanCount = 1;

    @ViewChild('grid') public grid?: GridComponent;

    ngOnInit(): void {
        this.data = data;
        this.toolbarOptions = ['ExcelExport'];
    }
    toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === 'Grid_excelexport') {
            // 'Grid_excelexport' -> Grid component id + _ + toolbar item name
            (this.grid as GridComponent).excelExport();
        }
    }
    onDataBound() {
        let previousData: number | null = null;
        let startRowIndex: number | null = null;
        let endRowIndex: number | null = null;

        let rows = (this.grid as GridComponent).getRows();
        let data = (this.grid as GridComponent).getCurrentViewRecords();

        for (let i = 0, len = rows.length; i < len; i++) {
            if (!previousData) {
                previousData = (data[i] as Order)['OrderID'];
                startRowIndex = parseInt(((rows[i] as HTMLElement).getAttribute("aria-rowindex") as string));
            }
            else if (previousData === (data[i] as Order)['OrderID']) {
                rows[i].children[0].classList.add('e-hide');
            }
            else if (previousData && previousData !== (data[i] as Order)['OrderID']) {
                if ((this.grid as GridComponent).getRows().length > 0 && (this.grid as GridComponent).getRows().length > (startRowIndex as number)) {
                    endRowIndex = parseInt(((rows[i] as HTMLElement).getAttribute("aria-rowindex") as string), 10);
                    let targetRow = (this.grid as GridComponent).getRows()[(startRowIndex as number)];
                    let currentRowChild = rows[i] && rows[i].children[0];
                    if (targetRow && currentRowChild) {
                        let targetCell = [].slice.call(targetRow.querySelectorAll('.e-rowcell')).filter((cell) =>
                            parseInt(((cell as HTMLElement).getAttribute('aria-colindex') as string), 10) === parseInt(((currentRowChild as HTMLElement).getAttribute('aria-colindex') as string))
                        );
                        if (targetCell[0]) {
                            (targetCell[0] as HTMLElement).setAttribute("rowSpan", ((endRowIndex as number) - (startRowIndex as number)).toString());
                        }
                    }
                    previousData = (data[i] as Order)['OrderID'];
                    startRowIndex = parseInt(((rows[i] as HTMLElement).getAttribute("aria-rowindex") as string), 10);
                }
            }
            if (rows[i].children[0].classList.contains("e-hide") || i < len) {
                endRowIndex = parseInt(((rows[i] as HTMLElement).getAttribute("aria-rowindex") as string), 10);
                if (endRowIndex > 0) {
                    let targetRow = (this.grid as GridComponent).getRows()[(startRowIndex as number)];
                    let currentRowChild = rows[i] && rows[i].children[0];
                    if (targetRow && currentRowChild) {
                        let targetCell = [].slice.call(targetRow.querySelectorAll('.e-rowcell')).filter((cell) =>
                            parseInt(((cell as HTMLElement).getAttribute('aria-colindex') as string), 10) === parseInt(((currentRowChild as HTMLElement).getAttribute('aria-colindex') as string))
                        );
                        if (targetCell.length > 0) {
                            (targetCell[0] as HTMLElement).setAttribute("rowSpan", ((endRowIndex as number) - (startRowIndex as number) + 1).toString());
                        }
                    }
                }
            }
        }

    };
    excelQueryCellInfo(args: ExcelQueryCellInfoEventArgs) {

        if (!this.currentOrderID && args.column.field == "OrderID") {
            this.currentOrderID = (args.data as Order)["OrderID"];
            this.gridcells = (args.cell as HTMLElement);
        }
        else if (this.currentOrderID && args.column.field == "OrderID" && this.currentOrderID == (args.data as Order)["OrderID"]) {
            this.rowspanCount++;
        } else if (this.currentOrderID !== (args.data as Order)["OrderID"] && args.column.field == "OrderID") {
            (this.gridcells as HTMLTableCellElement).rowSpan = this.rowspanCount;
            this.currentOrderID = (args.data as Order)["OrderID"];
            this.gridcells = (args.cell as HTMLElement);
            this.rowspanCount = 1;
        }
    };
    excelExportComplete(args: ExcelExportCompleteArgs) {
        this.currentOrderID = null;
        this.gridcells = null;
        this.rowspanCount = 1;
    }
}

interface Order {
    OrderID: number;
    CustomerID: string;
    City: string;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Exporting multiple grids

Exporting multiple grids in the Syncfusion Angular Grid component allows you to export different grids to compare them side by side in external applications on the same or different pages of a Excel. Each grid is identified by its unique ID. You can specify which grid to export by listing their IDs in the exportGrids property.

Same sheet

Export multiple grids to the same Excel worksheet by setting multipleExport.type to AppendToSheet in excelExportProperties. Separate them with blank rows using multipleExport.blankRows.

Example: Export multiple grids to one worksheet:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data, employeeData } from './datasource';
import { GridComponent, ToolbarItems, ExcelExportProperties } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,
    selector: 'app-root',
    template: `<p><b>First Grid:</b></p>
               <ejs-grid #grid1 id='FirstGrid' [dataSource]='firstData' 
               [toolbar]='toolbarOptions' [allowExcelExport]='true'
               (toolbarClick)='toolbarClick($event)' [exportGrids]='exportGrids'>
                    <e-columns>
                        <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                        width=120></e-column>
                        <e-column field='CustomerID' headerText='Customer ID' width=150>
                        </e-column>
                        <e-column field='ShipCity' headerText='Ship City' width=150></e-column>
                        <e-column field='ShipName' headerText='Ship Name' width=150></e-column>
                    </e-columns>
                    </ejs-grid>
                    <p><b>Second Grid:</b></p>
                    <ejs-grid #grid2 id='SecondGrid' [dataSource]='secondData' 
                    [allowExcelExport]='true'>
                    <e-columns>
                        <e-column field='EmployeeID' headerText='Employee ID' textAlign='Right' 
                        width=120></e-column>
                        <e-column field='FirstName' headerText='FirstName' width=150></e-column>
                        <e-column field='LastName' headerText='Last Name' width=150></e-column>
                        <e-column field='City' headerText='City' width=150></e-column>
                    </e-columns>
                </ejs-grid> `
})
export class AppComponent implements OnInit {

    public firstData?: object[];
    public secondData?: object[];
    public toolbarOptions?: ToolbarItems[];
    public exportGrids?: string[];
    @ViewChild('grid1') public firstGrid?: GridComponent;
    @ViewChild('grid2') public secondGrid?: GridComponent;

    ngOnInit(): void {
        this.firstData = data.slice(0, 5);
        this.secondData = employeeData.slice(0, 5);
        this.toolbarOptions = ['ExcelExport'];
        this.exportGrids = ['FirstGrid', 'SecondGrid']
    }
    toolbarClick = (args: ClickEventArgs) => {
        if (args.item.id === 'FirstGrid_excelexport') { 
            // 'Grid_excelexport' -> Grid component id + _ + toolbar item name
            const appendExcelExportProperties: ExcelExportProperties = {
                multipleExport: { type: 'AppendToSheet', blankRows: 2 }
            };
            (this.firstGrid as GridComponent).excelExport(appendExcelExportProperties, true);
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Default multipleExport.blankRows value is 5.

New sheet

Export each grid to a separate worksheet by setting multipleExport.type to NewPage.

Example: Export multiple grids to multiple worksheets:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data, employeeData } from './datasource';
import { GridComponent, ToolbarItems, ExcelExportProperties } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,
    selector: 'app-root',
    template: `<p><b>First Grid:</b></p>
               <ejs-grid #grid1 id='FirstGrid' [dataSource]='firstData' [toolbar]='toolbarOptions' 
               [allowExcelExport]='true' (toolbarClick)='toolbarClick($event)' 
               [exportGrids]='exportGrids'>
                    <e-columns>
                        <e-column field='OrderID' headerText='Order ID' textAlign='Right'
                         width=120></e-column>
                        <e-column field='CustomerID' headerText='Customer ID' width=150>
                        </e-column>
                        <e-column field='ShipCity' headerText='Ship City' width=150></e-column>
                        <e-column field='ShipName' headerText='Ship Name' width=150></e-column>
                    </e-columns>
                    </ejs-grid>
                    <p><b>Second Grid:</b></p>
                    <ejs-grid #grid2 id='SecondGrid' [dataSource]='secondData' 
                    [allowExcelExport]='true'>
                    <e-columns>
                        <e-column field='EmployeeID' headerText='Employee ID' textAlign='Right' 
                        width=120></e-column>
                        <e-column field='FirstName' headerText='FirstName' width=150>
                        </e-column>
                        <e-column field='LastName' headerText='Last Name' width=150>
                        </e-column>
                        <e-column field='City' headerText='City' width=150></e-column>
                    </e-columns>
                </ejs-grid>
                `
})
export class AppComponent implements OnInit {

    public firstData?: object[];
    public secondData?: object[];
    public toolbarOptions?: ToolbarItems[];
    public exportGrids?: string[];
    @ViewChild('grid1') public firstGrid?: GridComponent;
    @ViewChild('grid2') public secondGrid?: GridComponent;

    ngOnInit(): void {
        this.firstData = data.slice(0, 5);
        this.secondData = employeeData.slice(0, 5);
        this.toolbarOptions = ['ExcelExport'];
        this.exportGrids = ['FirstGrid', 'SecondGrid']
    }
    toolbarClick = (args: ClickEventArgs) => {
        if (args.item.id === 'FirstGrid_excelexport') { 
            // 'Grid_excelexport' -> Grid component id + _ + toolbar item name
            const appendExcelExportProperties: ExcelExportProperties = {
                multipleExport: { type: 'NewSheet' }
            };
            (this.firstGrid as GridComponent).excelExport(appendExcelExportProperties, true);
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Multiple grids exporting is not supported on the server side.

Exporting hierarchy grid

Exporting a hierarchy grid in the Syncfusion Angular Grid component allows you to generate a Excel or CSV document that includes the parent grid along with its child grids. This feature is useful when you need to export hierarchical data with its related details.

To achieve this, you can customize the exporting behavior by using the ExcelExportProperties.hierarchyExportMode property of the Grid. This property allows you to specify the exporting behavior for the hierarchy grid. The following options are available:

Mode Behavior
Expanded Exports the master grid with expanded child grids.
All Exports the master grid with all child grids, expanded or not.
None Exports only the master grid without any child grids.

The following example demonstrates how to export hierarchical grid to Excel document. Also change the excelExportProperties.hierarchyExportMode property by using value property of the DropDownList component:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService,DetailRowService, GridComponent,ToolbarItems,ExcelExportProperties,GridModel } from '@syncfusion/ej2-angular-grids'
import { DropDownListAllModule, DropDownListComponent } from '@syncfusion/ej2-angular-dropdowns'
import { Component, OnInit, ViewChild } from '@angular/core';
import { data, employeeData } from './datasource';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
    imports: [GridModule,DropDownListAllModule],
    providers: [ExcelExportService, ToolbarService, DetailRowService],
    standalone: true,
    selector: 'app-root',
    template: `
            <div style="display: flex">
                <label style="padding: 10px 10px 26px 0"> 
                Change the hierarchy export mode: </label>
                <ejs-dropdownlist
                style="margin-top:5px"
                #dropDownList
                index="0"
                width="150"
                [dataSource]="dropDownData"></ejs-dropdownlist>
            </div>
            <ejs-grid #grid id='Grid' [dataSource]='data' [toolbar]='toolbarOptions' 
            [childGrid]='childGrid' height='220px' [allowExcelExport]='true' 
            (toolbarClick)='toolbarClick($event)'>
                <e-columns>
                    <e-column field='EmployeeID' headerText='Employee ID' textAlign='Right' 
                    width=90></e-column>
                    <e-column field='FirstName' headerText='FirstName' width=100>
                    </e-column>
                    <e-column field='LastName' headerText='Last Name' width=100>
                    </e-column>
                    <e-column field='City' headerText='City' width=100></e-column>
                </e-columns>
            </ejs-grid>`
})
export class AppComponent implements OnInit {

    public data?: object[];
    public toolbarOptions?: ToolbarItems[];
    @ViewChild('grid') public grid?: GridComponent;
    @ViewChild('dropDownList')
    public dropDownList?: DropDownListComponent;
    public dropDownData: object[] = [
        { text: 'None', value: 'None' },
        { text: 'Expanded', value: 'Expanded' },
        { text: 'All', value: 'All' },
    ];
    public childGrid: GridModel = {
        dataSource: data,
        queryString: 'EmployeeID',
        columns: [
            {
                field: 'OrderID',
                headerText: 'Order ID',
                textAlign: 'Right',
                width: 90,
            },
            { field: 'CustomerID', headerText: 'Customer ID', width: 100 },
            { field: 'ShipCity', headerText: 'Ship City', width: 100 },
            { field: 'ShipName', headerText: 'Ship Name', width: 110 },
        ],
    };

    ngOnInit(): void {
        this.data = employeeData;
        this.toolbarOptions = ['ExcelExport'];
    }
    toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === 'Grid_excelexport') {
            // 'Grid_Excelexport' -> Grid component id + _ + toolbar item name
            const exportProperties: ExcelExportProperties = {
                hierarchyExportMode: ((this.dropDownList as DropDownListComponent).value as ExcelExportProperties["hierarchyExportMode"] )
            };
            (this.grid as GridComponent).excelExport(exportProperties);
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Format the child grid columns before exporting

Customize child grid columns during export using the exportDetailDataBound event. Set column format such as date formatting.

Example: Format OrderDate as dd/MM/yyyy in the child grid:

import { ViewChild} from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, DetailRowService, GridComponent, ToolbarItems, ExcelExportProperties, GridModel, DetailDataBoundEventArgs, ColumnModel } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { data, employeeData } from './datasource';
import { ClickEventArgs } from "@syncfusion/ej2-angular-navigations";
@Component({
    imports: [ GridModule],
    providers: [ExcelExportService, ToolbarService, DetailRowService],
    standalone: true,
    selector: 'app-root',
    template: `
    <ejs-grid #grid id="Grid" [dataSource]="data" [toolbar]="toolbarOptions" [childGrid]="childGrid" height="220px" [allowExcelExport]="true" (toolbarClick)="toolbarClick($event)" (exportDetailDataBound)="exportDetailDataBound($event)">
        <e-columns>
            <e-column field="EmployeeID" headerText="Employee ID" textAlign="Right" width="90"></e-column>
            <e-column field="FirstName" headerText="FirstName" width="100"></e-column>
            <e-column field="LastName" headerText="Last Name" width="100"></e-column>
            <e-column field="City" headerText="City" width="100"></e-column>
        </e-columns>
    </ejs-grid>`
})
export class AppComponent implements OnInit {
    @ViewChild("grid") public grid?: GridComponent;
    public data?: object[];
    public toolbarOptions?: ToolbarItems[];
    public childGrid: GridModel = {
        dataSource: data,
        queryString: "EmployeeID",
        columns: [
            { field: "OrderID", headerText: "Order ID", textAlign: "Right", width: 90 },
            { field: "CustomerID", headerText: "Customer ID", width: 100 },
            { field: "OrderDate", headerText: "Order Date", width: 120, format: { type: 'date', format: 'dd-MM-yyyy' } },
            { field: "ShipCity", headerText: "Ship City", width: 100 },
        ],
    };
    ngOnInit(): void {
        this.data = employeeData;
        this.toolbarOptions = ["ExcelExport"];
    }
    public exportDetailDataBound(args: DetailDataBoundEventArgs): void {
        // Set the date format for the OrderDate column before exporting.
        ((args.childGrid as GridModel).columns as ColumnModel[])[2].format = 'dd\\/MM\\/yyyy';
    }
    public toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === "Grid_excelexport") {
            const exportProperties: ExcelExportProperties = {
                hierarchyExportMode: 'All',
            };
            (this.grid as GridComponent).excelExport(exportProperties);
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Microsoft Excel supports up to seven levels of outlines. If the nested templates exceed this, outlines are not applied. Microsoft Limitation

Remove header row while exporting

Remove the header row from the exported file by clearing header cells in the excelHeaderQueryCellInfo event and removing the row in the created event.

Example: Export grid data without a header row:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { ExcelCell, ExcelHeaderQueryCellInfoEventArgs, GridComponent, ToolbarItems,ExcelExport  } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';


@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,

    selector: 'app-root',
    template: `<ejs-grid #grid id='Grid' [dataSource]='data' [toolbar]='toolbarOptions' 
               height='272px' [allowExcelExport]='true' (toolbarClick)='toolbarClick($event)' 
               (excelHeaderQueryCellInfo)="excelHeaderQueryCellInfo($event)" 
               (created)=created()>
                    <e-columns>
                    <e-column field='OrderID' headerText='Order ID' textAlign='Right' 
                    width=90></e-column>
                    <e-column field='CustomerID' headerText='Customer ID' 
                    width=100></e-column>
                    <e-column field='OrderDate' headerText='Order Date' 
                    [format]='formatOptions' width=100></e-column>
                    <e-column field='Freight' headerText='Freight' width=80></e-column>
                    </e-columns>
              </ejs-grid>`

})

export class AppComponent implements OnInit {

    public data?: object[];
    public toolbarOptions?: ToolbarItems[];
    public formatOptions?: object;
    @ViewChild('grid') public grid?: GridComponent;

    ngOnInit(): void {
        this.data = data;
        this.toolbarOptions = ['ExcelExport'];
        this.formatOptions = { type: 'date', format: "yMd" };
    }
    toolbarClick(args: ClickEventArgs): void {
        if (args.item.id === 'Grid_excelexport') {
            (this.grid as GridComponent).excelExport();
        }
    }
    excelHeaderQueryCellInfo(args: ExcelHeaderQueryCellInfoEventArgs) {
        (args.gridCell as ExcelCell).value = '';
      }

    created() {
    //   var gridObj = (document.getElementById("Grid")).ej2_instances[0];
      var processGridExportObject =
          ((this.grid as GridComponent).excelExportModule as any).__proto__.processGridExport;
          ((this.grid as GridComponent).excelExportModule as any).__proto__.processGridExport = function (
           gobj:object,
          props:ExcelExport,
          r:boolean
      ) {
          var rows = processGridExportObject.call(this, gobj, props, r);
          rows.shift();
          rows.forEach((item:any, index:number) => {
              item.index = index + 1;
          });
          return rows;
      };
    }
     
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

How to add formula for the cell while exporting

Insert Excel formulas during export using the valueAccessor with excelQueryCellInfo.

Example: Add formulas to exported cells by assigning a formula in excelQueryCellInfo:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ToolbarService, ExcelExportService, FilterService } from '@syncfusion/ej2-angular-grids'

import { Component, ViewChild } from '@angular/core';
import { inventoryData } from './datasource';
import { GridComponent, ToolbarItems, ExcelExportProperties, ExcelQueryCellInfoEventArgs } from '@syncfusion/ej2-angular-grids';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';

@Component({
imports: [
        
        GridModule
    ],

providers: [ExcelExportService, ToolbarService, FilterService],
standalone: true,
  selector: 'app-root',
  template: `
          <ejs-grid #grid id='Grid' [dataSource]='data' [allowPaging]='true' 
            [toolbar]='toolbarOptions' height='272px' [allowExcelExport]='true' 
            (toolbarClick)='toolbarClick($event)' (excelQueryCellInfo)="excelQueryCellInfo($event)">
            <e-columns>
              <e-column field="Inventor" headerText="Inventor Name" width="180" textAlign="Right">
              </e-column>
              <e-column field="NumberofPatentFamilies" headerText="Number of Patent Families" 
              width="180" textAlign="Right"></e-column>
              <e-column field="Country" headerText="Country" width="140" textAlign="Left">
              </e-column>
              <e-column field="Mainfieldsofinvention" headerText="Main fields of invention" 
              width="200" textAlign="Left"></e-column>
              <e-column field="Number of INPADOC patents" headerText="Number of INPADOC patents" 
              width="180" textAlign="Right"></e-column>
              <e-column field="TotalPatents" headerText="Total Patents" [visible]='false' 
              [valueAccessor]="valueAccess" width="120"  textAlign="Right"></e-column>
            </e-columns>
          </ejs-grid>`
})
export class AppComponent {

  public data?: object[];
  public toolbarOptions?: ToolbarItems[];
  @ViewChild('grid') public grid?: GridComponent;

  public ngOnInit(): void {
    this.data = inventoryData;
    this.toolbarOptions = ['ExcelExport'];
  }
  toolbarClick(args: ClickEventArgs): void {
    if (args.item.id === 'Grid_excelexport') {
      // 'Grid_pdfexport' -> Grid component id + _ + toolbar item name
      const excelExportProperties: ExcelExportProperties = {
        includeHiddenColumn: true,
      };
      (this.grid as GridComponent).excelExport(excelExportProperties);
    }

  }
  valueAccess = (field: string, data: Object[]) => {
    const cell = (this.data as Object[]).indexOf(data) + 2;
    return '=E' + cell + '+' + 'B' + cell;
  }
  excelQueryCellInfo(args: ExcelQueryCellInfoEventArgs): void {
    if (args.column.field === 'TotalPatents') {
      args.value = this.valueAccess(args.column.field, (args.data as Object[]));
      (args.cell as CustomExcelCell).formula = args.value;
    }
  } 
} 
interface CustomExcelCell {
  formula: string; 
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Passing additional parameters to the server when exporting

Add extra parameters to the export request using the query property and the toolbarClick event. Use the addParams method to add custom parameters.

Example: Pass recordcount as 15 using addParams:

import { Component, OnInit, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GridModule, ToolbarService, ExcelExportService, GridComponent, ToolbarItems, ExcelExportCompleteArgs } from '@syncfusion/ej2-angular-grids';
import { Query } from '@syncfusion/ej2-data';
import { ClickEventArgs } from '@syncfusion/ej2-navigations';
import { data } from './datasource';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, GridModule],
  providers: [ExcelExportService, ToolbarService],
  template: `<p id="message"></p>
             <ejs-grid #grid id='Grid' [dataSource]='data'[toolbar]='toolbarOptions' height='272px' [allowExcelExport]='true' (excelExportComplete)='excelExportComplete($event)' (toolbarClick)='toolbarClick($event)'>
              <e-columns>
                  <e-column field='OrderID' headerText='Order ID' textAlign='Right' width='120'></e-column>
                  <e-column field='CustomerID' headerText='Customer ID' [visible]='false' width='150'></e-column>
                  <e-column field='ShipCity' headerText='Ship City' width='150'></e-column>
                  <e-column field='ShipName' headerText='Ship Name' width='150'></e-column>
              </e-columns>
             </ejs-grid>
             <p id="message"></p>`
})
export class AppComponent implements OnInit {
  @ViewChild('grid') public grid!: GridComponent;
  public data: object[] = [];
  public toolbarOptions: ToolbarItems[] = ['ExcelExport'];
  public queryClone!: Query;
  public message: string = '';

  public ngOnInit(): void {
    this.data = data;
  }

  public toolbarClick(args: ClickEventArgs): void {
    if (args.item.id === 'Grid_excelexport') {
      this.queryClone = this.grid.query;
      this.grid.query = new Query().addParams('recordcount', '15');
      this.message = `Key: ${this.grid.query.params[0].key} and Value: ${this.grid.query.params[0].value} on ${args.item.text}`;
      this.grid.excelExport();
    }
  }

  public excelExportComplete(args: ExcelExportCompleteArgs): void {
    this.grid.query = this.queryClone;
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Limitations

  • CSV is plain text and does not support formatting features like rotation, font and color customization, column and row spanning, or formulas. It only contains raw data.

See Also