SpreadCheetah includes a C# Source Generator that simplifies mapping objects (classes, records, or structs) to spreadsheet rows. This avoids manual cell mapping and uses pooled arrays internally for high performance.
1. Define your data model
Create a plain C# class with public getters. The order of properties determines the order of cells in the row.
public class MyObject
{
public string Question { get; set; }
public int Answer { get; set; }
}
2. Define the Row Context
Create a partial class that inherits from WorksheetRowContext and decorate it with the [WorksheetRow] attribute, specifying your data type.
using SpreadCheetah.SourceGeneration;
namespace MyNamespace;
[WorksheetRow(typeof(MyObject))]
public partial class MyObjectRowContext : WorksheetRowContext;
3. Add the object as a row
Use the AddAsRowAsync method, passing your object and the generated context.
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
};
// Use the generated context to map the object to a row
await spreadsheet.AddAsRowAsync(myObj, MyObjectRowContext.Default.MyObject);
await spreadsheet.FinishAsync();
Note: The Source Generator requires C# 12 or greater, but can be used with all supported .NET versions including .NET Framework.
// Example of the generated code pattern (internal implementation detail)
// 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);
// }
// }