NanoXLSX.Reader 3.0.0-rc.5
Loading...
Searching...
No Matches
ThemeReader.cs
1/*
2 * NanoXLSX is a small .NET library to generate and read XLSX (Microsoft Excel 2007 or newer) files in an easy and native way
3 * Copyright Raphael Stoeckli © 2026
4 * This library is licensed under the MIT License.
5 * You find a copy of the license in project folder or on: http://opensource.org/licenses/MIT
6 */
7
8using System;
9using System.IO;
10using System.Xml;
11using NanoXLSX.Colors;
12using NanoXLSX.Interfaces;
13using NanoXLSX.Interfaces.Reader;
14using NanoXLSX.Registry;
15using NanoXLSX.Registry.Attributes;
16using NanoXLSX.Themes;
17using IOException = NanoXLSX.Exceptions.IOException;
18
20{
24 [NanoXlsxPlugIn(PlugInUUID = PlugInUUID.ThemeReader)]
25 public class ThemeReader : IPluginBaseReader
26 {
27
28 private MemoryStream stream;
29
30 #region properties
34 public Workbook Workbook { get; set; }
38 public IOptions Options { get; set; }
42 public Action<MemoryStream, Workbook, string, IOptions, int?> InlinePluginHandler { get; set; }
43 #endregion
44
45 #region constructors
49 internal ThemeReader()
50 {
51 }
52 #endregion
53
54 #region methods
62 public void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions, Action<MemoryStream, Workbook, string, IOptions, int?> inlinePluginHandler)
63 {
64 this.stream = stream;
65 this.Workbook = workbook;
66 this.Options = readerOptions;
67 this.InlinePluginHandler = inlinePluginHandler;
68 }
69
74 public void Execute()
75 {
76 try
77 {
78 using (stream) // Close after processing
79 {
80 XmlDocument xr = new XmlDocument() { XmlResolver = null };
81 using (XmlReader reader = XmlReader.Create(stream, new XmlReaderSettings() { XmlResolver = null }))
82 {
83 xr.Load(reader);
84 string prefix = ReaderUtils.DiscoverPrefix(xr, "theme");
85 XmlNodeList themes = ReaderUtils.GetElementsByTagName(xr, "theme", prefix);
86 string themeName = ReaderUtils.GetAttribute(themes[0], "name"); // If this fails, something is completely wrong
87 Workbook.WorkbookTheme = new Theme(themeName);
88 ColorScheme colorScheme = new ColorScheme();
89 Workbook.WorkbookTheme.Colors = colorScheme;
90 XmlNodeList colors = ReaderUtils.GetElementsByTagName(xr, "clrScheme", prefix);
91
92 foreach (XmlNode color in colors)
93 {
94 string colorSchemeName = ReaderUtils.GetAttribute(color, "name", "");
95 Workbook.WorkbookTheme.Colors.Name = colorSchemeName;
96 XmlNodeList colorNodes = color.ChildNodes;
97 foreach (XmlNode colorNode in colorNodes)
98 {
99 string name = colorNode.LocalName;
100 switch (name)
101 {
102 case "dk1":
103 colorScheme.Dark1 = ParseColor(colorNode.ChildNodes);
104 break;
105 case "lt1":
106 colorScheme.Light1 = ParseColor(colorNode.ChildNodes);
107 break;
108 case "dk2":
109 colorScheme.Dark2 = ParseColor(colorNode.ChildNodes);
110 break;
111 case "lt2":
112 colorScheme.Light2 = ParseColor(colorNode.ChildNodes);
113 break;
114 case "accent1":
115 colorScheme.Accent1 = ParseColor(colorNode.ChildNodes);
116 break;
117 case "accent2":
118 colorScheme.Accent2 = ParseColor(colorNode.ChildNodes);
119 break;
120 case "accent3":
121 colorScheme.Accent3 = ParseColor(colorNode.ChildNodes);
122 break;
123 case "accent4":
124 colorScheme.Accent4 = ParseColor(colorNode.ChildNodes);
125 break;
126 case "accent5":
127 colorScheme.Accent5 = ParseColor(colorNode.ChildNodes);
128 break;
129 case "accent6":
130 colorScheme.Accent6 = ParseColor(colorNode.ChildNodes);
131 break;
132 case "hlink":
133 colorScheme.Hyperlink = ParseColor(colorNode.ChildNodes);
134 break;
135 case "folHlink":
136 colorScheme.FollowedHyperlink = ParseColor(colorNode.ChildNodes);
137 break;
138 }
139
140 }
141 }
142 InlinePluginHandler?.Invoke(stream, Workbook, PlugInUUID.ThemeInlineReader, Options, null);
143 }
144 }
145 }
146 catch (Exception ex)
147 {
148 throw new IOException("The XML entry could not be read from the input stream. Please see the inner exception:", ex);
149 }
150 }
151
157 private static IColor ParseColor(XmlNodeList childNodes)
158 {
159 foreach (XmlNode node in childNodes)
160 {
161 if (node.LocalName == "sysClr")
162 {
163 SystemColor.Value value = ParseSystemColor(node);
164 SystemColor systemColor = new SystemColor
165 {
166 ColorValue = value
167 };
168 string lastColor = ReaderUtils.GetAttribute(node, "lastClr");
169 if (lastColor != null)
170 {
171 systemColor.LastColor = lastColor;
172 }
173 return systemColor;
174 }
175 else if (node.LocalName == "srgbClr")
176 {
177 SrgbColor srgbColor = new SrgbColor
178 {
179 ColorValue = ReaderUtils.GetAttribute(node, "val")
180 };
181 return srgbColor;
182 }
183 }
184 return null;
185 }
186
193 private static SystemColor.Value ParseSystemColor(XmlNode innerNode)
194 {
195 string value = ReaderUtils.GetAttribute(innerNode, "val");
196 if (string.IsNullOrEmpty(value))
197 {
198 throw new IOException("The system color entry was null or empty");
199 }
200 try
201 {
202 return SystemColor.MapStringToValue(value);
203 }
204 catch (Exception ex)
205 {
206 throw new IOException("The system color entry '" + value + "' could not be parsed", ex);
207 }
208 }
209 #endregion
210 }
211}
Static class with common util methods, used during reading XLSX files.
static string GetAttribute(XmlNode node, string targetName, string fallbackValue=null)
Gets the XML attribute of the passed XML node by its name.
Class representing a reader for theme definitions of XLSX files.
Action< MemoryStream, Workbook, string, IOptions, int?> InlinePluginHandler
Reference to the ReaderPlugInHandler, to be used for post operations in the Execute method.
void Execute()
Method to execute the main logic of the plug-in (interface implementation).
Workbook Workbook
Workbook reference where read data is stored (should not be null).
IOptions Options
Reader options.
void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions, Action< MemoryStream, Workbook, string, IOptions, int?> inlinePluginHandler)
Initialization method (interface implementation).
Exceptions.IOException IOException