Gooseberry.ExcelStreaming 1.8.4

dotnet add package Gooseberry.ExcelStreaming --version 1.8.4
                    
NuGet\Install-Package Gooseberry.ExcelStreaming -Version 1.8.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Gooseberry.ExcelStreaming" Version="1.8.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Gooseberry.ExcelStreaming" Version="1.8.4" />
                    
Directory.Packages.props
<PackageReference Include="Gooseberry.ExcelStreaming" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Gooseberry.ExcelStreaming --version 1.8.4
                    
#r "nuget: Gooseberry.ExcelStreaming, 1.8.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Gooseberry.ExcelStreaming@1.8.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Gooseberry.ExcelStreaming&version=1.8.4
                    
Install as a Cake Addin
#tool nuget:?package=Gooseberry.ExcelStreaming&version=1.8.4
                    
Install as a Cake Tool

Gooseberry.ExcelStreaming

NuGet

Create Excel files with high performance and low memory allocations.

Features

  • Extremely fast streaming write (100 columns * 100 000 rows in 0.58 second, 14Kb allocated memory)
  • Most basic excel column types are supported (incl. hyperlinks)
  • Shared strings, utf8 binary and interpolated strings
  • Cell formatting, styling and merging
  • Basic pictures support
  • Asynchronous compression
  • Used in heavy-load production environment

Create Excel file

await using var file = new FileStream("myExcelReport.xlsx", FileMode.Create);

await using var writer = new ExcelWriter(file, token: cancellationToken);

// optional sheet configuration
var sheetConfig = new SheetConfiguration(
    Columns: [new Column(Width: 10m), new Column(Width: 13m)], // column width
    FrozenColumns: 1, // freeze pane: colums count
    FrozenRows: 3, // freeze pane: rows count
    ShowGridLines: true,
    AutoFilter: "A1:G1" /* or new((1,1), (7,1)) */); // table headers filter. A1-style string or indexes 

await writer.StartSheet("First sheet", sheetConfig);

writer.AddEmptyRows(3); // three empty rows

await foreach(var record in store.GetRecordsAsync(cancellationToken))
{
    await writer.StartRow();

    writer
        .AddEmptyCell() // empty
        .AddEmptyCells(5) // five empty cells
        .AddCell(42) // int
        .AddCell(999_999_999_999_999) // long 
        .AddCell(DateTime.Now) // DateTime
        .AddCell(DateOnly.FromDateTime(DateTime.Now.Date)) // DateOnly
        .AddCell(123.765M) // decimal
        .AddCell(Math.PI) //double (note: very slow)
        .AddCell("string") // string
        .AddCell('#') // char
        .AddCellUtf8String("string"u8) // utf8 string
        .AddCellSharedString("shared"); // shared string
   
    // hyperlink
    writer.AddCell(new Hyperlink("https://[address]", "Label text")); 
    // cell with picture
    writer.AddCellPicture(someStreamOrByteArray, PictureFormat.Jpeg, new Size(100, 130));
}

// Adding picture from stream to "First sheet" placed to
// cell (column 4, row 2, values are zero-based) with fixed size
writer.AddPicture(someStream, PictureFormat.Jpeg, new AnchorCell(3, 1), new Size(100, 130));

// Adding picture from byte array or ReadOnlyMemory<byte> to "First sheet" 
// with top left corner placed in the cell (column 11:row 2, values are zero-based) 
// and right bottom corner is placed in another cell (column 16:row 11)
writer.AddPicture(someByteArray, PictureFormat.Jpeg, new AnchorCell(10, 1), new AnchorCell(15, 10));


await writer.StartSheet("Second sheet");
for (var row = 0; row < 100; row++)
{
   ... //write rows
}

await writer.Complete(); // DisposeAsync method also will call Complete

More examples

IUtf8SpanFormattable support (.net8+)

Effective way to write standard and custom types to cell without string allocation.

//write any IUtf8SpanFormattable value as string cell or numeric cell
//format, format provider and styles are optional

writer.AddCellString(Guid.NewGuid(), ['N']);  

float value = 0.3f;
writer.AddCellNumber(value);

Interpolated strings (.net8+)

Writing interpolated strings to cells without allocations (benchmark).

writer.AddCell($"{person.FirstName} {person.LastName}, age {person.Age}");
writer.AddCell($"Now is {DateTime.Now}");  

Write Excel file to Http response

The data isn't accumulated in memory. It is flushed to Http response streamingly.

Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.Headers.Add("Content-Disposition", $"attachment; filename=fileName.xlsx");

await Response.StartAsync();

await using var writer = new ExcelWriter(Response.BodyWriter.AsStream(), token: cancellationToken);

await writer.StartSheet("Sheet name");
await writer.StartRow();
writer.AddCell(123);

await writer.Complete();

Row Attributes


