Search code examples
openxml

Change Sheet tab color of excel file using Open XML


I want to change the sheet tab color of an excel Xlsx document. I am using the following code but it does not set the sheet color. I get object reference exception when I set the sheet tab color.

public static string filepath = @"C:\Test\Book1.xlsx";
private static void ChangeSheetcolor()
{
    try
    {
        using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(filepath, false))
        {
            WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
            IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
            //my code
            WorksheetPart worksheetPart =
                  GetWorksheetPartByName(spreadSheetDocument, "Sheet1");

            if (worksheetPart != null)
            {
             //   worksheetPart.Worksheet.SheetProperties.TabColor.Rgb = DocumentFormat.OpenXml.HexBinaryValue.FromString("Red");
                worksheetPart.Worksheet.SheetProperties.TabColor.Rgb = DocumentFormat.OpenXml.HexBinaryValue.FromString("#CCCCCC");
                // Save the worksheet.
                worksheetPart.Worksheet.Save();
            }
        }
    }
    catch (Exception ex)
    { 

    }            
}
private static WorksheetPart
     GetWorksheetPartByName(SpreadsheetDocument document,
     string sheetName)
{
    IEnumerable<Sheet> sheets =
       document.WorkbookPart.Workbook.GetFirstChild<Sheets>().
       Elements<Sheet>().Where(s => s.Name == sheetName);
    if (sheets.Count() == 0)
    {
        //does not exist
        return null;
    }
    string relationshipId = sheets.First().Id.Value;
    WorksheetPart worksheetPart = (WorksheetPart)
         document.WorkbookPart.GetPartById(relationshipId);
    return worksheetPart;
}

How to change the sheet tab color using Open XML dlls?


Solution

  • You seem to have 3 issues as far as I can tell. Firstly, the second parameter to the Open method you are calling denotes whether or not the file is editable. You need to pass true here if you wish to edit the file otherwise you'll hit the following exception upon saving the worksheet:

    System.IO.IOException: Cannot get stream with FileMode.Create, FileMode.CreateNew, FileMode.Truncate, FileMode.Append when access is FileAccess.Read.

    Secondly, SheetProperties or TabColor could be null. In the XSD they are defined as

    <xsd:element name="sheetPr" type="CT_SheetPr" minOccurs="0" maxOccurs="1"/>
    

    and

    <xsd:element name="tabColor" type="CT_Color" minOccurs="0" maxOccurs="1"/>
    

    Note both have minOccurs="0" so either could be null. If they are, you can just create new instances and assign them to the Worksheet.

    Finally, the Rgb property is arguably badly named as the documentation states (emphasis mine):

    Standard Alpha Red Green Blue color value (ARGB).
    The possible values for this attribute are defined by the ST_UnsignedIntHex simple type (§18.18.86).

    18.18.86 goes on to say (again, emphasis mine):

    This simple type's contents have a length of exactly 8 hexadecimal digit(s).

    Assuming you want a solid color you can set the alpha channel to FF. You also shouldn't include the leading # so for a solid red for example you should use "FFFF0000". More details on ARGB values can be found on this question.

    Putting that all together your code becomes something like this:

    public static string filepath = @"C:\Test\Book1.xlsx";
    private static void ChangeSheetcolor()
    {
        try
        {
            using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(filepath, false))
            {
                WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
                IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
                //my code
                WorksheetPart worksheetPart =
                        GetWorksheetPartByName(spreadSheetDocument, "Sheet1");
    
                if (worksheetPart != null)
                {
                    //create the SheetProperties if it doesn't exist
                    if (worksheetPart.Worksheet.SheetProperties == null)
                        worksheetPart.Worksheet.SheetProperties = new SheetProperties();
                    //create the TabColor if it doesn't exist
                    if (worksheetPart.Worksheet.SheetProperties.TabColor == null)
                        worksheetPart.Worksheet.SheetProperties.TabColor = new TabColor();
                    //this will set the tab color to Red
                    //note the value is an ARGB not an RGB
                    worksheetPart.Worksheet.SheetProperties.TabColor.Rgb = DocumentFormat.OpenXml.HexBinaryValue.FromString("FFFF0000");
                    // Save the worksheet.
                    worksheetPart.Worksheet.Save();
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }