Create Excel files in Blazor

With GemBox.Spreadsheet you can build Blazor applications that read, write, edit, process, and convert Excel workbooks. The following live demos show how you can create Blazor apps that generate Excel files and download them to your browser.

Create Excel files in Blazor Server App

The following example shows how you can create a Blazor Server application that:

  1. Exports tabular data from a web form to an Excel workbook.
  2. Creates a file of a specified format like XLSX, XLS, ODS, or CSV.
  3. Downloads the generated file with a downloadFileFromStream JS function (see ASP.NET Core Blazor file downloads).
Exporting tabular data and generating XLSX file in Blazor Server app
Screenshot of submitted web form and created Excel workbook
@page "/"
@inject IJSRuntime JS
@using BlazorServerApp.Data
@using System.IO
@using GemBox.Spreadsheet

<h1>Report generator [Blazor Server App]</h1>

<EditForm Model="model" OnSubmit="CreateSpreadsheet">
    <table>
        <thead>
            <tr>
                <th>Id</th>
                <th>Name</th>
                <th>Salary [$]</th>
            </tr>
        </thead>
        <tbody>
            @{ int index = 0;}
            @foreach (var item in model.Items)
            {
                <tr>
                    <td><InputNumber @bind-Value="item.Id" class="form-control" readonly /></td>
                    <td><InputText @bind-Value="item.Name" class="form-control" /></td>
                    <td><InputNumber @bind-Value="item.Salary" class="form-control" /></td>
                </tr>
                ++index;
            }
        </tbody>
    </table>
    <div class="col-1 my-2" style="min-width:75px">
        <InputSelect @bind-Value="model.Format" class="form-control">
            @foreach (string format in model.FormatMappingDictionary.Select(item => item.Key))
            {
                <option value="@format">@format</option>
            }
        </InputSelect>
    </div>
    <button class="btn btn-primary" type="submit">Create</button>
</EditForm>

@code {
    private ReportModel model = new();

    private async Task CreateSpreadsheet()
    {
        SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");

        // Create new workbook.
        var workbook = new ExcelFile();
        var worksheet = workbook.Worksheets.Add("Report");

        // Format sheet.
        worksheet.PrintOptions.PrintGridlines = true;

        // Format rows and columns.
        worksheet.Rows[0].Style.HorizontalAlignment = HorizontalAlignmentStyle.Center;
        worksheet.Rows[0].Style.Font.Weight = ExcelFont.BoldWeight;
        worksheet.Columns[0].SetWidth(40, LengthUnit.Pixel);
        worksheet.Columns[1].SetWidth(100, LengthUnit.Pixel);
        worksheet.Columns[2].SetWidth(100, LengthUnit.Pixel);
        worksheet.Columns[2].Style.NumberFormat = @"\$\ #,##0";

        // Create header row.
        worksheet.Cells["A1"].Value = nameof(ReportItemModel.Id);
        worksheet.Cells["B1"].Value = nameof(ReportItemModel.Name);
        worksheet.Cells["C1"].Value = nameof(ReportItemModel.Salary);

        // Create data rows.
        for (int r = 1; r <= this.model.Items.Count; r++)
        {
            ReportItemModel item = this.model.Items[r - 1];
            worksheet.Cells[r, 0].Value = item.Id;
            worksheet.Cells[r, 1].Value = item.Name;
            worksheet.Cells[r, 2].Value = item.Salary;
        }

        // Save spreadsheet in specified file format.
        var stream = new MemoryStream();
        workbook.Save(stream, model.Options);

        // Download file.
        using var streamRef = new DotNetStreamReference(stream);
        await JS.InvokeVoidAsync("downloadFileFromStream", $"BlazorServerOutput.{this.model.Format.ToLower()}", streamRef);
    }
}
using System.Collections.Generic;
using GemBox.Spreadsheet;

