PanoramicData.SheetMagic
3.0.118
dotnet add package PanoramicData.SheetMagic --version 3.0.118
NuGet\Install-Package PanoramicData.SheetMagic -Version 3.0.118
<PackageReference Include="PanoramicData.SheetMagic" Version="3.0.118" />
<PackageVersion Include="PanoramicData.SheetMagic" Version="3.0.118" />
<PackageReference Include="PanoramicData.SheetMagic" />
paket add PanoramicData.SheetMagic --version 3.0.118
#r "nuget: PanoramicData.SheetMagic, 3.0.118"
#:package PanoramicData.SheetMagic@3.0.118
#addin nuget:?package=PanoramicData.SheetMagic&version=3.0.118
#tool nuget:?package=PanoramicData.SheetMagic&version=3.0.118
PanoramicData.SheetMagic
Easily save/load data to/from Excel (XLSX) documents using strongly-typed C# classes.
Requirements
- .NET 9.0 - This library targets .NET 9.0 only
Installation
dotnet add package PanoramicData.SheetMagic
Features
- ? Strongly-typed - Work with your own C# classes
- ? Simple API - Easy to read and write XLSX files
- ? Multiple sheets - Add and read multiple worksheets
- ? Styling support - Apply table styles to your data
- ? Extended properties - Support for dynamic properties via
Extended<T> - ? Streams and files - Work with both
FileInfoandStreamobjects - ? Type safe - Full support for common .NET types including nullable types
Quick Start
Writing to a file
using PanoramicData.SheetMagic;
// Define your class
public class Thing
{
public string PropertyA { get; set; }
public int PropertyB { get; set; }
}
// Create some data
var things = new List<Thing>
{
new Thing { PropertyA = "Value 1", PropertyB = 1 },
new Thing { PropertyA = "Value 2", PropertyB = 2 },
};
// Write to Excel file
var fileInfo = new FileInfo($"Output {DateTime.UtcNow:yyyyMMddTHHmmss}Z.xlsx");
using var workbook = new MagicSpreadsheet(fileInfo);
workbook.AddSheet(things);
workbook.Save();
Reading from a file
using PanoramicData.SheetMagic;
// Read from Excel file
using var workbook = new MagicSpreadsheet(fileInfo);
workbook.Load();
// Read from default worksheet (first sheet)
var cars = workbook.GetList<Car>();
// Read from a specific worksheet by name
var animals = workbook.GetList<Animal>("Animals");
Advanced Features
Working with Streams
// Write to a stream
using var stream = new MemoryStream();
using (var workbook = new MagicSpreadsheet(stream))
{
workbook.AddSheet(data);
workbook.Save();
}
// Read from a stream
stream.Position = 0;
using var workbook = new MagicSpreadsheet(stream);
workbook.Load();
var items = workbook.GetList<MyClass>();
Multiple Sheets
using var workbook = new MagicSpreadsheet(fileInfo);
workbook.AddSheet(cars, "Cars");
workbook.AddSheet(animals, "Animals");
workbook.AddSheet(products, "Products");
workbook.Save();
Applying Table Styles
var options = new AddSheetOptions
{
TableOptions = new TableOptions
{
Name = "MyTable",
DisplayName = "MyTable1",
XlsxTableStyle = XlsxTableStyle.TableStyleMedium2,
ShowRowStripes = true,
ShowColumnStripes = false,
ShowFirstColumn = false,
ShowLastColumn = false
}
};
workbook.AddSheet(data, "StyledSheet", options);
Custom Property Headers
Use the Description attribute to customize column headers:
using System.ComponentModel;
public class Employee
{
public int Id { get; set; }
[Description("Full Name")]
public string Name { get; set; }
[Description("Hire Date")]
public DateTime HireDate { get; set; }
}
Property Filtering
// Include only specific properties
var options = new AddSheetOptions
{
IncludeProperties = new[] { "Name", "Age", "City" }
};
workbook.AddSheet(people, "Filtered", options);
// Exclude specific properties
var options = new AddSheetOptions
{
ExcludeProperties = new[] { "InternalId", "Password" }
};
workbook.AddSheet(users, "Public", options);
Extended Properties (Dynamic Properties)
Work with objects that have both strongly-typed and dynamic properties:
var extendedData = new List<Extended<MyClass>>
{
new Extended<MyClass>(
new MyClass { Id = 1, Name = "Item 1" },
new Dictionary<string, object?>
{
{ "DynamicProp1", "Value1" },
{ "DynamicProp2", 42 }
}
)
};
workbook.AddSheet(extendedData);
workbook.Save();
// Reading extended properties
var loadedData = workbook.GetExtendedList<MyClass>();
foreach (var item in loadedData)
{
Console.WriteLine($"{item.Item.Name}");
foreach (var prop in item.Properties)
{
Console.WriteLine($" {prop.Key}: {prop.Value}");
}
}
Supported Types
- Primitives:
int,long,short,uint,ulong,ushort - Floating point:
float,double,decimal - Boolean:
bool - Dates:
DateTime,DateTimeOffset - Strings:
string - Enums (stored as text)
- Lists:
List<string>(with configurable delimiter) - All nullable versions of the above
Options
Configure behavior with the Options class:
var options = new Options
{
StopProcessingOnFirstEmptyRow = true,
IgnoreUnmappedProperties = true,
EmptyRowInterpretedAsNull = false,
LoadNullExtendedProperties = true,
ListSeparator = ";"
};
using var workbook = new MagicSpreadsheet(fileInfo, options);
Known Limitations
- JObject Support: Direct
JObjectserialization is not yet supported. UseExtended<object>instead. - Nested Complex Objects: Properties of type
List<ComplexType>cannot be loaded from Excel (though they can be saved as delimited strings). - Large Integer Precision: Excel stores all numbers as doubles, so very large
Int64/UInt64values (nearMaxValue) may lose precision. - Special Values:
double.NaNandnullnullable types are stored as empty strings in Excel.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
See the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- DocumentFormat.OpenXml (>= 2.20.0 && < 3.0.0)
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 |
|---|---|---|
| 3.0.118 | 174 | 12/21/2025 |
| 3.0.117 | 174 | 12/21/2025 |
| 3.0.114 | 279 | 11/23/2025 |
| 3.0.109 | 297 | 10/27/2025 |
| 3.0.106 | 450 | 9/2/2025 |
| 3.0.105 | 572 | 5/21/2025 |
| 3.0.104 | 226 | 5/8/2025 |
| 3.0.101 | 2,746 | 10/16/2023 |
| 3.0.98 | 239 | 10/9/2023 |
| 3.0.96 | 867 | 7/13/2023 |
| 3.0.94 | 255 | 7/12/2023 |
| 3.0.93 | 258 | 7/12/2023 |
| 3.0.91 | 299 | 7/11/2023 |
| 3.0.85 | 1,128 | 1/26/2023 |
| 3.0.81 | 443 | 1/17/2023 |
| 3.0.79 | 661 | 11/8/2022 |
| 3.0.65 | 484 | 11/5/2022 |
| 3.0.62 | 556 | 10/14/2022 |
| 3.0.61 | 520 | 10/14/2022 |
| 3.0.58 | 941 | 3/27/2022 |
| 3.0.57 | 573 | 3/21/2022 |
| 3.0.55 | 591 | 3/21/2022 |
| 3.0.54 | 606 | 3/21/2022 |
| 3.0.46 | 741 | 1/25/2022 |
| 3.0.45 | 883 | 6/28/2021 |
| 3.0.41 | 667 | 1/28/2021 |
| 3.0.38 | 568 | 1/28/2021 |
| 3.0.37 | 569 | 1/26/2021 |
| 3.0.36 | 581 | 1/19/2021 |
| 3.0.35 | 586 | 1/19/2021 |
| 3.0.31 | 682 | 10/26/2020 |
| 3.0.30 | 692 | 10/16/2020 |
| 3.0.29 | 641 | 10/16/2020 |
| 3.0.25 | 679 | 10/16/2020 |
| 3.0.23 | 667 | 10/14/2020 |
| 3.0.22 | 624 | 10/13/2020 |
| 3.0.19 | 666 | 9/27/2020 |
| 3.0.18 | 764 | 9/14/2020 |
| 3.0.11 | 713 | 8/21/2020 |
| 3.0.10 | 665 | 8/20/2020 |
| 3.0.8 | 676 | 8/20/2020 |
| 3.0.5 | 817 | 6/14/2020 |
| 3.0.4 | 724 | 5/12/2020 |
| 3.0.3 | 714 | 4/7/2020 |
| 3.0.2 | 717 | 4/7/2020 |
| 3.0.1 | 695 | 4/7/2020 |
| 2.1.1 | 3,992 | 10/21/2019 |
| 2.1.0 | 876 | 3/31/2019 |
| 2.0.10 | 1,902 | 11/26/2018 |
| 2.0.8 | 1,006 | 10/8/2018 |
| 2.0.7 | 996 | 10/8/2018 |
| 2.0.6 | 1,043 | 9/24/2018 |
| 2.0.5 | 1,035 | 9/20/2018 |
| 2.0.4 | 1,513 | 6/18/2018 |
| 2.0.3 | 1,537 | 5/25/2018 |
| 2.0.2 | 1,508 | 4/26/2018 |
| 2.0.1 | 1,625 | 4/20/2018 |
| 2.0.0 | 1,491 | 4/19/2018 |
| 1.0.6 | 1,290 | 11/1/2017 |
| 1.0.5 | 1,268 | 10/19/2017 |
| 1.0.4 | 1,291 | 10/19/2017 |
| 1.0.3 | 1,537 | 10/19/2017 |
| 1.0.2 | 1,568 | 10/18/2017 |
| 1.0.1 | 1,562 | 10/18/2017 |
| 1.0.0 | 1,545 | 10/18/2017 |
Enhanced logic to handle missing text cells (this can happen with empty strings, if they have no formatting, and is a normal Excel optimization) in the Excel file's XML. These cell values are now returned as empty strings for consistency.