DevExtreme jQuery - Client-Side Exporting

Restrictions

When exporting data on the client side, the following restrictions naturally apply:

  • Only XLSX files are supported.
  • Exported files omit modifications made by the cell and row templates, master-detail interface, and data mapping. You can use calculated columns instead of the latter.
  • Excel limits the number of grouping levels to 7, while in the DataGrid it is unlimited.
  • Excel's data format support is limited to the predefined formats with exception of "largeNumber", "quarterAndYear", "second", "millisecond", "quarter", "hour", and "minute".
  • Client-side exporting in IE9 and Safari on MacOS is possible only through a proxy on the server.

User Interaction

A user clicks the Export button to save an Excel file with the exported data. Data types, sorting, filtering, and grouping settings are maintained.

DevExtreme HTML5 JavaScript DataGrid Export Button

Client-side exporting requires referencing the JSZip library on the page. See the guides in the Installation section for more information. After that, you can enable exporting in the DataGrid by setting the export.enabled option to true.

jQuery
JavaScript
$(function () {
    $("#dataGridContainer").dxDataGrid({
        // ...
        export: {
            enabled: true
        }
    });
});
Angular
HTML
TypeScript
<dx-data-grid ... >
    <dxo-export [enabled]="true"></dxo-export>
</dx-data-grid>
import { DxDataGridModule } from 'devextreme-angular';
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})

You can disable exporting a specific column by setting its allowExporting option to false:

jQuery
JavaScript
$(function () {
    $("#dataGridContainer").dxDataGrid({
        export: {
            enabled: true
        },
        columns: [{
            dataField: "id",
            allowExporting: false
        }, 
            // ...
        ]
    });
});
Angular
HTML
TypeScript
<dx-data-grid ... >
    <dxo-export [enabled]="true"></dxo-export>
    <dxi-column dataField="id" [allowExporting]="false"></dxi-column>
    <!-- ... -->
</dx-data-grid>
import { DxDataGridModule } from 'devextreme-angular';
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})

The resulting file is renamed according to the fileName option, and contains only the selected rows if you set the allowExportSelectedData option to true.

jQuery
JavaScript
$(function () {
    $("#dataGridContainer").dxDataGrid({
        // ...
        export: {
            enabled: true,
            allowExportSelectedData: true,
            fileName: "NewFileName"
        }
    });
});
Angular
HTML
TypeScript
<dx-data-grid ... >
    <dxo-export 
        [enabled]="true"
        [allowExportSelectedData]="true"
        fileName="NewFileName">
    </dxo-export>
</dx-data-grid>
import { DxDataGridModule } from 'devextreme-angular';
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})

View Demo

API

Call exportToExcel(selectionOnly) method to export data programmatically. When the selectionOnly parameter is false, the method exports all rows; when true - only the selected ones.

jQuery
JavaScript
// Exports selected rows
$("#dataGridContainer").dxDataGrid("instance").exportToExcel(true);
Angular
TypeScript
import { ..., ViewChild } from '@angular/core';
import { DxDataGridModule, DxDataGridComponent } from 'devextreme-angular';
// ...
export class AppComponent {
    @ViewChild(DxDataGridComponent) dataGrid: DxDataGridComponent;
    exportSelectedData () {
        this.dataGrid.instance.exportToExcel(true);
    };
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})

You can customize data before exporting by specifying the customizeExportData function. See an example in its description.

Events

The DataGrid raises the following export-related events:

  • exporting
    Allows you to request export details or prevent export. Can also be used to adjust grid columns before exporting.

  • exported
    Allows you to notify an end user when exporting is completed.

  • fileSaving
    Allows you to access the exported data in the BLOB format and/or prevent it from being saved on the user's local storage.

You can handle these events with functions. Assign the handling functions to the onExporting, onExported and onFileSaving options when you configure the widget if they are going to remain unchanged at runtime.

