sveinungf / spreadcheetah

SpreadCheetah is a high-performance .NET library for generating spreadsheet (Microsoft Excel XLSX) files.
MIT License
304 stars 17 forks source link

Source generator - Number format #43

Closed darkurse closed 5 days ago

darkurse commented 7 months ago

First of all, thank you for your super fast library :)

Could you add an option to specify the style of the column when using the source generator ?

This will be useful to customize datetime and number formatting on a column basis. Something like a ColumnFormattingAttribute class which takes a StandardNumberFormat for simplicity.

public class Person
{
    [ColumnFormatting(Standard = StandardNumberFormat.NoDecimalPlaces)]
    public int Age { get; set; }

    [ColumnFormatting(Standard = StandardNumberFormat.ShortDate)]
    public DateTime ModifiedAt { get; set; }
}

[WorksheetRow(typeof(Person))]
public partial class PersonRowContext : WorksheetRowContext;

Thank you.

sveinungf commented 7 months ago

Thanks for the feedback! Right now there is no way to use any styling with the source generator. This looks like a useful addition, and so does #31. However, there can be many other use cases for styling that would then need similar attributes. For that reason, I'm considering to first implement a more general purpose approach, so that there is a way to use all supported forms of styling with the source generator. My idea so far is to be able to add named styles to the worksheet first, and then those styles can be referenced with attributes on the properties. Something like [ColumnNamedStyle("My ModifiedAt style")]. Once that is in place, more specific attributes (such as the one you suggest) can be implemented for ease of use.

darkurse commented 7 months ago

That's a great idea ! Where do I sign ?

thank you :)

darkurse commented 7 months ago

Oh, another thing I would consider on top of the styling of the columns is to be able to set the size of the columns automatically.

What I am doing right now for this scope is do this thing manually :

public class Person
{
    [ColumnHeaderInfo(17)]
    public int Age { get; set; }

    [ColumnHeaderInfo(35)]
    public DateTime ModifiedAt { get; set; }
}

[WorksheetRow(typeof(Person))]
public partial class PersonRowContext : WorksheetRowContext;

The attribute

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class ColumnHeaderInfoAttribute(double size) : Attribute
{
    public double Size { get; init; } = size;
}

and then later in the code, to use it

    protected static WorksheetOptions GetWorksheetOptions<T>()
    {
        var props = typeof(T).GetProperties();

        var options = new WorksheetOptions();

        for (var i = 0; i < props.Length; i++)
        {
            var attr = props[i].GetCustomAttributes(typeof(ColumnHeaderInfoAttribute), false);
            if (attr is not null && attr.Length > 0)
            {
                options.Column(i + 1).Width = ((ColumnHeaderInfoAttribute)attr[0]).Size;
            }
        }

        return options;
    }
sveinungf commented 7 months ago

I've created #44 to track support for named styles.

Setting column widths automatically, i.e. having the widths automatically adjusted to fit to the cell contents, is not really possible without having a huge performance hit as far as I can see. See #12 for a more thorough explanation. However, I can add an attribute to set fixed column widths, similarly to what you have implemented using reflection. I've created #45 to track support for that.

sveinungf commented 5 days ago

The CellFormat attribute is now available in version 1.19.0. More details with an example in the wiki.