Releases: sveinungf/spreadcheetah
v1.20.0
Features
- Added overloads of
Spreadsheet.AddHeaderRowAsync
that takes a collection of header name strings. They can be used for creating header rows without the need to create cell instances first. - Added support for Data Validation of
DateTime
instances. Thanks to @PhilipeRLeal for the contribution! - The
OverloadResolutionPriority
attribute from .NET 9 has been added toSpreadsheet.AddRowAsync
. This resolves some possible overload ambiguity problems, and allows for some more uses of collection expressions when calling this method. - Arguments for the source generator attributes are now easier to retrieve with reflection. More details in #83. Thanks to @jonsagara for the contribution!
- Number formats in styles can now be of any length. Previously the length was constrained by the length of the internal buffer.
- Added an icon for the NuGet package.
Bug fixes
- Source generator: Warning
SPCH1002
(unsupported type for cell value) will no longer be emitted for properties with theColumnIgnore
attribute.
Performance improvements
- Minor performance improvements related to writing numeric cell values when targeting .NET 8 or later.
Other changes
- The .NET 7 target of the library has been removed, due to it being out of support since May 2024. The library can still be used on .NET 7, but would now use the .NET 6 target instead of the .NET 7 target.
- The .NET Standard 2.0 target of the library no longer depends on
Microsoft.Bcl.HashCode
.
v1.19.0
Features
- Source generator: Support for ignoring properties with the
ColumnIgnore
attribute (#76). An example can be seen in the wiki. - Source generator: Support for specifying cell format on a property with the
CellFormat
attribute (#43). More details with an example in the wiki. - The package now includes a Roslyn analyzer. Previously the source generator itself would emit warnings and errors about incorrect usage (such as combinations of attributes that are not supported), but this is now handled by the Roslyn analyzer instead. This gives the following improvements:
- Diagnostics (e.g. warnings and errors) will now show up with squiggly lines in e.g. Visual Studio. They will also appear without requiring a solution build.
- The severity of the diagnostics can now be configured in an
.editorconfig
file. This should be the preferred way going forward, and for that reason theSuppressWarnings
option on theWorksheetRowGenerationOptions
attribute is now marked as obsolete.
Bug fixes
- Fix for invalid code being generated by the source generator if the
WorksheetRow
attribute type had an indexer.
v1.18.0
v1.17.0
Features
- Support for named styles. A named style is created by passing the name as the second argument to
Spreadsheet.AddStyle
. An optional visibility parameter can also be set that determines if the style name should be visible in Excel. - Source generator: Support for using styling (#44). The
CellStyle
attribute can now be placed on a property to reference a named style. More details with an example in the wiki. - Source generator: Support for custom converters to control how property values are mapped to cells (#67). This is done by implementing
CellValueConverter<T>
and using it on a property with theCellValueConverter
attribute. More details with an example in the wiki. Thanks to @Ashymonth for the contribution! StyledCell
andCell
now have new constructors so they can be created fromDataCell
.
Performance improvements
- Minor improvements to generated IL for
SpreadsheetUtility
methods.
v1.16.0
Features
- Added attribute
ColumnWidth
, which can be used to set fixed column widths when using the source generator. The column widths must be set when starting a worksheet, and a new overload ofSpreadsheet.StartWorksheetAsync
has been added for convenience. Here is an example:public class Book { [ColumnWidth(50)] public string Title { get; set; } [ColumnWidth(20)] public string Author { get; set; } } [WorksheetRow(typeof(Book))] public partial class BookContext : WorksheetRowContext;
In case you need to use// Alternative 1: Use the new overload of StartWorksheetAsync. // It takes the context type generated by the source generator as the second parameter. await spreadsheet.StartWorksheetAsync("Sheet", BookContext.Default.Book); var book = new Book { Title = "A Game of Thrones", Author = "George R. R. Martin" }; await spreadsheet.AddAsRowAsync(book, BookContext.Default.Book);
WorksheetOptions
, you can instead create an instance with the column widths like this:// Alternative 2: Create an instance of WorksheetOptions from the context type. // The WorksheetOptions instance will be created with the column widths from the class attributes. var options = BookContext.Default.Book.CreateWorksheetOptions(); // Can now set additional options, for example frozen columns. options.FrozenColumns = 1; await spreadsheet.StartWorksheetAsync("Sheet", options); var book = new Book { Title = "A Game of Thrones", Author = "George R. R. Martin" }; await spreadsheet.AddAsRowAsync(book, BookContext.Default.Book);
- Added attribute
CellValueTruncate
, which can be used to truncate string values when using the source generator. Here is an example:public class LoremIpsum { [CellValueTruncate(15)] public string Text { get; set; } } [WorksheetRow(typeof(LoremIpsum))] public partial class LoremIpsumContext : WorksheetRowContext;
In this example, the value in cell A1 will bevar loremIpsum = new LoremIpsum { Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }; await spreadsheet.AddAsRowAsync(loremIpsum, LoremIpsumContext.Default.LoremIpsum);
Lorem ipsum dol
(the 15 first characters). A string consisting of fewer characters than the truncate length will have its whole value written to the cell. Internally the implementation will useReadOnlyMemory<char>
to avoid additional string allocations when truncating strings.
Bug fixes
- Fixed a compilation issue for UWP when using .NET Native (issue #58).
WorksheetOptions.Column(int columnNumber)
will no longer allow a column number larger than 16384 (maximum in Excel). An exception will be thrown if attempting to use a larger number.
Performance improvements
- Smaller loop performance improvements in the hot path when adding rows to a worksheet.
- Smaller improvements to memory allocations.
v1.15.0
Features
-
Support for inheritance when using the source generator. By default, the source generator will only create columns from properties defined directly on the type passed to the
WorksheetRow
attribute. With the newInheritColumns
attribute, the base class will be taken into account as well. Here is an example:public class Vehicle { public int Wheels { get; set; } public bool HasEngine { get; set; } } [InheritColumns] public class Car : Vehicle { public string Make { get; set; } public string Model { get; set; } } [WorksheetRow(typeof(Car))] public partial class CarContext : WorksheetRowContext;
In this example, the columns will be created in this order:
Wheels
,HasEngine
,Make
,Model
. The order can be customized by settingDefaultColumnOrder
on theInheritColumns
attribute, or by using theColumnOrder
attribute directly on the properties. Thanks to @Ashymonth for the contribution! -
String cells can now be created from
ReadOnlyMemory<char>
in addition tostring
. New constructors have been added toCell
,StyledCell
, andDataCell
.
Performance improvements
- Most of the
DataCell
constructors are now branchless on .NET 8 and later. - Improved performance of creating
workbook.xml
(metadata file that is part of an XLSX file).
v1.14.0
Features
- Support for creating hidden columns by using
ColumnOptions.Hidden
. Thanks to @BredStik for the contribution! - The
ColumnHeader
attribute can now reference resource files (ResX) to have localized header names. For example, to reference a resource keyHeader_FirstName
from resource fileMyResources.resx
:Note that the resource file must have a public access modifier. A row of header names can then in turn be created in a worksheet by calling[ColumnHeader(typeof(MyResources), nameof(MyResources.Header_FirstName))] public string FirstName { get; }
Spreadsheet.AddHeaderRowAsync
. This feature is not just limited to resource files, and can also similarly reference other public static properties.
v1.13.1
v1.13.0
Features
-
Support for creating a row of header names using the source generator. The new
Spreadsheet.AddHeaderRowAsync
method takes the type created by the source generator as the first argument, and an optional style as the second argument. By default the header name for a property will be the property name. E.g. this property:public string Surname { get; }
will create the header name
"Surname"
. The header name can be customized by using theColumnHeader
attribute. If we want to have header name"Last name"
instead, we can decorate the property with the attribute like this:[ColumnHeader("Last name")] public string Surname { get; }
-
Support for customizing the order between columns when using the source generator. By default, the order is decided by the order of the properties in the class/struct. The order can now be customized by using the
ColumnOrder
attribute. E.g. for these properties:[ColumnOrder(3)] public string LastName { get; } [ColumnOrder(1)] public string FirstName { get; } [ColumnOrder(2)] public string? MiddleName { get; }
the column order would be:
FirstName
,MiddleName
,LastName
. -
Illegal control characters from strings will now be ignored when writing the resulting XLSX file. These are the characters from
\x00
to\x1f
(except CR, LF, and TAB). These control characters can otherwise make the XLSX file invalid.
Performance improvements
-
All
Spreadsheet.AddRowAsync
methods now have improved performance by choosing between different implementations of the cell writers internally based onSpreadCheetahOptions.WriteCellReferenceAttributes
. -
SpreadsheetUtility.GetColumnName
will no longer allocate when the result is a one-character column name. Cases with longer column names also have improved performance, especially when running on .NET 8 or later. -
The source generator should now have better performance as well, and the source generator pipeline is now cachable. This should lead to a smaller impact on compile time for projects that are using the source generator. Thanks to Andrew Lock for his excellent article series about source generators!
v1.12.0
Features
- Support for adding images that are embedded into the spreadsheet. An example of how to do this can be seen in the wiki. Currently only PNG images are supported.
- The source generator now supports creating cells from
DateTime
properties. Thanks to @Misiu for the contribution! - The source generator now also supports creating cells from
Nullable<T>
properties (e.g.int?
). Thanks to @Misiu for the contribution! - Greatly reduced memory allocations for data validations, cell merges, and notes by using pooled arrays internally.
- Other smaller performance improvements, where most of these take effect when targeting .NET 7 or later.
- The library is now being marked as Native AOT compatible when targeting .NET 8 or later.
Other changes
- The .NET Standard 2.1 target of the library has been removed, due to .NET Core 3.1 and .NET 5 being out of support for a while. .NET Standard 2.0 will still be supported going forward.