namespace BlazorServerApp.Data
{
    public class ReportModel
    {
        public IList<ReportItemModel> Items { get; } = new List<ReportItemModel>()
        {
            new ReportItemModel() { Id = 100, Name = "John Doe", Salary = 3600 },
            new ReportItemModel() { Id = 101, Name = "Jane Doe", Salary = 7200 },
            new ReportItemModel() { Id = 102, Name = "Fred Nurk", Salary = 2580 },
            new ReportItemModel() { Id = 103, Name = "Hans Meier", Salary = 3200 },
            new ReportItemModel() { Id = 104, Name = "Ivan Horvat", Salary = 4100 },
            new ReportItemModel() { Id = 105, Name = "Jean Dupont", Salary = 6850 },
            new ReportItemModel() { Id = 106, Name = "Mario Rossi", Salary = 4400 }
        };
        public string Format { get; set; } = "XLSX";
        public SaveOptions Options => this.FormatMappingDictionary[this.Format];
        public IDictionary<string, SaveOptions> FormatMappingDictionary => new Dictionary<string, SaveOptions>()
        {
            ["XLSX"] = new XlsxSaveOptions(),
            ["XLS"] = new XlsSaveOptions(),
            ["ODS"] = new OdsSaveOptions(),
            ["PDF"] = new PdfSaveOptions(),
            ["HTML"] = new HtmlSaveOptions() { EmbedImages = true },
            ["MHTML"] = new HtmlSaveOptions() { HtmlType = HtmlType.Mhtml },
            ["CSV"] = new CsvSaveOptions(CsvType.CommaDelimited),
            ["TXT"] = new CsvSaveOptions(CsvType.TabDelimited),
            ["XPS"] = new XpsSaveOptions(),
            ["PNG"] = new ImageSaveOptions(ImageSaveFormat.Png),
            ["JPG"] = new ImageSaveOptions(ImageSaveFormat.Jpeg),
            ["BMP"] = new ImageSaveOptions(ImageSaveFormat.Bmp),
            ["GIF"] = new ImageSaveOptions(ImageSaveFormat.Gif),
            ["TIF"] = new ImageSaveOptions(ImageSaveFormat.Tiff)
        };
    }

    public class ReportItemModel
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public int Salary { get; set; }
    }
}

Note that saving to XPS and image formats (like PNG and JPG) currently works only on Blazor Server applications that are hosted on Windows Server. To export an XPS or image file, you need to use a Windows-specific TFM in the project file. Besides the .NET Core Runtime, you also need a .NET Windows Desktop Runtime installed on the server.

Create Excel files in Blazor WebAssembly App

The following example shows how you can create a Blazor WebAssembly application that:

  1. Exports tabular data from a web form to an Excel workbook.
  2. Creates a file of a specified format like XLSX, XLS, ODS, or CSV.
  3. Downloads the generated file with a downloadFileFromStream JS function (see ASP.NET Core Blazor file downloads).
Exporting tabular data and generating PDF report in Blazor WebAssembly app
Screenshot of submitted web form and created PDF report
@page "/"
@inject IJSRuntime JS
@using BlazorWebAssemblyApp.Data
@using System.IO
@using GemBox.Spreadsheet

<h1>Report generator [Blazor WebAssembly App]</h1>

<EditForm Model="model" OnSubmit="CreateSpreadsheet">
    <table>
        <thead>
            <tr>
                <th>Id</th>
                <th>Name</th>
                <th>Salary [$]</th>
            </tr>
        </thead>
        <tbody>
            @{ int index = 0;}
            @foreach (var item in model.Items)
            {
                <tr>
                    <td><InputNumber @bind-Value="item.Id" class="form-control" readonly /></td>
                    <td><InputText @bind-Value="item.Name" class="form-control" /></td>
                    <td><InputNumber @bind-Value="item.Salary" class="form-control" /></td>
                </tr>
                ++index;
            }
        </tbody>
    </table>
    <div class="col-1 my-2" style="min-width:75px">
        <InputSelect @bind-Value="model.Format" class="form-control">
            @foreach (string format in model.FormatMappingDictionary.Select(item => item.Key))
            {
                <option value="@format">@format</option>
            }
        </InputSelect>
    </div>
    <button class="btn btn-primary" type="submit">Create</button>
</EditForm>

@code {
    private ReportModel model = new();

    private async Task CreateSpreadsheet()
    {
        SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");

        // Add embedded resource fonts, required for saving to PDF.
        FontSettings.FontsBaseResourceLocation = "/Fonts/";

        // Create new workbook.
        var workbook = new ExcelFile();
        var worksheet = workbook.Worksheets.Add("Report");

        // Format sheet.
        worksheet.PrintOptions.PrintGridlines = true;

        // Format rows and columns.
        worksheet.Rows[0].Style.HorizontalAlignment = HorizontalAlignmentStyle.Center;
        worksheet.Rows[0].Style.Font.Weight = ExcelFont.BoldWeight;
        worksheet.Columns[0].SetWidth(40, LengthUnit.Pixel);
        worksheet.Columns[1].SetWidth(100, LengthUnit.Pixel);
        worksheet.Columns[2].SetWidth(100, LengthUnit.Pixel);
        worksheet.Columns[2].Style.NumberFormat = @"\$\ #,##0";

        // Create header row.
        worksheet.Cells["A1"].Value = nameof(ReportItemModel.Id);
        worksheet.Cells["B1"].Value = nameof(ReportItemModel.Name);
        worksheet.Cells["C1"].Value = nameof(ReportItemModel.Salary);

        // Create data rows.
        for (int r = 1; r <= this.model.Items.Count; r++)
        {
            ReportItemModel item = this.model.Items[r - 1];
            worksheet.Cells[r, 0].Value = item.Id;
            worksheet.Cells[r, 1].Value = item.Name;
            worksheet.Cells[r, 2].Value = item.Salary;
        }

        // Save spreadsheet in specified file format.
        var stream = new MemoryStream();
        workbook.Save(stream, model.Options);

        // Download file.
        using var streamRef = new DotNetStreamReference(stream);
        await JS.InvokeVoidAsync("downloadFileFromStream", $"BlazorWebAssemblyOutput.{this.model.Format.ToLower()}", streamRef);
    }
}
using System.Collections.Generic;
using GemBox.Spreadsheet;

