Prerequisites and Restrictions
Client-side export requires a third-party library called JSZip. In a modular environment, it is included in the DevExtreme dependencies and is activated automatically in most of the applications. However, this does not apply to apps created with Angular CLI 6+. In such apps, you need to register JSZip.
If your app does not use modules, reference the library on your page before the DevExtreme files:
<!-- A CDN link --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js"></script> <!-- or a local script --> <script type="text/javascript" src="js/jszip.min.js"></script> <!-- ... --> <!-- DevExtreme files are referenced here -->
The following restrictions apply when exporting data on the client side:
- Only XLSX files are supported.
- Only visible columns are exported.*
- Modifications made in the cell and row templates, master-detail interface, and data mapping are omitted. 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.
- Client-side export in Safari on MacOS is possible only through a proxy on the server.
User Interaction
A user can click the Export button to save an Excel file with the exported data. Data types, sorting, filtering, and grouping settings are maintained.
To allow a user to export data, set the export.enabled option to true.
jQuery
$(function () { $("#dataGridContainer").dxDataGrid({ // ... export: { enabled: true } }); });
Angular
<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
$(function () { $("#dataGridContainer").dxDataGrid({ export: { enabled: true }, columns: [{ dataField: "id", allowExporting: false }, // ... ] }); });
Angular
<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
$(function () { $("#dataGridContainer").dxDataGrid({ // ... export: { enabled: true, allowExportSelectedData: true, fileName: "NewFileName" } }); });
Angular
<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 ], // ... })
Customize Excel Data
The customizeExcelCell function allows you to change the Excel cell font, background color and fill pattern, as well as align, format, and modify the cell value.
In the code below, Excel cells are customized. Values in the Cost
column are formatted according to values in the Currency
column. Cells in the Product
column have a different appearance if the product costs more than 3000.
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ columns: ['Product', 'Cost'], dataSource: [ { Product: 'Projector', Cost: 3500, Currency: '$' }, { Product: 'Video Player', Cost: 170, Currency: '€' }, // ... ], export: { enabled: true, customizeExcelCell: function(e) { if(e.gridCell.rowType === 'data') { if(e.gridCell.column.dataField == "Cost") { e.numberFormat = `"${e.gridCell.data.Currency}"#,##0.00`; } if(e.gridCell.column.dataField == "Product" && e.gridCell.data.Cost > 3000) { e.fillPatternType = "lightGray"; e.fillPatternColor = "#FF0000"; } } } } }) })
Angular
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { dataSource = [ { Product: 'Projector', Cost: 3500, Currency: '$' }, { Product: 'Video Player', Cost: 170, Currency: '€' }, // ... ]; customizeExcelCell(e) { if(e.gridCell.rowType === 'data') { if(e.gridCell.column.dataField == "Cost") { e.numberFormat = `"${e.gridCell.data.Currency}"#,##0.00`; } if(e.gridCell.column.dataField == "Product" && e.gridCell.data.Cost > 3000) { e.fillPatternType = "lightGray"; e.fillPatternColor = "#FF0000"; } } } } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
<dx-data-grid [columns]="['Product', 'Cost']" [dataSource]="dataSource"> <dxo-export [enabled]="true" [customizeExcelCell]="customizeExcelCell"> </dxo-export> </dx-data-grid>
Hidden columns are ignored on export. If you still need to export them, use the onExporting and onExported functions. Refer to the onExporting description for an example.
Export
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
// Exports selected rows $("#dataGridContainer").dxDataGrid("instance").exportToExcel(true);
Angular
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 ], // ... })
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
$(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
<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.
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
ASPx
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"])); } ?>
If you have technical questions, please create a support ticket in the DevExpress Support Center.
We appreciate your feedback.