Back to Devexpress

Export Blazor Grid Data to XLS/XLSX

blazor-405472-components-grid-export-excel-export.md

latest23.0 KB
Original Source

Export Blazor Grid Data to XLS/XLSX

  • Mar 24, 2026
  • 11 minutes to read

Call the ExportToXlsAsync/ExportToXlsxAsync method to export Grid data to an Excel format. The output table maintains groups, sort settings, totals, and group summaries. You can save the result to a stream or download it on the client. The method parameter allows you to configure export settings and customize the sheet’s appearance.

Run Demo: Grid - Export DataView Example: Customize Export Settings

You can also export Grid data to PDF or CSV formats.

Limitations and Specifics

If the Grid is bound to a GridDevExtremeDataSource object, the following limitations apply:

  • You must specify the KeyFieldName property to export only selected rows.
  • The expanded state of groups is not exported and corresponds to the GroupExportMode property value.
  • Grouped data, filtered, and sorted rows may differ in the resulting document. This happens because export depends on database collation. For instance, the same string with different capitalization may form multiple groups in the exported document. The Grid component puts such values into a single group.

Refer to the following article for additional information: Microsoft Excel specifications and limits.

Prevent a Column from Being Exported

The Grid component exports data from all data columns. Set a column’s ExportEnabled property to false to exclude it from data export:

razor
@inject WeatherForecastService ForecastService

<DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
<DxGrid @ref="Grid" Data="@Data">
    <Columns>
        <DxGridDataColumn FieldName="Date" DisplayFormat="D" />
        <DxGridDataColumn FieldName="TemperatureC" Caption="@("Temp. (\x2103)")" />
        <DxGridDataColumn FieldName="TemperatureF" Caption="@("Temp. (\x2109)")" ExportEnabled="false" />
        <DxGridDataColumn FieldName="Forecast" ExportEnabled="false" />
        <DxGridDataColumn FieldName="CloudCover" ExportEnabled="false" />
    </Columns>
</DxGrid>

@code {
    IGrid Grid { get; set; }
    object Data { get; set; }

    protected override void OnInitialized() {
        Data = ForecastService.GetForecast();
    }
    async Task ExportXlsx_Click() {
        await Grid.ExportToXlsxAsync("ExportResult");
    }
}
csharp
using System;

public class WeatherForecast {
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public double TemperatureF => Math.Round((TemperatureC * 1.8 + 32), 2);
    public string Forecast { get; set; }
    public string CloudCover { get; set; }
    public bool Precipitation { get; set; }
}
csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

public class WeatherForecastService {
    private List<WeatherForecast> Forecast { get; set; }

    private static string[] CloudCover = new[] {
        "Sunny", "Partly cloudy", "Cloudy", "Storm"
    };

    Tuple<int, string>[] ConditionsForForecast = new Tuple<int, string>[] {
        Tuple.Create( 22 , "Hot"),
        Tuple.Create( 13 , "Warm"),
        Tuple.Create( 0 , "Cold"),
        Tuple.Create( -10 , "Freezing")
    };

    public WeatherForecastService() {
        Forecast = CreateForecast();
    }

    private List<WeatherForecast> CreateForecast() {
        var rng = new Random();
        DateTime startDate = DateTime.Now;
        return Enumerable.Range(1, 15).Select(index => {
            var temperatureC = rng.Next(-10, 30);
            return new WeatherForecast {
                Date = startDate.AddDays(index),
                TemperatureC = temperatureC,
                CloudCover = CloudCover[rng.Next(0, 4)],
                Precipitation = Convert.ToBoolean(rng.Next(0, 2)),
                Forecast = ConditionsForForecast.First(c => c.Item1 <= temperatureC).Item2
            };
        }).ToList();
    }

    public IEnumerable<WeatherForecast> GetForecast() {
        return Forecast.ToArray();
    }
    // ...
}
csharp
// ...
builder.Services.AddSingleton<WeatherForecastService>();

Display/Hide Exported Columns

The Grid exports data of all data columns unless you assign false to a column’s ExportEnabled property. A column whose Visible property is set to false is exported as a hidden column (has a zero width).

