SimpleExcelExporter 1.5.0

dotnet add package SimpleExcelExporter --version 1.5.0
                    
NuGet\Install-Package SimpleExcelExporter -Version 1.5.0
                    
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="SimpleExcelExporter" Version="1.5.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SimpleExcelExporter" Version="1.5.0" />
                    
Directory.Packages.props
<PackageReference Include="SimpleExcelExporter" />
                    
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 SimpleExcelExporter --version 1.5.0
                    
#r "nuget: SimpleExcelExporter, 1.5.0"
                    
#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 SimpleExcelExporter@1.5.0
                    
#: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=SimpleExcelExporter&version=1.5.0
                    
Install as a Cake Addin
#tool nuget:?package=SimpleExcelExporter&version=1.5.0
                    
Install as a Cake Tool

SimpleExcelExporter

NuGet NuGet pre-releases CI License

Small focused C# library for exporting .NET objects to .xlsx files. Built on top of DocumentFormat.OpenXml, it trades the SDK's full flexibility for a much simpler API aimed at one specific use case: turning a list of annotated POCOs into a spreadsheet.

The generated files open in:

  • Microsoft Excel (Windows + macOS)
  • LibreOffice Calc
  • Google Sheets (up to its 10 M-cell quota)
  • Apple Numbers — since 1.5.0 the output is strict ECMA-376 compliant

Installation

dotnet add package SimpleExcelExporter

Target framework: .NET 8.

Two ways to use it

Annotate your model classes with attributes from SimpleExcelExporter.Annotations, then let the exporter discover the structure via reflection.

using SimpleExcelExporter;
using SimpleExcelExporter.Annotations;
using SimpleExcelExporter.Definitions;

public class Player
{
    [CellDefinition(CellDataType.String)]
    [Header(typeof(TeamRes), "PlayerNameColumnName")]
    [Index(1)]
    public string? PlayerName { get; set; }

    [CellDefinition(CellDataType.Date)]
    [Header(typeof(TeamRes), "DateOfBirthColumnName")]
    [Index(2)]
    public DateTime? DateOfBirth { get; set; }

    [CellDefinition(CellDataType.Number)]
    [Header(typeof(TeamRes), "NumberOfVictoryColumnName")]
    [Index(3)]
    public int? NumberOfVictory { get; set; }
}

public class Team
{
    private ICollection<Player>? _players;

    [SheetName(typeof(TeamRes), "SheetName")]
    [EmptyResultMessage(typeof(TeamRes), "EmptyResultMessage")]
    public ICollection<Player> Players => _players ??= new HashSet<Player>();
}

// …and then:
var team = new Team { Players = { /* … */ } };
using var stream = new FileStream("team.xlsx", FileMode.Create);
new SpreadsheetWriter(stream, team).Write();

Header labels come from a resource file (TeamRes.resx) so the same workbook can be exported in several languages.

See the full worked example at SimpleExcelExporterExample.

2. WorkbookDfn — explicit, attribute-free

If annotating your domain classes is not an option, build a WorkbookDfn by hand and pass that to the writer. You keep full control of sheet names, column ordering, cell types, and data.

var workbook = new WorkbookDfn();
var sheet = new WorksheetDfn("Players");
workbook.Worksheets.Add(sheet);

sheet.ColumnHeadings.Cells.Add(new CellDfn("Name"));
sheet.ColumnHeadings.Cells.Add(new CellDfn("Date of birth"));

var row = new RowDfn();
row.Cells.Add(new CellDfn("Alexandre", cellDataType: CellDataType.String));
row.Cells.Add(new CellDfn(new DateTime(1974, 2, 1), cellDataType: CellDataType.Date));
sheet.Rows.Add(row);

using var stream = new FileStream("players.xlsx", FileMode.Create);
new SpreadsheetWriter(stream, workbook).Write();

A more complete example is in src/ConsoleApp/Program.cs.

Supported attributes

Attribute Applied on Purpose
[SheetName] property returning IEnumerable<T> Localised sheet name from a resource file
[EmptyResultMessage] idem Message shown in the sheet when the collection is empty
[Header] property Localised column header
[Index] property Column order within a sheet (1-indexed)
[CellDefinition] property Cell data type (Date, Number, Boolean, Percentage, Time, String)
[MultiColumn] property of collection type Expands a sub-collection into repeating columns
[IgnoreFromSpreadSheet] property Skip this property during export

What's in the generated XLSX?

Output conforms to ECMA-376 strict mode since 1.5.0:

  • Every <c> carries r="A1"-style references (Apple Numbers requires it).
  • Non-empty string cells route through xl/sharedStrings.xml (deduplicated).
  • Empty cells are omitted from the sheet XML — readers infer the position (matches Excel's native output).
  • Default style attributes (s="0", t="n") are omitted to keep files compact.
  • docProps/core.xml is populated with dc:creator, dcterms:created, dcterms:modified.
  • Deterministic writes when running under CI (ContinuousIntegrationBuild=true), plus a companion .snupkg with Source Link for step-into-source debugging.

Performance and file-size characteristics

On a 1 M-row annotated fixture (see BENCHMARK_RESULTS.md for the full table and methodology):

  • Runtime is dominated by the reflection walk of annotated objects (~60 % of total) rather than the XML write.
  • Files sit ~100 % larger than the pre-1.5.0 output — the price of the mandatory r="A1" attribute on every cell. Three spec-conformant optimisations (skip empty cells, omit default s="0", omit default t="n") partially offset this and keep a 1 M × 20 fixture under Google Sheets' 100 MB upload limit.

A reproducible benchmark harness is at scripts/benchmark.sh.

Repository layout

src/
  SimpleExcelExporter/         the library (published as the NuGet package)
  ConsoleApp/                  runnable harness used for manual + perf checks
test/
  SimpleExcelExporterTests/    48 NUnit tests (unit + OOXML compliance + behaviour)
scripts/
  benchmark.sh                 perf & file-size benchmark across library versions
.github/
  workflows/                   CI (on push/PR) and Release (on tag)
  dependabot.yml               weekly NuGet + Actions dependency scans

Releasing

Version bumps, NuGet publication, and GitHub Releases are driven entirely by pushing a v* tag that matches <Version> in the csproj. See RELEASING.md for the step-by-step flow, SemVer guidance, and troubleshooting.

License

LGPL-3.0-or-later.

Product Compatible and additional computed target framework versions.
.NET 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.

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.5.0 100 4/21/2026
1.5.0-alpha.3 52 4/21/2026
1.5.0-alpha.2 46 4/21/2026
1.5.0-alpha.1 53 4/21/2026
1.4.4 1,861 11/26/2024
1.4.3 2,068 9/23/2024
1.4.3-alpha 135 9/23/2024
1.4.2 254 8/27/2024
1.4.2-alpha.1 110 8/27/2024
1.4.2-alpha 177 8/21/2024
1.4.1 275 6/7/2024
1.4.1-alpha.2 106 6/7/2024
1.4.1-alpha.1 120 6/6/2024
1.4.1-alpha 158 6/6/2024
1.4.0 501 6/3/2024
1.4.0-alpha 173 6/3/2024
1.3.1 317 8/29/2023
1.3.0 278 8/28/2023
1.2.3 407 3/9/2023
1.2.2 409 3/8/2023
Loading failed