SpreadCheetah 1.19.0
dotnet add package SpreadCheetah --version 1.19.0
NuGet\Install-Package SpreadCheetah -Version 1.19.0
<PackageReference Include="SpreadCheetah" Version="1.19.0" />
paket add SpreadCheetah --version 1.19.0
#r "nuget: SpreadCheetah, 1.19.0"
// Install SpreadCheetah as a Cake Addin #addin nuget:?package=SpreadCheetah&version=1.19.0 // Install SpreadCheetah as a Cake Tool #tool nuget:?package=SpreadCheetah&version=1.19.0
SpreadCheetah
SpreadCheetah is a high-performance .NET library for generating spreadsheet (Microsoft Excel XLSX) files.
Features
- Performance (see benchmarks below)
- Low memory allocation (see benchmarks below)
- Async APIs
- No dependency to Microsoft Excel
- Targeting .NET Standard 2.0 for .NET Framework and earlier versions of .NET Core
- Targeting .NET 6 and newer for more optimizations
- Trimmable and NativeAOT compatible
SpreadCheetah is designed to create spreadsheet files in a forward-only manner. That means worksheets from left to right, rows from top to bottom, and row cells from left to right. This allows for creating spreadsheet files in a streaming manner, while also keeping a low memory footprint.
Most basic spreadsheet functionality is supported, such as cells with different data types, basic styling, and formulas. More advanced functionality will be added in future releases. See the list of currently supported spreadsheet functionality in the wiki.
See Releases for release notes. This project adheres to Semantic Versioning.
How to install
SpreadCheetah is available as a package on nuget.org. The NuGet package targets .NET Standard 2.0 as well as newer versions of .NET. The .NET Standard 2.0 version is intended for backwards compatibility (.NET Framework and earlier versions of .NET Core). More optimizations are enabled when targeting newer versions of .NET.
Basic usage
using (var spreadsheet = await Spreadsheet.CreateNewAsync(stream))
{
// A spreadsheet must contain at least one worksheet.
await spreadsheet.StartWorksheetAsync("Sheet 1");
// Cells are inserted row by row.
var row = new List<Cell>
{
new Cell("Answer to the ultimate question:"),
new Cell(42)
};
// Rows are inserted from top to bottom.
await spreadsheet.AddRowAsync(row);
// Remember to call Finish before disposing.
// This is important to properly finalize the XLSX file.
await spreadsheet.FinishAsync();
}
Other examples
- Writing to a file
- Styling basics
- Formula basics
- DateTime and formatting
- Data Validations
- Adding an embedded image
- Performance tips
Using the Source Generator
Source Generators is a feature in the C# compiler. SpreadCheetah includes a source generator that makes it easier to create rows from objects. It is used in a similar way to the System.Text.Json
source generator:
namespace MyNamespace;
// A plain old C# class which we want to add as a row in a worksheet.
// The source generator will pick the properties with public getters.
// The order of the properties will decide the order of the cells.
public class MyObject
{
public string Question { get; set; }
public int Answer { get; set; }
}
The source generator will be instructed to generate code by defining a partial class like this:
using SpreadCheetah.SourceGeneration;
namespace MyNamespace;
[WorksheetRow(typeof(MyObject))]
public partial class MyObjectRowContext : WorksheetRowContext;
During build, the type will be analyzed and an implementation of the context class will be created. We can then create a row from an object by calling AddAsRowAsync
with the object and the context type as parameters:
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream);
await spreadsheet.StartWorksheetAsync("Sheet 1");
var myObj = new MyObject
{
Question = "How many Rings of Power were there?",
Answer = 20
};
await spreadsheet.AddAsRowAsync(myObj, MyObjectRowContext.Default.MyObject);
await spreadsheet.FinishAsync();
Here is a peek at part of the code that was generated for this example. As you can see, the generated code also takes advantage of using a pooled array to avoid memory allocations:
// <auto-generated />
private static async ValueTask AddAsRowInternalAsync(Spreadsheet spreadsheet, MyObject obj, CancellationToken token)
{
var cells = ArrayPool<DataCell>.Shared.Rent(2);
try
{
cells[0] = new DataCell(obj.Question);
cells[1] = new DataCell(obj.Answer);
await spreadsheet.AddRowAsync(cells.AsMemory(0, 2), token).ConfigureAwait(false);
}
finally
{
ArrayPool<DataCell>.Shared.Return(cells, true);
}
}
The source generator can generate rows from classes, records, and structs. It can be used in all supported .NET versions, including .NET Framework, however the C# version must be 8.0 or greater. More features of the source generator can be seen in the wiki.
Benchmarks
The benchmark results here have been collected using BenchmarkDotNet with the following system configuration:
BenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.4894/22H2/2022Update)
Intel Core i5-8600K CPU 3.60GHz (Coffee Lake), 1 CPU, 6 logical and 6 physical cores
.NET SDK 9.0.100-preview.7.24407.12
[Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
.NET 6.0 : .NET 6.0.33 (6.0.3324.36610), X64 RyuJIT AVX2
.NET 8.0 : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
.NET Framework 4.8 : .NET Framework 4.8.1 (4.8.9261.0), X64 RyuJIT VectorSize=256
InvocationCount=1 UnrollFactor=1
These libraries have been used in the comparison benchmarks: | Library | Version | |--------------------------------------------------------|--------:| | SpreadCheetah | 1.18.0 | | Open XML SDK | 2.20.0 | | ClosedXML | 0.102.3 | | EPPlusFree | 4.5.3.8 |
Disclaimer: The libraries have different feature sets compared to each other. SpreadCheetah can only create spreadsheets, while the other libraries used in this comparison can also open spreadsheets. SpreadCheetah is also a newer library and has been designed from the ground up to utilize many of the newer performance related features in .NET. The other libraries have longer history and need to take backwards compatibility into account. Keep this in mind when evaluating the results.
The code executed in the benchmark creates a worksheet of 20 000 rows and 10 columns filled with string values. Some of these libraries have multiple ways of achieving the same result, but to make this a fair comparison the idea is to use the most efficient approach for each library. The code is available in the Benchmark project.
<details open> <summary><h3>.NET 8</h3></summary>
| Library | Mean | Allocated | |----------------------------|-------------:|--------------:| | SpreadCheetah | 21.22 ms | 6.33 KB | | Open XML (SAX approach) | 185.66 ms | 66 037.32 KB | | EPPlusFree | 358.31 ms | 195 610.91 KB | | Open XML (DOM approach) | 701.17 ms | 182 916.73 KB | | ClosedXML | 739.16 ms | 529 203.20 KB | </details>
<details> <summary><h3>.NET 6</h3></summary>
| Library | Mean | Allocated | |----------------------------|-------------:|--------------:| | SpreadCheetah | 25.05 ms | 6.52 KB | | Open XML (SAX approach) | 234.12 ms | 66 052.24 KB | | EPPlusFree | 407.38 ms | 195 791.84 KB | | Open XML (DOM approach) | 803.30 ms | 182 926.09 KB | | ClosedXML | 874.41 ms | 529 844.80 KB | </details>
<details> <summary><h3>.NET Framework 4.8</h3></summary>
| Library | Mean | Allocated | |----------------------------|-------------:|--------------:| | SpreadCheetah | 72.34 ms | 152.23 KB | | Open XML (SAX approach) | 408.03 ms | 43 317.24 KB | | EPPlusFree | 622.80 ms | 286 141.77 KB | | Open XML (DOM approach) | 1,070.28 ms | 161 067.34 KB | | ClosedXML | 1,319.16 ms | 509 205.80 KB | </details>
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. 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 is compatible. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 1.1.1)
- Microsoft.Bcl.HashCode (>= 1.1.1)
- System.Memory (>= 4.5.5)
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (5)
Showing the top 5 NuGet packages that depend on SpreadCheetah:
Package | Downloads |
---|---|
DNCB.AspNetCoreApi
ASP.NET Core Api |
|
CalendarAnalyser.Extensions.Export.Excel
Package Description |
|
Zeyt.ExcelDocument
Zeyt.ExcelDocument is a C# library that simplifies the creation of Excel documents from object lists... |
|
DNCB.NetCoreFile
Net Core File |
|
DNCB.Files
Net Core File |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.19.0 | 5,213 | 11/3/2024 |
1.18.0 | 24,792 | 9/15/2024 |
1.17.0 | 2,026 | 9/7/2024 |
1.16.0 | 29,613 | 6/30/2024 |
1.15.0 | 8,380 | 5/12/2024 |
1.14.0 | 41,022 | 3/17/2024 |
1.13.1 | 15,678 | 2/27/2024 |
1.13.0 | 1,638 | 2/25/2024 |
1.12.0 | 23,912 | 12/9/2023 |
1.11.0 | 98,549 | 9/2/2023 |
1.10.0 | 46,442 | 6/24/2023 |
1.9.0 | 24,267 | 2/19/2023 |
1.8.0 | 8,598 | 1/14/2023 |
1.7.0 | 7,091 | 11/6/2022 |
1.6.0 | 13,839 | 9/17/2022 |
1.5.0 | 10,235 | 4/23/2022 |
1.4.0 | 5,801 | 6/13/2021 |
1.3.0 | 445 | 2/21/2021 |
1.2.0 | 561 | 11/22/2020 |
1.1.1 | 531 | 10/28/2020 |
1.1.0 | 449 | 10/25/2020 |
1.0.0 | 837 | 9/28/2020 |