NanoXLSX.Reader 3.0.0-rc.5
Loading...
Searching...
No Matches
Internal/Readers/WorkbookReader.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.Exceptions;
12using NanoXLSX.Interfaces;
13using NanoXLSX.Interfaces.Reader;
14using NanoXLSX.Registry;
15using NanoXLSX.Registry.Attributes;
16using NanoXLSX.Utils;
17using static NanoXLSX.Enums.Password;
18using IOException = NanoXLSX.Exceptions.IOException;
19
21{
25 [NanoXlsxPlugIn(PlugInUUID = PlugInUUID.WorkbookReader)]
26 public partial class WorkbookReader : IPluginBaseReader
27 {
28 private MemoryStream stream;
29 private IPasswordReader passwordReader;
30 // private ReaderOptions readerOptions;
31
32 #region properties
36 public Workbook Workbook { get; set; }
40 public IOptions Options { get; set; }
44 public Action<MemoryStream, Workbook, string, IOptions, int?> InlinePluginHandler { get; set; }
45 #endregion
46
47 #region constructors
51 internal WorkbookReader()
52 {
53 }
54 #endregion
55
56 #region methods
64 public void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions, Action<MemoryStream, Workbook, string, IOptions, int?> inlinePluginHandler)
65 {
66 this.stream = stream;
67 this.Workbook = workbook;
68 this.Options = readerOptions;
69 this.InlinePluginHandler = inlinePluginHandler;
70 this.passwordReader = PlugInLoader.GetPlugIn<IPasswordReader>(PlugInUUID.PasswordReader, new LegacyPasswordReader());
71 this.passwordReader.Init(PasswordType.WorkbookProtection, (ReaderOptions)readerOptions);
72 }
73
78 public void Execute()
79 {
80 try
81 {
82 using (stream) // Close after processing
83 {
84 XmlDocument xr = new XmlDocument() { XmlResolver = null };
85 using (XmlReader reader = XmlReader.Create(stream, new XmlReaderSettings() { XmlResolver = null }))
86 {
87 xr.Load(reader);
88 foreach (XmlNode node in xr.DocumentElement.ChildNodes)
89 {
90 if (node.LocalName.Equals("sheets", StringComparison.OrdinalIgnoreCase) && node.HasChildNodes)
91 {
92 GetWorksheetInformation(node.ChildNodes);
93 }
94 else if (node.LocalName.Equals("bookViews", StringComparison.OrdinalIgnoreCase) && node.HasChildNodes)
95 {
96 GetViewInformation(node.ChildNodes);
97 }
98 else if (node.LocalName.Equals("workbookProtection", StringComparison.OrdinalIgnoreCase))
99 {
100 GetProtectionInformation(node);
101 }
102 }
103 InlinePluginHandler?.Invoke(stream, Workbook, PlugInUUID.WorkbookInlineReader, Options, null);
104 }
105 }
106 }
107 catch (NotSupportedContentException)
108 {
109 throw; // rethrow
110 }
111 catch (Exception ex)
112 {
113 throw new IOException("The XML entry could not be read from the input stream. Please see the inner exception:", ex);
114 }
115 }
116
121 private void GetProtectionInformation(XmlNode node)
122 {
123 bool lockStructure = false;
124 bool lockWindows = false;
125 //this.Protected = true;
126 string attribute = ReaderUtils.GetAttribute(node, "lockWindows");
127 if (attribute != null)
128 {
129 int value = ParserUtils.ParseBinaryBool(attribute);
130 //this.LockWindows = value == 1;
131 lockWindows = value == 1;
132 }
133 attribute = ReaderUtils.GetAttribute(node, "lockStructure");
134 if (attribute != null)
135 {
136 int value = ParserUtils.ParseBinaryBool(attribute);
137 //this.LockStructure = value == 1;
138 lockStructure = value == 1;
139 }
140 Workbook.SetWorkbookProtection(true, lockWindows, lockStructure, null);
141 passwordReader.ReadXmlAttributes(node);
142 if (passwordReader.PasswordIsSet())
143 {
144 Workbook.WorkbookProtectionPassword.CopyFrom(passwordReader);
145 }
146 }
147
152 private void GetViewInformation(XmlNodeList nodes)
153 {
154 foreach (XmlNode node in nodes)
155 {
156 if (node.LocalName.Equals("workbookView", StringComparison.OrdinalIgnoreCase))
157 {
158 string attribute = ReaderUtils.GetAttribute(node, "visibility");
159 if (attribute != null && ParserUtils.ToLower(attribute) == "hidden")
160 {
161 this.Workbook.Hidden = true;
162 }
163 attribute = ReaderUtils.GetAttribute(node, "activeTab");
164 if (!string.IsNullOrEmpty(attribute))
165 {
166 Workbook.AuxiliaryData.SetData(PlugInUUID.WorkbookReader, PlugInUUID.SelectedWorksheetEntity, ParserUtils.ParseInt(attribute));
167 }
168 }
169 }
170 }
171
176 private void GetWorksheetInformation(XmlNodeList nodes)
177 {
178 foreach (XmlNode node in nodes)
179 {
180 if (node.LocalName.Equals("sheet", StringComparison.OrdinalIgnoreCase))
181 {
182 try
183 {
184 string sheetName = ReaderUtils.GetAttribute(node, "name", "worksheet1");
185 int id = ParserUtils.ParseInt(ReaderUtils.GetAttribute(node, "sheetId")); // Default will rightly throw an exception
186 string relId = ReaderUtils.GetAttribute(node, "r:id");
187 string state = ReaderUtils.GetAttribute(node, "state");
188 bool hidden = false;
189 if (state != null && ParserUtils.ToLower(state) == "hidden")
190 {
191 hidden = true;
192 }
193 WorksheetDefinition definition = new WorksheetDefinition(id, sheetName, relId)
194 {
195 Hidden = hidden
196 };
197 Workbook.AuxiliaryData.SetData(PlugInUUID.WorkbookReader, PlugInUUID.WorksheetDefinitionEntity, id, definition);
198 }
199 catch (Exception e)
200 {
201 throw new IOException("The workbook information could not be resolved. Please see the inner exception:", e);
202 }
203 }
204 }
205 }
206 #endregion
207 }
208}
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 legacy passwords.
Class representing a reader to decompile a workbook in an XLSX files.
Workbook Workbook
Workbook reference where read data is stored (should not be null).
void Execute()
Method to execute the main logic of the plug-in (interface implementation).
Action< MemoryStream, Workbook, string, IOptions, int?> InlinePluginHandler
Reference to the ReaderPlugInHandler, to be used for post operations in the Execute method.
void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions, Action< MemoryStream, Workbook, string, IOptions, int?> inlinePluginHandler)
Initialization method (interface implementation).
Exceptions.IOException IOException