//add row with specified height
await writer.StartRow(height: 15);

//or specify optional row attributes
await writer.StartRow(new RowAttributes(
    Height: 25, 
    OutlineLevel: 1,
    IsCollapsed: true,
    IsHidden: true)); 

Using styles

// 1. Define styles

var styleBuilder = new StylesSheetBuilder();

staticSomeStyle = styleBuilder.GetOrAdd(
    new Style(
        Format: "0.00%", // or StandardFormat.PercentPrecision2
        Font: new Font(Size: 24, Color: Color.DodgerBlue),
        Fill: new Fill(Color: Color.Crimson, FillPattern.Gray125),
        Borders: new Borders(
            Left: new Border(BorderStyle.Thick, Color.BlueViolet),
            Right: new Border(BorderStyle.MediumDashed, Color.Coral)),
        Alignment: new Alignment(HorizontalAlignment.Center, VerticalAlignment.Center, false)));

// 2. Build styles. We can reuse single style sheet many times to increase performance. 
//    Style sheet is immutable and thread safe.

staticStyleSheet = styleBuilder.Build();

// 3. Using styles

await using var writer = new ExcelWriter(file, staticStyleSheet);

await writer.StartSheet("First sheet");
await writer.StartRow(15); //optional row height specified

writer.AddCell(123, staticSomeStyle);  // all cells support style reference

await writer.Complete();

Format property can be string, int (any valid numFmtId) or StandardFormat enum value

Shared strings

Shared strings decrease the size of the resulting file when it contains repeated strings. It's implemented as unique list of strings, and cell contains only reference to the list index.

// 1. We can use global shared strings table

var tableBuilder = new SharedStringTableBuilder();

staticSharedStringRef1 = tableBuilder.GetOrAdd("String");
staticSharedStringRef2 = tableBuilder.GetOrAdd("Another String");

// 2. Build table

staticSharedStringTable = sharedStringTableBuilder.Build();

// 3. Using shared strings

await using var writer = new ExcelWriter(stream, sharedStringTable: staticSharedStringTable);

await writer.StartSheet("First sheet");
await writer.StartRow();

// using refernce from global table
writer.AddCell(staticSharedStringRef1);  
writer.AddCell(staticSharedStringRef2);  

// using local dictionary automatically maintained in the ExcelWriter instance
writer.AddCellSharedString("Some string from exteranal store");
writer.AddCellSharedString("Some string from exteranal store");

await writer.Complete();

Benchmarks & performance

Benchmarks results and source code.

Please note .net 9 can be 2x faster than .net 8 for some cases.
Benchmarks below use .net 9.0 runtime.

Real world report

100 columns: numbers, dates, strings

RowsCount Mean Allocated
100 972.0 μs 13.96 KB
1000 6,317.1 μs 14 KB
10000 57,972.8 μs 13.89 KB
100000 587,329.5 μs 14.05 KB
500000 2,984,083.0 μs 14.16 KB
OpenXML and SpreadCheetah comparison
Method RowsCount Mean Gen0 Gen1 Gen2 Allocated
ExcelWriter 100 1.260 ms - - - 14.23 KB
SpreadCheetah 100 1.305 ms - - - 8.61 KB
OpenXml 100 4.258 ms 195.3125 195.3125 195.3125 1216.48 KB
ExcelWriter 1000 7.435 ms - - - 14.32 KB
SpreadCheetah 1000 11.655 ms - - - 8.61 KB
OpenXml 1000 36.718 ms 1214.2857 571.4286 500.0000 16630.37 KB
ExcelWriter 10000 73.579 ms - - - 14.73 KB
SpreadCheetah 10000 112.971 ms - - - 9.11 KB
OpenXml 10000 349.437 ms 10000.0000 3000.0000 3000.0000 142199.43 KB
ExcelWriter 100000 751.082 ms - - - 29.38 KB
SpreadCheetah 100000 1,210.076 ms - - - 27.7 KB
OpenXml 100000 3,570.153 ms 74000.0000 3000.0000 3000.0000 1225984.89 KB

Full results and benchmark code.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.8.4 270 8/25/2025
1.8.3 132 8/13/2025
1.8.2 139 4/25/2025
1.8.1 129 2/6/2025
1.8.0 141 2/4/2025
1.7.0 121 1/12/2025
1.6.0 157 10/28/2024
1.5.5 163 9/19/2024
1.5.4 163 6/23/2024
1.5.3 151 6/3/2024
1.5.2 147 5/30/2024
1.5.1 133 5/10/2024
1.5.0 154 5/3/2024
1.4.1 156 4/27/2024
1.4.0 150 4/26/2024
1.3.0 392 12/25/2022
1.2.0 521 3/31/2022
1.1.0 503 2/25/2022
1.0.2 496 2/18/2022
1.0.1 446 12/15/2021
1.0.0 441 12/13/2021