Skip to content

Releases: sveinungf/spreadcheetah

v1.19.0

03 Nov 21:55
Compare
Choose a tag to compare

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 the SuppressWarnings option on the WorksheetRowGenerationOptions 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

15 Sep 09:53
Compare
Choose a tag to compare

Features

  • Source generator: Columns can now be created from custom type properties when they have declared a CellValueConverter (#73). Thanks to @Ashymonth for the contribution!

v1.17.0

07 Sep 22:52
Compare
Choose a tag to compare

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 the CellValueConverter attribute. More details with an example in the wiki. Thanks to @Ashymonth for the contribution!
  • StyledCell and Cell now have new constructors so they can be created from DataCell.

Performance improvements

  • Minor improvements to generated IL for SpreadsheetUtility methods.

v1.16.0

30 Jun 22:31
Compare
Choose a tag to compare

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 of Spreadsheet.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;
    // 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);
    In case you need to use 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;
    var loremIpsum = new LoremIpsum { Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." };
    await spreadsheet.AddAsRowAsync(loremIpsum, LoremIpsumContext.Default.LoremIpsum);
    In this example, the value in cell A1 will be 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 use ReadOnlyMemory<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

12 May 20:57
Compare
Choose a tag to compare

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 new InheritColumns 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 setting DefaultColumnOrder on the InheritColumns attribute, or by using the ColumnOrder attribute directly on the properties. Thanks to @Ashymonth for the contribution!

  • String cells can now be created from ReadOnlyMemory<char> in addition to string. New constructors have been added to Cell, StyledCell, and DataCell.

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

17 Mar 12:37
Compare
Choose a tag to compare

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 key Header_FirstName from resource file MyResources.resx:
    [ColumnHeader(typeof(MyResources), nameof(MyResources.Header_FirstName))]
    public string FirstName { get; }
    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 Spreadsheet.AddHeaderRowAsync. This feature is not just limited to resource files, and can also similarly reference other public static properties.

v1.13.1

27 Feb 20:38
0f1113b
Compare
Choose a tag to compare

Bug fixes

  • Fixed an issue where a buffer could end up being too small for escaped XML characters.

v1.13.0

25 Feb 15:38
Compare
Choose a tag to compare

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 the ColumnHeader 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 on SpreadCheetahOptions.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

09 Dec 10:24
Compare
Choose a tag to compare

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.

v1.11.0

02 Sep 14:09
Compare
Choose a tag to compare

Features

  • Support for adding a note to a cell with Spreadsheet.AddNote(string cellReference, string noteText). Currently plain-text notes without styling are supported.
  • Added utility method SpreadsheetUtility.TryParseColumnName. It will try to parse a column name (e.g. A) to its column number (e.g. 1).
  • The Style class now has a Format property that is intended to replace the NumberFormat property. Previously there was an issue that a format could automatically use one of the locale dependent standard formats from Excel, even if the user wanted to specify a custom format. The Format property allows for explicitly specifying whether the number format should be a custom or a standard one. Thanks to @AlexVallat for the contribution!

Breaking changes

  • The NumberFormat property on Style has been marked as obsolete. Existing code should migrate to use the Format property instead, either by using Format = NumberFormat.Standard(...) to use one of the standard formats from Excel, or Format = NumberFormat.Custom(...) to use a custom format.

Other changes