namespace BlazorWebAssemblyApp.Data
{
    public class ReportModel
    {
        public IList<ReportItemModel> Items { get; } = new List<ReportItemModel>()
        {
            new ReportItemModel() { Id = 100, Name = "John Doe", Salary = 3600 },
            new ReportItemModel() { Id = 101, Name = "Jane Doe", Salary = 7200 },
            new ReportItemModel() { Id = 102, Name = "Fred Nurk", Salary = 2580 },
            new ReportItemModel() { Id = 103, Name = "Hans Meier", Salary = 3200 },
            new ReportItemModel() { Id = 104, Name = "Ivan Horvat", Salary = 4100 },
            new ReportItemModel() { Id = 105, Name = "Jean Dupont", Salary = 6850 },
            new ReportItemModel() { Id = 106, Name = "Mario Rossi", Salary = 4400 }
        };
        public string Format { get; set; } = "PDF";
        public SaveOptions Options => this.FormatMappingDictionary[this.Format];
        public IDictionary<string, SaveOptions> FormatMappingDictionary => new Dictionary<string, SaveOptions>()
        {
            ["XLSX"] = new XlsxSaveOptions(),
            ["XLS"] = new XlsSaveOptions(),
            ["ODS"] = new OdsSaveOptions(),
            ["PDF"] = new PdfSaveOptions(),
            ["HTML"] = new HtmlSaveOptions() { EmbedImages = true },
            ["MHTML"] = new HtmlSaveOptions() { HtmlType = HtmlType.Mhtml },
            ["CSV"] = new CsvSaveOptions(CsvType.CommaDelimited),
            ["TXT"] = new CsvSaveOptions(CsvType.TabDelimited)
        };
    }

    public class ReportItemModel
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public int Salary { get; set; }
    }
}

Besides installing GemBox.Spreadsheet, for Blazor WebAssembly you'll also need to include its native dependencies. If you are going to create PDF files, the font files need to be present, so you'll need to embed the required font files inside the application itself and specify the FontSettings.FontsBaseResourceLocation property.

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <WasmBuildNative>true</WasmBuildNative>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="GemBox.Spreadsheet" Version="*" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.3" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.3" PrivateAssets="all" />
  </ItemGroup>

  <!-- Add HarfBuzzSharp and SkiaSharp native assets. -->
  <ItemGroup>
    <PackageReference Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="2.8.2.3" />
    <NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\3.1.12\*.a" />
    <PackageReference Include="SkiaSharp.NativeAssets.WebAssembly" Version="2.88.3" />
    <NativeFileReference Include="$(SkiaSharpStaticLibraryPath)\3.1.12\*.a" />
  </ItemGroup>

  <!-- Add Calibri and Calibri Bold embedded fonts. -->
  <ItemGroup>
    <EmbeddedResource Include="Fonts\calibri.ttf" />
    <EmbeddedResource Include="Fonts\calibrib.ttf" />
  </ItemGroup>

</Project>

Host and deploy Blazor

GemBox.Spreadsheet is licensed per individual developer, and the licenses include a royalty-free deployment. You can feel free to build an unlimited number of applications and deploy or distribute them to an unlimited number of services, servers, or end-user machines with no extra cost.

GemBox.Spreadsheet licenses are compatible with SaaS or PaaS solutions, as long as they don't offer similar or competing functionality to our component, or expose our features through an API for use by an unlicensed third party. For more information, please check the EULA.

See also


Next steps

GemBox.Spreadsheet is a .NET component that enables you to read, write, edit, convert, and print spreadsheet files from your .NET applications using one simple API.

Download Buy