Handle the CustomizeColumn event and specify the Column.IsHidden argument to display/hide columns in the output document:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        CustomizeColumn = CustomizeColumn,
    });
}
void CustomizeColumn(GridExportCustomizeColumnEventArgs e) {
    // Shows every grid column in the output document
    e.Column.IsHidden = false;
}

Specify Column Width

Use the ExportWidth property to specify the column width in the exported document:

razor
@inject WeatherForecastService ForecastService

<DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
<DxGrid @ref="Grid" Data="@Data">
    <Columns>
        <DxGridDataColumn FieldName="Date" DisplayFormat="D" />
        <DxGridDataColumn FieldName="TemperatureC" Caption="@("Temp. (\x2103)")" ExportWidth="100"/>
        <DxGridDataColumn FieldName="TemperatureF" Caption="@("Temp. (\x2109)")" ExportWidth="100" />
        <DxGridDataColumn FieldName="Forecast" />
        <DxGridDataColumn FieldName="CloudCover" />
    </Columns>
</DxGrid>

@code {
    IGrid Grid { get; set; }
    object Data { get; set; }

    protected override void OnInitialized() {
        Data = ForecastService.GetForecast();
    }
    async Task ExportXlsx_Click() {
        await Grid.ExportToXlsxAsync("ExportResult");
    }
}

Note that Microsoft Excel performs width calculation in characters. When you open a document, Excel converts the column width in pixels to characters. The column width in characters differs on a machine with more than 100% DPI - the resulting width in pixels differs from the specified value. You can handle the CustomizeColumn action and specify the Column.WidthInCharacters property to set the column width in characters.

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        CustomizeColumn = CustomizeColumn,
    });
}
void CustomizeColumn(GridExportCustomizeColumnEventArgs e) {
    if (e.FieldName.Contains("Temperature"))
        e.Column.WidthInCharacters = 10;
}

Hide Column Headers

Set the ExportColumnHeaders property to false to exclude the column header row from export:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        ExportColumnHeaders = false,
    });
}

Handle the CustomizeSheet event and use its Sheet.PrintTitles argument to repeat specific rows and columns on every printed page:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(GridExportCustomizeSheetEventArgs e) {
    // Prints the first row on every page.
    e.Sheet.PrintTitles.SetRows(0, 0);
}

Expand/Collapse Group Rows

The Grid exports group rows and preserves their expanded state. Use the GroupExportMode property to expand/collapse all rows in the exported document:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        GroupExportMode = GridGroupExportMode.ExpandAll,
    });
}

To prevent group row export, set the GroupExportMode property to None.

Export Selected Rows

Assign true to the ExportSelectedRowsOnly property to export only selected rows:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        ExportSelectedRowsOnly = true,
    });
}

Once enabled, the Grid ignores group settings and exports records as flat data. To preserve row hierarchy, set SelectedRowsExportMode to KeepGrouping:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        ExportSelectedRowsOnly = true,
        SelectedRowsExportMode = GridSelectedRowsExportMode.KeepGrouping
    });
}

Export Display Text

The Grid component exports cell values. To export display text instead of values, set the ExportDisplayText property to true:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        ExportDisplayText = true,
    });
}

Export Unbound Expressions as Formulas

When exporting unbound columns, the Grid component exports cell values instead of functions. To export UnboundExpression formulas, set the ExportUnboundExpressionAsFunction property to true:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        ExportUnboundExpressionAsFunction = true,
    });
}

Color Cells

Handle the CustomizeCell event and use the Formatting argument to format exported cells:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        CustomizeCell = CustomizeCell
    });
}
void CustomizeCell(GridExportCustomizeCellEventArgs e) {
    // Applies bold formatting to column headers
    if (e.AreaType == DevExpress.Export.SheetAreaType.Header)
        e.Formatting.Font = new XlCellFont() { Bold = true };
    if (e.AreaType == DevExpress.Export.SheetAreaType.DataArea) {
        var forecast = (WeatherForecast)e.DataItem;
        // Highlights rows with low/high TemperatureC values
        if (forecast.TemperatureC < 10)
            e.Formatting.BackColor = System.Drawing.Color.LightBlue;
        if (forecast.TemperatureC > 20)
            e.Formatting.BackColor = System.Drawing.Color.PaleVioletRed;
    }
    // Applies the specified settings.
    e.Handled = true;
}

