NanoXLSX.Reader 3.0.0-rc.2
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 © 2025
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.Plugin;
14using NanoXLSX.Registry;
15using NanoXLSX.Registry.Attributes;
16using NanoXLSX.Utils;
18using IOException = NanoXLSX.Exceptions.IOException;
19
21{
25 [NanoXlsxPlugIn(PlugInUUID = PlugInUUID.WorkbookReader)]
26 public partial class WorkbookReader : IPlugInReader
27 {
28 private MemoryStream stream;
29 private IPasswordReader passwordReader;
30 private ReaderOptions readerOptions;
31
32 #region properties
36 public Workbook Workbook { get; set; }
37 #endregion
38
39 #region constructors
43 internal WorkbookReader()
44 {
45 }
46 #endregion
47
48 #region methods
55 public void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions)
56 {
57 this.stream = stream;
58 this.Workbook = workbook;
59 this.readerOptions = (ReaderOptions)readerOptions;
60 this.passwordReader = PlugInLoader.GetPlugIn<IPasswordReader>(PlugInUUID.PasswordReader, new LegacyPasswordReader());
61 this.passwordReader.Init(PasswordType.WorkbookProtection, this.readerOptions);
62 }
63
68 public void Execute()
69 {
70 try
71 {
72 using (stream) // Close after processing
73 {
74 XmlDocument xr = new XmlDocument() { XmlResolver = null };
75 using (XmlReader reader = XmlReader.Create(stream, new XmlReaderSettings() { XmlResolver = null }))
76 {
77 xr.Load(reader);
78 foreach (XmlNode node in xr.DocumentElement.ChildNodes)
79 {
80 if (node.LocalName.Equals("sheets", StringComparison.OrdinalIgnoreCase) && node.HasChildNodes)
81 {
82 GetWorksheetInformation(node.ChildNodes);
83 }
84 else if (node.LocalName.Equals("bookViews", StringComparison.OrdinalIgnoreCase) && node.HasChildNodes)
85 {
86 GetViewInformation(node.ChildNodes);
87 }
88 else if (node.LocalName.Equals("workbookProtection", StringComparison.OrdinalIgnoreCase))
89 {
90 GetProtectionInformation(node);
91 }
92 }
93 RederPlugInHandler.HandleInlineQueuePlugins(ref stream, Workbook, PlugInUUID.WorkbookInlineReader);
94 }
95 }
96 }
97 catch (NotSupportedContentException)
98 {
99 throw; // rethrow
100 }
101 catch (Exception ex)
102 {
103 throw new IOException("The XML entry could not be read from the input stream. Please see the inner exception:", ex);
104 }
105 }
106
111 private void GetProtectionInformation(XmlNode node)
112 {
113 bool lockStructure = false;
114 bool lockWindows = false;
115 //this.Protected = true;
116 string attribute = ReaderUtils.GetAttribute(node, "lockWindows");
117 if (attribute != null)
118 {
119 int value = ParserUtils.ParseBinaryBool(attribute);
120 //this.LockWindows = value == 1;
121 lockWindows = value == 1;
122 }
123 attribute = ReaderUtils.GetAttribute(node, "lockStructure");
124 if (attribute != null)
125 {
126 int value = ParserUtils.ParseBinaryBool(attribute);
127 //this.LockStructure = value == 1;
128 lockStructure = value == 1;
129 }
130 Workbook.SetWorkbookProtection(true, lockWindows, lockStructure, null);
131 passwordReader.ReadXmlAttributes(node);
132 if (passwordReader.PasswordIsSet())
133 {
134 Workbook.WorkbookProtectionPassword.CopyFrom(passwordReader);
135 }
136 }
137
142 private void GetViewInformation(XmlNodeList nodes)
143 {
144 foreach (XmlNode node in nodes)
145 {
146 if (node.LocalName.Equals("workbookView", StringComparison.OrdinalIgnoreCase))
147 {
148 string attribute = ReaderUtils.GetAttribute(node, "visibility");
149 if (attribute != null && ParserUtils.ToLower(attribute) == "hidden")
150 {
151 this.Workbook.Hidden = true;
152 }
153 attribute = ReaderUtils.GetAttribute(node, "activeTab");
154 if (!string.IsNullOrEmpty(attribute))
155 {
156 Workbook.AuxiliaryData.SetData(PlugInUUID.WorkbookReader, PlugInUUID.SelectedWorksheetEntity, ParserUtils.ParseInt(attribute));
157 }
158 }
159 }
160 }
161
166 private void GetWorksheetInformation(XmlNodeList nodes)
167 {
168 foreach (XmlNode node in nodes)
169 {
170 if (node.LocalName.Equals("sheet", StringComparison.OrdinalIgnoreCase))
171 {
172 try
173 {
174 string sheetName = ReaderUtils.GetAttribute(node, "name", "worksheet1");
175 int id = ParserUtils.ParseInt(ReaderUtils.GetAttribute(node, "sheetId")); // Default will rightly throw an exception
176 string relId = ReaderUtils.GetAttribute(node, "r:id");
177 string state = ReaderUtils.GetAttribute(node, "state");
178 bool hidden = false;
179 if (state != null && ParserUtils.ToLower(state) == "hidden")
180 {
181 hidden = true;
182 }
183 WorksheetDefinition definition = new WorksheetDefinition(id, sheetName, relId)
184 {
185 Hidden = hidden
186 };
187 Workbook.AuxiliaryData.SetData(PlugInUUID.WorkbookReader, PlugInUUID.WorksheetDefinitionEntity, id, definition);
188 }
189 catch (Exception e)
190 {
191 throw new IOException("The workbook information could not be resolved. Please see the inner exception:", e);
192 }
193 }
194 }
195 }
196 #endregion
197 }
198}
Static class that contains enums for password handling.
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).
void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions)
Initialization method (interface implementation).
The reader options define global rules, applied when loading a worksheet. The options are mainly to o...
Interface, used by password readers.
void ReadXmlAttributes(XmlNode node)
Reads the attributes of the passed XML node that contains password information.
void Init(PasswordType type, ReaderOptions readerOptions)
Method to initialize the password reader.
Exceptions.IOException IOException