Use of custom Table style

Dec 1, 2014 at 3:48 PM
I have a workbook with an existing custom table style. The first issue I ran into is that ClosedXML throws an error when opening an existing workbook where a table uses a custom style. The error is: "Requested value 'StyleName' was not found." and trace:
   at System.Enum.EnumResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument)
   at System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)
   at System.Enum.Parse(Type enumType, String value, Boolean ignoreCase)
   at System.Enum.Parse(Type enumType, String value)
   at ClosedXML.Excel.XLWorkbook.LoadSpreadsheetDocument(SpreadsheetDocument  
As I didn't need to have preexisting tables this was okay. However I can't figure out how to apply my custom theme to a new table.

I suspect that it is currently a limitation, and that the error is related. I believe the code is trying to parse the table Style name and find it within the XLTableTheme Enum.

Is this a current limitation? Is there a workaround for this issue? If there is no plan to support custom table styles directly, is it perhaps possible to catch a Parse error on the table style enum and use a 'default' table style - to allow existing workbooks with custom styles to be opened?

Thanks and kind regards,
Dec 1, 2014 at 5:22 PM
Edited Dec 1, 2014 at 5:23 PM
After looking at the source code, I can confirm my suspicion regarding the source of the error. While it would be amazing if ClosedXML supported custom table styles, it would likely be beneficial in any case to add some error handling such that existing files with custom-styled tables can be opened. Something like:

XLWorkbook_Load.cs
if (dTable.TableStyleInfo != null)
{
    if (dTable.TableStyleInfo.ShowFirstColumn != null)
        xlTable.EmphasizeFirstColumn = dTable.TableStyleInfo.ShowFirstColumn.Value;
    if (dTable.TableStyleInfo.ShowLastColumn != null)
        xlTable.EmphasizeLastColumn = dTable.TableStyleInfo.ShowLastColumn.Value;
    if (dTable.TableStyleInfo.ShowRowStripes != null)
        xlTable.ShowRowStripes = dTable.TableStyleInfo.ShowRowStripes.Value;
    if (dTable.TableStyleInfo.ShowColumnStripes != null)
        xlTable.ShowColumnStripes = dTable.TableStyleInfo.ShowColumnStripes.Value;
    if (dTable.TableStyleInfo.Name != null)
    {
        XLTableTheme theme;
        if (Enum.TryParse(dTable.TableStyleInfo.Name.Value, out theme))                        
            xlTable.Theme = theme;                        
        else                        
            xlTable.Theme = XLTableTheme.None;                                             
    }
    else
        xlTable.Theme = XLTableTheme.None;
}
In this way the Load will succeed even when a custom style is used on a table in the document.
Dec 1, 2014 at 5:51 PM
Sorry for the string of self replies. After further investigating the source code, it seems that the only reason a custom theme is not supported is that the Theme is using an Enum, even though the final output is just the XLTableTheme name as a string in XML.

My recommendation would be to add a ThemeName property that can be set directly or is automatically set to the Enum.GetName value of the Theme property. This way the Load could fall back on setting the ThemeName property when the enum value cannot be parsed and the Save methods could simply use the ThemeName string rather than the GetName as is currently used.

I will submit a patch.