Add Headers and Footers

Handle CustomizeSheetHeader and CustomizeSheetFooter events to add rows above and below Grid content in the output document. For additional information, see event descriptions.

Freeze Columns and Rows

Handle the CustomizeSheet event and use its Sheet.SplitPosition argument to freeze rows and columns displayed above and to the left of the specified cell:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(GridExportCustomizeSheetEventArgs e) {
    // Freezes the left column and top two rows
    e.Sheet.SplitPosition = new DevExpress.Export.Xl.XlCellPosition(1, 2);
}

Filter Exported Data

Handle the RowExporting event to filter exported data. Set the Cancel event argument to true to exclude the row from the exported document:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("Cool Weather", new GridXlExportOptions() {
            RowExporting = RowExporting,
        });
}
void RowExporting(GridRowExportingEventArgs e) {
    if (!e.IsGroupRow) {
        if ((int)e.GetRowValue("TemperatureC") < 10) {
            e.Cancel = true;
        }
    }
}

Specify the Sheet Name

Use the SheetName property to specify the sheet name for the output document:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        SheetName = "Forecasts"
    });
}

Alternatively, you can handle the CustomizeSheet event and use its Sheet.Name argument to customize the sheet name:

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(GridExportCustomizeSheetEventArgs e) {
    e.Sheet.Name = "Forecasts";
}

Specify Document Print Settings

Handle the CustomizeSheet event and use the Sheet argument to access the following print settings:

PageSetupSpecifies page layout and printing options for a worksheet.PrintOptionsSpecifies options that control how a worksheet is printed.PrintTitlesSpecifies rows and columns to be repeated on every printed page.PrintAreaSpecifies the cell range to be printed.PageMarginsSpecifies page margins used to align the worksheet content on a printed page.