jQuery
JavaScript
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        onExporting: function (e) {
            // Handler of the "exporting" event
        },
        onExported: function (e) {
            // Handler of the "exported" event
        },
        onFileSaving: function (e) {
            // Handler of the "fileSaving" event
        }
    });
});
Angular
HTML
TypeScript
<dx-data-grid ...
    (onExporting)="onExporting($event)"
    (onExported)="onExported($event)"
    (onFileSaving)="onFileSaving($event)">
</dx-data-grid>
import { DxDataGridModule } from 'devextreme-angular';
// ...
export class AppComponent {
    onExporting (e) {
        // Handler of the "exporting" event
    };
    onExported (e) {
        // Handler of the "exported" event
    };
    onFileSaving (e) {
        // Handler of the "fileSaving" event
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})

Otherwise (or if you need several handlers for a single event), subscribe to the export-related events using the on(eventName, eventHandler) method. This approach is more typical of jQuery.

JavaScript
var exportedHandler1 = function (e) {
    // First handler of the "exported" event
};

var exportedHandler2 = function (e) {
    // Second handler of the "exported" event
};

$("#dataGridContainer").dxDataGrid("instance")
    .on("exported", exportedHandler1)
    .on("exported", exportedHandler2);
See Also

Set Up a Server-Side Proxy

If you need the export function in browsers that do not provide an API for saving files (that is, in IE9 and Safari on Mac OS), implement a server-side proxy that streams the resulting file back to an end user in response to a POST request. The proxy implementation is different for each platform.

ASPx

C#
VB
using System;
using System.Web;

namespace ExportService {

    public class ExportHandler : IHttpHandler {
        public void ProcessRequest(HttpContext context) {
            if(context.Request.Form["contentType"] != null && 
               context.Request.Form["fileName"]    != null && 
               context.Request.Form["data"]        != null) {
                context.Response.Clear();
                context.Response.ContentType = context.Request.Form["contentType"].ToString();
                context.Response.Charset = "UTF-8";
                context.Response.Expires = 0;
                context.Response.AppendHeader("Content-transfer-encoding", "binary");
                context.Response.AppendHeader("Content-Disposition", 
                                              "attachment; filename=" + context.Request.Form["fileName"].ToString());
                context.Response.BinaryWrite(Convert.FromBase64String(context.Request.Form["data"].ToString()));
                context.Response.Flush();
                context.Response.End();
            }
        }
        public bool IsReusable {
            get { return false; }
        }
    }

}
Imports System
Imports System.Web

Namespace ExportService

    Public Class ExportHandler
        Implements IHttpHandler

        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            If context.Request.Form("contentType") IsNot Nothing AndAlso
               context.Request.Form("fileName")    IsNot Nothing AndAlso
               context.Request.Form("data")        IsNot Nothing Then
                context.Response.Clear()
                context.Response.ContentType = context.Request.Form("contentType").ToString()
                context.Response.Charset = "UTF-8"
                context.Response.Expires = 0
                context.Response.AppendHeader("Content-transfer-encoding", "binary")
                context.Response.AppendHeader("Content-Disposition", "attachment; filename=" & context.Request.Form("fileName").ToString())
                context.Response.BinaryWrite(Convert.FromBase64String(context.Request.Form("data").ToString()))
                context.Response.Flush()
                context.Response.End()
            End If
        End Sub

        Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property
    End Class

End Namespace

PHP

<?php
    if(!empty($_POST["data"]) && !empty($_POST["contentType"]) && !empty($_POST["fileName"])) {
    header("Access-Control-Allow-Origin: *");
    header("Content-type: {$_POST['contentType']};\n");
    header("Content-Transfer-Encoding: binary");
    header("Content-length: ".strlen($_POST['data']).";\n");
    header("Content-disposition: attachment; filename=\"{$_POST['fileName']}\"");
    die(base64_decode($_POST["data"]));
    } 
?>

Usage

Specify the export.proxyUrl option to make the widget export a file through the proxy.