EPPlus icon indicating copy to clipboard operation
EPPlus copied to clipboard

Disable custom labels in LoadFromCollection

Open swmal opened this issue 1 year ago • 0 comments

Initially reported as a comment in #1042 ,

Issue description

I brought in the new EPPlus version and it ended up throwing an error when trying to run LoadFromCollection: "Table Table1 Column Phone Number does not have a unique name.". This is due to having multiple "Phone Number" display values on different properties. Looking into this more the unique column requirement seems to come from excel tables.

The problem for us lies in the potential breaking change of bringing in the new package version. We've thought some ideas below that could help until we are ready to fully implement these display label changes.

Is it possible to disable custom labels set via Display/DisplayName/Description attributes and always use the property name? Is it possible to have the underlying value in the excel table header be the property name, while the visible value is the display name? Thank you for any input.

Cause of this error

EPPlus has never allowed column names/headers in a table to have the same value (it will throw an Exception indicating that column names/headers must be unique). The reason for that the reporter get this error in EPPlus 7 is most likely that we recently have added support for the DisplayNameAttribute, previously we only supported the DisplayAttribute and the DescriptionAttribute.

Solution options

1. Use HeaderParsingType

We could add a new member of the HeaderParsingType enum and make the enum a flag that can be used via the LoadFromCollectionOptions class. Example:

sheet.Cells["C1"].LoadFromCollection(items, c => {
    c.PrintHeaders = true;
    c.HeaderParsingType = HeaderParsingTypes.CamelCaseToSpace | HeaderParsingTypes.IgnoreAllAttributes;
});

This will ignore all Description, Display, DisplayName and EPPlusTableColumn attributes and always build the headers from the property names.

2. Add a boolean property for ignoring attributes.

sheet.Cells["C1"].LoadFromCollection(items, c => {
    c.PrintHeaders = true;
    c.HeaderParsingType = HeaderParsingTypes.CamelCaseToSpace;
    c.IgnoreAllAttrbutesForHeaders = true;
});

This will ignore all Description, Display, DisplayName and EPPlusTableColumn attributes and always build the headers from the property names.

3. Ignore per property via EPPlusTableColumnAttribute

Add a new boolean property IgnoreHeaderAttributes to the EPPlusTableColumnAttribute.

[EPPlusTable(PrintHeaders = true)]
public class MyClass
{
   [EPPlusTableColumn(IgnoreHeaderAttributes = true)]
   public string Name { get; set; }
}

This will ignore all Description, Display, DisplayName and EPPlusTableColumn on a specific property only.

4. Use Excel's built in logic

Implement Excel's internal logic for handling multiple column names with the same name which is to prepend the name with a number, i.e. "PhoneNumber1", "PhoneNumber2", etc.

5. Don't change the behaviour

Do nothing to change the current behaviour and clarify how this works in the docs. The downside for users will be that they want to use DataAnnotation attributes such as Description, Display and DisplayName for other purposes than export data to EPPlus, for example in ASP.NET MVC.

swmal avatar Feb 20 '24 15:02 swmal