1
+ using System ;
2
+ using DocumentFormat . OpenXml ;
3
+ using DocumentFormat . OpenXml . Spreadsheet ;
4
+
5
+ namespace Openize . Cells
6
+ {
7
+ /// <summary>
8
+ /// Provides extension methods for managing worksheet tab colors in Excel workbooks.
9
+ /// </summary>
10
+ public static class WorksheetColorExtensions
11
+ {
12
+ /// <summary>
13
+ /// Sets the tab color for a worksheet using RGB values.
14
+ /// </summary>
15
+ /// <param name="worksheet">The worksheet to set the tab color for.</param>
16
+ /// <param name="red">The red component (0-255).</param>
17
+ /// <param name="green">The green component (0-255).</param>
18
+ /// <param name="blue">The blue component (0-255).</param>
19
+ /// <exception cref="ArgumentNullException">Thrown when worksheet is null.</exception>
20
+ /// <exception cref="ArgumentOutOfRangeException">Thrown when color components are outside the valid range.</exception>
21
+ public static void SetTabColor ( this Worksheet worksheet , byte red , byte green , byte blue )
22
+ {
23
+ if ( worksheet == null )
24
+ throw new ArgumentNullException ( nameof ( worksheet ) ) ;
25
+
26
+ string hexColor = $ "{ red : X2} { green : X2} { blue : X2} ";
27
+ SetTabColorByHex ( worksheet , hexColor ) ;
28
+ }
29
+
30
+ /// <summary>
31
+ /// Sets the tab color for a worksheet using an HTML-style hex color code.
32
+ /// </summary>
33
+ /// <param name="worksheet">The worksheet to set the tab color for.</param>
34
+ /// <param name="hexColor">The hex color code (e.g., "FF0000" for red).</param>
35
+ /// <exception cref="ArgumentNullException">Thrown when worksheet is null.</exception>
36
+ /// <exception cref="ArgumentException">Thrown when hexColor is null, empty, or invalid.</exception>
37
+ public static void SetTabColorByHex ( this Worksheet worksheet , string hexColor )
38
+ {
39
+ if ( worksheet == null )
40
+ throw new ArgumentNullException ( nameof ( worksheet ) ) ;
41
+
42
+ if ( string . IsNullOrEmpty ( hexColor ) )
43
+ throw new ArgumentException ( "Hex color cannot be null or empty." , nameof ( hexColor ) ) ;
44
+
45
+ // Strip # if present
46
+ if ( hexColor . StartsWith ( "#" ) )
47
+ hexColor = hexColor . Substring ( 1 ) ;
48
+
49
+ // Validate hex color format
50
+ if ( ! IsValidHexColor ( hexColor ) )
51
+ throw new ArgumentException ( "Invalid hex color format. Expected format: RRGGBB" , nameof ( hexColor ) ) ;
52
+
53
+ // Get access to the internal OpenXML worksheet
54
+ var openXmlWorksheetPart = GetOpenXmlWorksheetPart ( worksheet ) ;
55
+ if ( openXmlWorksheetPart == null )
56
+ return ;
57
+
58
+ var openXmlWorksheet = openXmlWorksheetPart . Worksheet ;
59
+
60
+ // Get or create the SheetProperties element
61
+ SheetProperties sheetProperties = openXmlWorksheet . GetFirstChild < SheetProperties > ( ) ;
62
+ if ( sheetProperties == null )
63
+ {
64
+ sheetProperties = new SheetProperties ( ) ;
65
+ openXmlWorksheet . InsertAt ( sheetProperties , 0 ) ;
66
+ }
67
+
68
+ // Get or create the TabColor element
69
+ TabColor tabColor = sheetProperties . GetFirstChild < TabColor > ( ) ;
70
+ if ( tabColor == null )
71
+ {
72
+ tabColor = new TabColor ( ) ;
73
+ sheetProperties . AppendChild ( tabColor ) ;
74
+ }
75
+
76
+ // Set the RGB value
77
+ tabColor . Rgb = hexColor ;
78
+
79
+ // Save the changes
80
+ openXmlWorksheet . Save ( ) ;
81
+ }
82
+
83
+ /// <summary>
84
+ /// Gets the tab color of a worksheet as RGB values.
85
+ /// </summary>
86
+ /// <param name="worksheet">The worksheet to get the tab color from.</param>
87
+ /// <param name="red">Output parameter to receive the red component.</param>
88
+ /// <param name="green">Output parameter to receive the green component.</param>
89
+ /// <param name="blue">Output parameter to receive the blue component.</param>
90
+ /// <returns>True if a tab color is set; otherwise, false.</returns>
91
+ /// <exception cref="ArgumentNullException">Thrown when worksheet is null.</exception>
92
+ public static bool GetTabColor ( this Worksheet worksheet , out byte red , out byte green , out byte blue )
93
+ {
94
+ red = 0 ;
95
+ green = 0 ;
96
+ blue = 0 ;
97
+
98
+ if ( worksheet == null )
99
+ throw new ArgumentNullException ( nameof ( worksheet ) ) ;
100
+
101
+ string hexColor = GetTabColorAsHex ( worksheet ) ;
102
+ if ( string . IsNullOrEmpty ( hexColor ) )
103
+ return false ;
104
+
105
+ // Parse the hex color
106
+ red = Convert . ToByte ( hexColor . Substring ( 0 , 2 ) , 16 ) ;
107
+ green = Convert . ToByte ( hexColor . Substring ( 2 , 2 ) , 16 ) ;
108
+ blue = Convert . ToByte ( hexColor . Substring ( 4 , 2 ) , 16 ) ;
109
+
110
+ return true ;
111
+ }
112
+
113
+ /// <summary>
114
+ /// Gets the tab color of a worksheet as a hex color code.
115
+ /// </summary>
116
+ /// <param name="worksheet">The worksheet to get the tab color from.</param>
117
+ /// <returns>The tab color as a hex color code, or null if no tab color is set.</returns>
118
+ /// <exception cref="ArgumentNullException">Thrown when worksheet is null.</exception>
119
+ public static string GetTabColorAsHex ( this Worksheet worksheet )
120
+ {
121
+ if ( worksheet == null )
122
+ throw new ArgumentNullException ( nameof ( worksheet ) ) ;
123
+
124
+ // Get access to the internal OpenXML worksheet
125
+ var openXmlWorksheetPart = GetOpenXmlWorksheetPart ( worksheet ) ;
126
+ if ( openXmlWorksheetPart == null )
127
+ return null ;
128
+
129
+ var openXmlWorksheet = openXmlWorksheetPart . Worksheet ;
130
+
131
+ // Check if tab color is set
132
+ SheetProperties sheetProperties = openXmlWorksheet . GetFirstChild < SheetProperties > ( ) ;
133
+ if ( sheetProperties == null )
134
+ return null ;
135
+
136
+ TabColor tabColor = sheetProperties . GetFirstChild < TabColor > ( ) ;
137
+ if ( tabColor == null || string . IsNullOrEmpty ( tabColor . Rgb ) )
138
+ return null ;
139
+
140
+ return tabColor . Rgb ;
141
+ }
142
+
143
+ /// <summary>
144
+ /// Removes the tab color from a worksheet.
145
+ /// </summary>
146
+ /// <param name="worksheet">The worksheet to remove the tab color from.</param>
147
+ /// <exception cref="ArgumentNullException">Thrown when worksheet is null.</exception>
148
+ public static void RemoveTabColor ( this Worksheet worksheet )
149
+ {
150
+ if ( worksheet == null )
151
+ throw new ArgumentNullException ( nameof ( worksheet ) ) ;
152
+
153
+ // Get access to the internal OpenXML worksheet
154
+ var openXmlWorksheetPart = GetOpenXmlWorksheetPart ( worksheet ) ;
155
+ if ( openXmlWorksheetPart == null )
156
+ return ;
157
+
158
+ var openXmlWorksheet = openXmlWorksheetPart . Worksheet ;
159
+
160
+ // Check if tab color is set
161
+ SheetProperties sheetProperties = openXmlWorksheet . GetFirstChild < SheetProperties > ( ) ;
162
+ if ( sheetProperties == null )
163
+ return ;
164
+
165
+ TabColor tabColor = sheetProperties . GetFirstChild < TabColor > ( ) ;
166
+ if ( tabColor != null )
167
+ {
168
+ tabColor . Remove ( ) ;
169
+ openXmlWorksheet . Save ( ) ;
170
+ }
171
+ }
172
+
173
+ /// <summary>
174
+ /// Validates a hex color code.
175
+ /// </summary>
176
+ /// <param name="hexColor">The hex color code to validate.</param>
177
+ /// <returns>True if the hex color code is valid; otherwise, false.</returns>
178
+ private static bool IsValidHexColor ( string hexColor )
179
+ {
180
+ if ( string . IsNullOrEmpty ( hexColor ) )
181
+ return false ;
182
+
183
+ // Standard hex color format is either RRGGBB or AARRGGBB
184
+ return System . Text . RegularExpressions . Regex . IsMatch ( hexColor , "^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$" ) ;
185
+ }
186
+
187
+ /// <summary>
188
+ /// Gets the OpenXML worksheet part from a Worksheet object.
189
+ /// </summary>
190
+ /// <param name="worksheet">The worksheet to get the OpenXML part from.</param>
191
+ /// <returns>The OpenXML worksheet part, or null if not available.</returns>
192
+ private static DocumentFormat . OpenXml . Packaging . WorksheetPart GetOpenXmlWorksheetPart ( Worksheet worksheet )
193
+ {
194
+ // Use reflection to access the _worksheetPart field from the Worksheet class
195
+ var fieldInfo = worksheet . GetType ( ) . GetField ( "_worksheetPart" , System . Reflection . BindingFlags . NonPublic | System . Reflection . BindingFlags . Instance ) ;
196
+ if ( fieldInfo == null )
197
+ return null ;
198
+
199
+ return fieldInfo . GetValue ( worksheet ) as DocumentFormat . OpenXml . Packaging . WorksheetPart ;
200
+ }
201
+ }
202
+ }
0 commit comments