csharp
async Task ExportXlsx_Click() {
    await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(GridExportCustomizeSheetEventArgs e) {
    e.Sheet.PageSetup.PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
    e.Sheet.PageSetup.PageOrientation = DevExpress.Export.Xl.XlPageOrientation.Landscape;
    e.Sheet.PrintTitles.SetColumns(0, 0);
    e.Sheet.PrintTitles.SetRows(0, 0);
    e.Sheet.PageMargins = new DevExpress.Export.Xl.XlPageMargins();
    e.Sheet.PageMargins.PageUnits = DevExpress.Export.Xl.XlPageUnits.Centimeters;
    e.Sheet.PageMargins.Left = 3.0;
    e.Sheet.PageMargins.Right = 3.0;
    e.Sheet.PageMargins.Top = 3.25;
    e.Sheet.PageMargins.Bottom = 3.25;
}

Display Loading Indicators

Use DevExpress Blazor Loading Panel to display a loading indicator during export operations:

razor
@inject WeatherForecastService ForecastService

<DxLoadingPanel @bind-Visible="@PanelVisible"
                IsContentBlocked="true"
                ApplyBackgroundShading="true"
                IndicatorAreaVisible="false"
                Text="Exporting Document...">
    <DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
    <DxGrid @ref="Grid" Data="@Data">
        <Columns>
            <DxGridDataColumn FieldName="Date" DisplayFormat="D" />
            <DxGridDataColumn FieldName="TemperatureC" Caption="@("Temp. (\x2103)")" />
            <DxGridDataColumn FieldName="TemperatureF" Caption="@("Temp. (\x2109)")" />
            <DxGridDataColumn FieldName="Forecast" />
            <DxGridDataColumn FieldName="CloudCover" />
        </Columns>
    </DxGrid>
</DxLoadingPanel>

@code {
    IGrid Grid { get; set; }
    object Data { get; set; }
    bool PanelVisible { get; set; } = false;

    protected override void OnInitialized() {
        Data = ForecastService.GetForecast();
    }
    async Task ExportXlsx_Click() {
        PanelVisible = true;
        await Task.Yield();
        await Grid.ExportToXlsxAsync("ExportResult");
        PanelVisible = false;
    }
}

Use the Hyperlink argument of the CustomizeCell event to insert hyperlinks in data cells:

razor
@inject TestModelService TestModelService

<DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
<DxGrid @ref="Grid" Data="@Data">
    <Columns>
        <DxGridDataColumn FieldName=@nameof(TestModel.Name) Width="280" />
        <DxGridDataColumn FieldName=@nameof(TestModel.Universal) Width="100" />
        <DxGridDataColumn FieldName=@nameof(TestModel.DXperience) Width="100" />
        <DxGridDataColumn FieldName=@nameof(TestModel.WinForms) Width="100" />
        <DxGridDataColumn FieldName=@nameof(TestModel.WPF) Width="100" />
        <DxGridDataColumn FieldName=@nameof(TestModel.ASP) Caption="ASP.NET and Blazor" Width="100" />
        <DxGridDataColumn FieldName=@nameof(TestModel.DevExtreme) Caption="DevExtreme Complete" Width="100" />
    </Columns>
</DxGrid>

@code {
    IGrid Grid { get; set; }
    object Data { get; set; }

    protected override async Task OnInitializedAsync() {
        Data = await TestModelService.GetDataSourceAsync();
    }
    async Task ExportXlsx_Click() {
        await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
            CustomizeCell = CustomizeCell
        });
    }
    void CustomizeCell(GridExportCustomizeCellEventArgs e) {
        if (e.AreaType == DevExpress.Export.SheetAreaType.DataArea && e.ColumnFieldName == "Name") {
            var product = e.DataItem as TestModel;
            e.Hyperlink = product.Url;
            e.Handled = true;
        }
    }
}
csharp
public class TestModel {
    public string Name { get; set; }
    public bool Universal { get; set; }
    public bool DXperience { get; set; }
    public bool WinForms { get; set; }
    public bool WPF { get; set; }
    public bool ASP { get; set; }
    public bool DevExtreme { get; set; }
    public string Url { get; set; }
}
csharp
public class TestModelService {
    private List<TestModel> CreateDataSource() {
        List<TestModel> temp = new List<TestModel>();
        temp.Add(new TestModel() { Name = "WinForms Controls", Universal = true, DXperience = true, WinForms = true, WPF = false, ASP = false, DevExtreme = false, Url = "https://www.devexpress.com/products/net/controls/winforms/" });
        temp.Add(new TestModel() { Name = "WPF Controls", Universal = true, DXperience = true, WinForms = false, WPF = true, ASP = false, DevExtreme = false, Url = "https://www.devexpress.com/products/net/controls/wpf/" });
        temp.Add(new TestModel() { Name = "Blazor UI Components", Universal = true, DXperience = true, WinForms = false, WPF = false, ASP = true, DevExtreme = false, Url = "https://www.devexpress.com/blazor/" });
        temp.Add(new TestModel() { Name = "JavaScript - jQuery, Angular, React, Vue", Universal = true, DXperience = true, WinForms = false, WPF = false, ASP = true, DevExtreme = true, Url = "https://js.devexpress.com/" });
        temp.Add(new TestModel() { Name = "ASP.NET Web Forms Controls and MVC Extensions", Universal = true, DXperience = true, WinForms = false, WPF = false, ASP = true, DevExtreme = false, Url = "https://www.devexpress.com/products/net/controls/asp/" });
        temp.Add(new TestModel() { Name = "Reporting", Universal = true, DXperience = true, WinForms = true, WPF = true, ASP = true, DevExtreme = false, Url = "https://www.devexpress.com/subscriptions/reporting/" });
        temp.Add(new TestModel() { Name = "XPO - ORM Library", Universal = true, DXperience = true, WinForms = true, WPF = true, ASP = true, DevExtreme = true, Url = "https://www.devexpress.com/products/net/orm/" });
        temp.Add(new TestModel() { Name = "XAF - Cross-Platform .NET App UI", Universal = true, DXperience = false, WinForms = false, WPF = false, ASP = false, DevExtreme = false, Url = "https://www.devexpress.com/products/net/application_framework/" });
        return temp;
    }

    private List<TestModel> DataSource { get; set; }
    public TestModelService() {
        DataSource = CreateDataSource();
    }
    public Task<IEnumerable<TestModel>> GetDataSourceAsync(CancellationToken ct = default) {
        return Task.FromResult(DataSource.AsEnumerable());
    }
}
csharp
// ...
builder.Services.AddSingleton<TestModelService>();