NanoXLSX.Reader 3.0.0-rc.5
Loading...
Searching...
No Matches
StyleReader.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
9{
10 using System;
11 using System.IO;
12 using System.Xml;
13 using NanoXLSX.Colors;
14 using NanoXLSX.Interfaces;
15 using NanoXLSX.Interfaces.Reader;
16 using NanoXLSX.Registry;
17 using NanoXLSX.Registry.Attributes;
18 using NanoXLSX.Styles;
19 using NanoXLSX.Themes;
20 using NanoXLSX.Utils;
21 using static NanoXLSX.Styles.Border;
22 using static NanoXLSX.Styles.CellXf;
23 using static NanoXLSX.Styles.Font;
24 using static NanoXLSX.Styles.NumberFormat;
25 using static NanoXLSX.Themes.Theme;
26 using IOException = Exceptions.IOException;
27
31 [NanoXlsxPlugIn(PlugInUUID = PlugInUUID.StyleReader)]
32 public class StyleReader : IPluginBaseReader
33 {
34
35 private MemoryStream stream;
36 private StyleReaderContainer styleReaderContainer;
37
38 #region properties
42 public Workbook Workbook { get; set; }
46 public IOptions Options { get; set; }
50 public Action<MemoryStream, Workbook, string, IOptions, int?> InlinePluginHandler { get; set; }
51 #endregion
52
53 #region constructors
57 public StyleReader()
58 {
59 }
60 #endregion
61
62 #region methods
63
71 public void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions, Action<MemoryStream, Workbook, string, IOptions, int?> inlinePluginHandler)
72 {
73 this.stream = stream;
74 this.Workbook = workbook;
75 this.Options = readerOptions;
76 this.InlinePluginHandler = inlinePluginHandler;
77 }
78
83 public void Execute()
84 {
85 this.styleReaderContainer = new StyleReaderContainer();
86 try
87 {
88 using (stream) // Close after processing
89 {
90 XmlDocument xr = new XmlDocument() { XmlResolver = null };
91 using (XmlReader reader = XmlReader.Create(stream, new XmlReaderSettings() { XmlResolver = null }))
92 {
93 xr.Load(reader);
94 foreach (XmlNode node in xr.DocumentElement.ChildNodes)
95 {
96 if (node.LocalName.Equals("numfmts", StringComparison.OrdinalIgnoreCase)) // Handles custom number formats
97 {
98 GetNumberFormats(node);
99 }
100 else if (node.LocalName.Equals("borders", StringComparison.OrdinalIgnoreCase)) // Handles borders
101 {
102 GetBorders(node);
103 }
104 else if (node.LocalName.Equals("fills", StringComparison.OrdinalIgnoreCase)) // Handles fills
105 {
106 GetFills(node);
107 }
108 else if (node.LocalName.Equals("fonts", StringComparison.OrdinalIgnoreCase)) // Handles fonts
109 {
110 GetFonts(node);
111 }
112 else if (node.LocalName.Equals("colors", StringComparison.OrdinalIgnoreCase)) // Handles MRU colors
113 {
114 GetColors(node);
115 }
116 // TODO: Implement other style components
117 }
118 foreach (XmlNode node in xr.DocumentElement.ChildNodes) // Redo for composition after all style parts are gathered; standard number formats
119 {
120 if (node.LocalName.Equals("cellxfs", StringComparison.OrdinalIgnoreCase))
121 {
122 GetCellXfs(node);
123 }
124 }
125 HandleMruColors();
126 InlinePluginHandler?.Invoke(stream, Workbook, PlugInUUID.StyleInlineReader, Options, null);
127 }
128 }
129 Workbook.AuxiliaryData.SetData(PlugInUUID.StyleReader, PlugInUUID.StyleEntity, styleReaderContainer);
130 }
131 catch (Exception ex)
132 {
133 throw new IOException("The XML entry could not be read from the input stream. Please see the inner exception:", ex);
134 }
135 }
136
140 private void HandleMruColors()
141 {
142 if (styleReaderContainer.GetMruColors().Count > 0)
143 {
144 foreach (string color in styleReaderContainer.GetMruColors())
145 {
146 Workbook.AddMruColor(color);
147 }
148 }
149 }
150
155 private void GetNumberFormats(XmlNode node)
156 {
157 foreach (XmlNode childNode in node.ChildNodes)
158 {
159 if (childNode.LocalName.Equals("numfmt", StringComparison.OrdinalIgnoreCase))
160 {
161 NumberFormat numberFormat = new NumberFormat();
162 int id = ParserUtils.ParseInt(ReaderUtils.GetAttribute(childNode, "numFmtId")); // Default will (justified) throw an exception
163 string code = ReaderUtils.GetAttribute(childNode, "formatCode", string.Empty);
164 numberFormat.CustomFormatID = id;
165 numberFormat.Number = FormatNumber.Custom;
166 numberFormat.InternalID = id;
167 numberFormat.CustomFormatCode = code;
168 this.styleReaderContainer.AddStyleComponent(numberFormat);
169 }
170 }
171 }
172
177 private void GetBorders(XmlNode node)
178 {
179 foreach (XmlNode border in node.ChildNodes)
180 {
181 Border borderStyle = new Border();
182 string diagonalDown = ReaderUtils.GetAttribute(border, "diagonalDown");
183 string diagonalUp = ReaderUtils.GetAttribute(border, "diagonalUp");
184 if (diagonalDown != null)
185 {
186 int value = ParserUtils.ParseBinaryBool(diagonalDown);
187 if (value == 1)
188 {
189 borderStyle.DiagonalDown = true;
190 }
191 }
192 if (diagonalUp != null)
193 {
194 int value = ParserUtils.ParseBinaryBool(diagonalUp);
195 if (value == 1)
196 {
197 borderStyle.DiagonalUp = true;
198 }
199 }
200 XmlNode innerNode = ReaderUtils.GetChildNode(border, "diagonal");
201 if (innerNode != null)
202 {
203 borderStyle.DiagonalStyle = ParseBorderStyle(innerNode);
204 borderStyle.DiagonalColor = GetColor(innerNode, Border.DefaultBorderColor);
205 }
206 innerNode = ReaderUtils.GetChildNode(border, "top");
207 if (innerNode != null)
208 {
209 borderStyle.TopStyle = ParseBorderStyle(innerNode);
210 borderStyle.TopColor = GetColor(innerNode, Border.DefaultBorderColor);
211 }
212 innerNode = ReaderUtils.GetChildNode(border, "bottom");
213 if (innerNode != null)
214 {
215 borderStyle.BottomStyle = ParseBorderStyle(innerNode);
216 borderStyle.BottomColor = GetColor(innerNode, Border.DefaultBorderColor);
217 }
218 innerNode = ReaderUtils.GetChildNode(border, "left");
219 if (innerNode != null)
220 {
221 borderStyle.LeftStyle = ParseBorderStyle(innerNode);
222 borderStyle.LeftColor = GetColor(innerNode, Border.DefaultBorderColor);
223 }
224 innerNode = ReaderUtils.GetChildNode(border, "right");
225 if (innerNode != null)
226 {
227 borderStyle.RightStyle = ParseBorderStyle(innerNode);
228 borderStyle.RightColor = GetColor(innerNode, Border.DefaultBorderColor);
229 }
230 borderStyle.InternalID = this.styleReaderContainer.GetNextBorderId();
231 this.styleReaderContainer.AddStyleComponent(borderStyle);
232 }
233 }
234
240 private static StyleValue ParseBorderStyle(XmlNode innerNode)
241 {
242 string value = ReaderUtils.GetAttribute(innerNode, "style");
243 if (value != null)
244 {
245 return Border.GetStyleEnum(value);
246 }
247 return StyleValue.None;
248 }
249
254 private void GetFills(XmlNode node)
255 {
256 foreach (XmlNode fill in node.ChildNodes)
257 {
258 Fill fillStyle = new Fill();
259 XmlNode innerNode = ReaderUtils.GetChildNode(fill, "patternFill");
260 if (innerNode != null)
261 {
262 string pattern = ReaderUtils.GetAttribute(innerNode, "patternType", string.Empty);
263 fillStyle.PatternFill = Fill.GetPatternEnum(pattern);
264
265 // Read fgColor
266 XmlNode fgColorNode = ReaderUtils.GetChildNode(innerNode, "fgColor");
267 if (fgColorNode != null)
268 {
269 fillStyle.ForegroundColor = ReadColorFromNode(fgColorNode);
270 }
271
272 // Read bgColor
273 XmlNode bgColorNode = ReaderUtils.GetChildNode(innerNode, "bgColor");
274 if (bgColorNode != null)
275 {
276 fillStyle.BackgroundColor = ReadColorFromNode(bgColorNode);
277 }
278 }
279 fillStyle.InternalID = this.styleReaderContainer.GetNextFillId();
280 this.styleReaderContainer.AddStyleComponent(fillStyle);
281 }
282 }
283
289 private static Color ReadColorFromNode(XmlNode colorNode)
290 {
291 // Check for auto attribute
292 string autoAttr = ReaderUtils.GetAttribute(colorNode, "auto");
293 if (!string.IsNullOrEmpty(autoAttr) && ParserUtils.ParseBinaryBool(autoAttr) == 1)
294 {
295 return Color.CreateAuto();
296 }
297
298 // Check for rgb attribute
299 string rgbAttr = ReaderUtils.GetAttribute(colorNode, "rgb");
300 if (!string.IsNullOrEmpty(rgbAttr))
301 {
302 return Color.CreateRgb(rgbAttr);
303 }
304
305 // Check for indexed attribute
306 string indexedAttr = ReaderUtils.GetAttribute(colorNode, "indexed");
307 if (!string.IsNullOrEmpty(indexedAttr))
308 {
309 return Color.CreateIndexed(ParserUtils.ParseInt(indexedAttr));
310 }
311
312 // Check for theme attribute
313 string themeAttr = ReaderUtils.GetAttribute(colorNode, "theme");
314 if (!string.IsNullOrEmpty(themeAttr))
315 {
316 int themeIndex = ParserUtils.ParseInt(themeAttr);
317 // Check for optional tint attribute
318 string tintAttr = ReaderUtils.GetAttribute(colorNode, "tint");
319 double? tint = null;
320 if (!string.IsNullOrEmpty(tintAttr))
321 {
322 tint = ParserUtils.ParseDouble(tintAttr); // Or Convert.ToDouble with InvariantCulture
323 }
324 return Color.CreateTheme((Theme.ColorSchemeElement)themeIndex, tint);
325 }
326
327 // Check for system attribute (if supported)
328 string systemAttr = ReaderUtils.GetAttribute(colorNode, "system");
329 if (!string.IsNullOrEmpty(systemAttr))
330 {
331 SystemColor sysColor = new SystemColor(SystemColor.MapStringToValue(systemAttr));
332 return Color.CreateSystem(sysColor);
333 }
334
335 // No color defined
336 return Color.CreateNone();
337 }
338
343 private void GetFonts(XmlNode node)
344 {
345 string attribute;
346 foreach (XmlNode font in node.ChildNodes)
347 {
348 Font fontStyle = new Font();
349 XmlNode boldNode = ReaderUtils.GetChildNode(font, "b");
350 if (boldNode != null)
351 {
352 fontStyle.Bold = true;
353 }
354 XmlNode italicdNode = ReaderUtils.GetChildNode(font, "i");
355 if (italicdNode != null)
356 {
357 fontStyle.Italic = true;
358 }
359 XmlNode strikeNode = ReaderUtils.GetChildNode(font, "strike");
360 if (strikeNode != null)
361 {
362 fontStyle.Strike = true;
363 }
364 XmlNode outlineNode = ReaderUtils.GetChildNode(font, "outline");
365 if (outlineNode != null)
366 {
367 fontStyle.Outline = true;
368 }
369 XmlNode shadowNode = ReaderUtils.GetChildNode(font, "shadow");
370 if (shadowNode != null)
371 {
372 fontStyle.Shadow = true;
373 }
374 XmlNode condenseNode = ReaderUtils.GetChildNode(font, "condense");
375 if (condenseNode != null)
376 {
377 fontStyle.Condense = true;
378 }
379 XmlNode extendNode = ReaderUtils.GetChildNode(font, "extend");
380 if (extendNode != null)
381 {
382 fontStyle.Extend = true;
383 }
384 if (ReaderUtils.GetAttributeOfChild(font, "u", "val", out attribute))
385 {
386 if (attribute == null)
387 {
388 fontStyle.Underline = Font.UnderlineValue.Single; // Default value
389 }
390 else
391 {
392 fontStyle.Underline = Font.GetUnderlineEnum(attribute);
393 }
394 }
395 if (ReaderUtils.GetAttributeOfChild(font, "vertAlign", "val", out attribute))
396 {
397 fontStyle.VerticalAlign = Font.GetVerticalTextAlignEnum(attribute);
398 }
399 if (ReaderUtils.GetAttributeOfChild(font, "sz", "val", out attribute))
400 {
401 fontStyle.Size = ParserUtils.ParseFloat(attribute);
402 }
403 XmlNode colorNode = ReaderUtils.GetChildNode(font, "color");
404 if (colorNode != null)
405 {
406
407 attribute = ReaderUtils.GetAttribute(colorNode, "theme");
408 if (attribute != null)
409 {
410 ColorSchemeElement element = ColorSchemeElement.Dark1;
411 switch (attribute)
412 {
413 case "0":
414 element = ColorSchemeElement.Dark1;
415 break;
416 case "1":
417 element = ColorSchemeElement.Light1;
418 break;
419 case "2":
420 element = ColorSchemeElement.Dark2;
421 break;
422 case "3":
423 element = ColorSchemeElement.Light2;
424 break;
425 case "4":
426 element = ColorSchemeElement.Accent1;
427 break;
428 case "5":
429 element = ColorSchemeElement.Accent2;
430 break;
431 case "6":
432 element = ColorSchemeElement.Accent3;
433 break;
434 case "7":
435 element = ColorSchemeElement.Accent4;
436 break;
437 case "8":
438 element = ColorSchemeElement.Accent5;
439 break;
440 case "9":
441 element = ColorSchemeElement.Accent6;
442 break;
443 case "10":
444 element = ColorSchemeElement.Hyperlink;
445 break;
446 case "11":
447 element = ColorSchemeElement.FollowedHyperlink;
448 break;
449 }
450 fontStyle.ColorValue = Color.CreateTheme(element);
451
452 }
453 attribute = ReaderUtils.GetAttribute(colorNode, "rgb");
454 if (attribute != null)
455 {
456 fontStyle.ColorValue = Color.CreateRgb(attribute);
457 }
458 }
459 if (ReaderUtils.GetAttributeOfChild(font, "name", "val", out attribute))
460 {
461 fontStyle.Name = attribute;
462 }
463 if (ReaderUtils.GetAttributeOfChild(font, "family", "val", out attribute))
464 {
465 switch (attribute)
466 {
467
468 case "0":
469 fontStyle.Family = FontFamilyValue.NotApplicable;
470 break;
471 case "1":
472 fontStyle.Family = FontFamilyValue.Roman;
473 break;
474 case "2":
475 fontStyle.Family = FontFamilyValue.Swiss;
476 break;
477 case "3":
478 fontStyle.Family = FontFamilyValue.Modern;
479 break;
480 case "4":
481 fontStyle.Family = FontFamilyValue.Script;
482 break;
483 case "5":
484 fontStyle.Family = FontFamilyValue.Decorative;
485 break;
486 case "6":
487 fontStyle.Family = FontFamilyValue.Reserved1;
488 break;
489 case "7":
490 fontStyle.Family = FontFamilyValue.Reserved2;
491 break;
492 case "8":
493 fontStyle.Family = FontFamilyValue.Reserved3;
494 break;
495 case "9":
496 fontStyle.Family = FontFamilyValue.Reserved4;
497 break;
498 case "10":
499 fontStyle.Family = FontFamilyValue.Reserved5;
500 break;
501 case "11":
502 fontStyle.Family = FontFamilyValue.Reserved6;
503 break;
504 case "12":
505 fontStyle.Family = FontFamilyValue.Reserved7;
506 break;
507 case "13":
508 fontStyle.Family = FontFamilyValue.Reserved8;
509 break;
510 case "14":
511 fontStyle.Family = FontFamilyValue.Reserved9;
512 break;
513 }
514 }
515 if (ReaderUtils.GetAttributeOfChild(font, "scheme", "val", out attribute))
516 {
517 switch (attribute)
518 {
519 case "major":
520 fontStyle.Scheme = SchemeValue.Major;
521 break;
522 case "minor":
523 fontStyle.Scheme = SchemeValue.Minor;
524 break;
525 }
526 }
527 if (ReaderUtils.GetAttributeOfChild(font, "charset", "val", out attribute))
528 {
529 switch (attribute)
530 {
531 case "0":
532 fontStyle.Charset = CharsetValue.ANSI;
533 break;
534 case "1":
535 fontStyle.Charset = CharsetValue.Default;
536 break;
537 case "2":
538 fontStyle.Charset = CharsetValue.Symbols;
539 break;
540 case "77":
541 fontStyle.Charset = CharsetValue.Macintosh;
542 break;
543 case "128":
544 fontStyle.Charset = CharsetValue.JIS;
545 break;
546 case "129":
547 fontStyle.Charset = CharsetValue.Hangul;
548 break;
549 case "130":
550 fontStyle.Charset = CharsetValue.Johab;
551 break;
552 case "134":
553 fontStyle.Charset = CharsetValue.GBK;
554 break;
555 case "136":
556 fontStyle.Charset = CharsetValue.Big5;
557 break;
558 case "161":
559 fontStyle.Charset = CharsetValue.Greek;
560 break;
561 case "162":
562 fontStyle.Charset = CharsetValue.Turkish;
563 break;
564 case "163":
565 fontStyle.Charset = CharsetValue.Vietnamese;
566 break;
567 case "177":
568 fontStyle.Charset = CharsetValue.Hebrew;
569 break;
570 case "178":
571 fontStyle.Charset = CharsetValue.Arabic;
572 break;
573 case "186":
574 fontStyle.Charset = CharsetValue.Baltic;
575 break;
576 case "204":
577 fontStyle.Charset = CharsetValue.Russian;
578 break;
579 case "222":
580 fontStyle.Charset = CharsetValue.Thai;
581 break;
582 case "238":
583 fontStyle.Charset = CharsetValue.EasternEuropean;
584 break;
585 case "255":
586 fontStyle.Charset = CharsetValue.OEM;
587 break;
588 default:
589 fontStyle.Charset = CharsetValue.ApplicationDefined;
590 break;
591 }
592 }
593
594 fontStyle.InternalID = this.styleReaderContainer.GetNextFontId();
595 this.styleReaderContainer.AddStyleComponent(fontStyle);
596 }
597 }
598
603 private void GetCellXfs(XmlNode node)
604 {
605 foreach (XmlNode childNode in node.ChildNodes)
606 {
607 if (ReaderUtils.IsNode(childNode, "xf"))
608 {
609 CellXf cellXfStyle = new CellXf();
610 string attribute = ReaderUtils.GetAttribute(childNode, "applyAlignment");
611 if (attribute != null)
612 {
613 int value = ParserUtils.ParseBinaryBool(attribute);
614 cellXfStyle.ForceApplyAlignment = value == 1;
615 }
616 XmlNode alignmentNode = ReaderUtils.GetChildNode(childNode, "alignment");
617 if (alignmentNode != null)
618 {
619 attribute = ReaderUtils.GetAttribute(alignmentNode, "shrinkToFit");
620 if (attribute != null)
621 {
622 int value = ParserUtils.ParseBinaryBool(attribute);
623 if (value == 1)
624 {
625 cellXfStyle.Alignment = TextBreakValue.ShrinkToFit;
626 }
627 }
628 attribute = ReaderUtils.GetAttribute(alignmentNode, "wrapText");
629 if (attribute != null && attribute == "1")
630 {
631 cellXfStyle.Alignment = TextBreakValue.WrapText;
632 }
633 attribute = ReaderUtils.GetAttribute(alignmentNode, "horizontal", string.Empty);
634 cellXfStyle.HorizontalAlign = CellXf.GetHorizontalAlignEnum(attribute);
635 attribute = ReaderUtils.GetAttribute(alignmentNode, "vertical", string.Empty);
636 cellXfStyle.VerticalAlign = CellXf.GetVerticalAlignEnum(attribute);
637 attribute = ReaderUtils.GetAttribute(alignmentNode, "indent");
638 if (attribute != null)
639 {
640 cellXfStyle.Indent = ParserUtils.ParseInt(attribute);
641 }
642 attribute = ReaderUtils.GetAttribute(alignmentNode, "textRotation");
643 if (attribute != null)
644 {
645 int rotation = ParserUtils.ParseInt(attribute);
646 cellXfStyle.TextRotation = rotation > 90 ? 90 - rotation : rotation;
647 }
648 }
649 XmlNode protectionNode = ReaderUtils.GetChildNode(childNode, "protection");
650 if (protectionNode != null)
651 {
652 attribute = ReaderUtils.GetAttribute(protectionNode, "hidden");
653 if (attribute != null && attribute == "1")
654 {
655 cellXfStyle.Hidden = true;
656 }
657 attribute = ReaderUtils.GetAttribute(protectionNode, "locked");
658 if (attribute != null && attribute == "0")
659 {
660 cellXfStyle.Locked = false;
661 }
662 // else - NoOp - No need to set locked value, since true by default
663 }
664
665 cellXfStyle.InternalID = this.styleReaderContainer.GetNextCellXFId();
666 this.styleReaderContainer.AddStyleComponent(cellXfStyle);
667
668 Style style = new Style();
669 int id;
670 bool hasId;
671
672 hasId = ParserUtils.TryParseInt(ReaderUtils.GetAttribute(childNode, "numFmtId"), out id);
673 NumberFormat format = this.styleReaderContainer.GetNumberFormat(id);
674 if (!hasId || format == null)
675 {
676 FormatNumber formatNumber;
677 NumberFormat.TryParseFormatNumber(id, out formatNumber); // Validity is neglected here to prevent unhandled crashes. If invalid, the format will be declared as 'none'.
678 // Invalid values should not occur at all (malformed Excel files).
679 // Undefined values may occur if the file was saved by an Excel version that has implemented yet unknown format numbers (undefined in NanoXLSX)
680 format = new NumberFormat
681 {
682 Number = formatNumber,
683 InternalID = id
684 };
685 this.styleReaderContainer.AddStyleComponent(format);
686 }
687 hasId = ParserUtils.TryParseInt(ReaderUtils.GetAttribute(childNode, "borderId"), out id);
688 Border border = this.styleReaderContainer.GetBorder(id);
689 if (!hasId || border == null)
690 {
691 border = new Border
692 {
693 InternalID = this.styleReaderContainer.GetNextBorderId()
694 };
695 }
696 hasId = ParserUtils.TryParseInt(ReaderUtils.GetAttribute(childNode, "fillId"), out id);
697 Fill fill = this.styleReaderContainer.GetFill(id);
698 if (!hasId || fill == null)
699 {
700 fill = new Fill
701 {
702 InternalID = this.styleReaderContainer.GetNextFillId()
703 };
704 }
705 hasId = ParserUtils.TryParseInt(ReaderUtils.GetAttribute(childNode, "fontId"), out id);
706 Font font = this.styleReaderContainer.GetFont(id);
707 if (!hasId || font == null)
708 {
709 font = new Font
710 {
711 InternalID = this.styleReaderContainer.GetNextFontId()
712 };
713 }
714
715 // TODO: Implement other style information
716 style.CurrentNumberFormat = format;
717 style.CurrentBorder = border;
718 style.CurrentFill = fill;
719 style.CurrentFont = font;
720 style.CurrentCellXf = cellXfStyle;
721 style.InternalID = this.styleReaderContainer.GetNextStyleId();
722
723 this.styleReaderContainer.AddStyleComponent(style);
724 }
725 }
726 }
727
732 private void GetColors(XmlNode node)
733 {
734 foreach (XmlNode color in node.ChildNodes)
735 {
736 XmlNode mruColor = ReaderUtils.GetChildNode(color, "color");
737 if (color.Name.Equals("mruColors", StringComparison.Ordinal) && mruColor != null)
738 {
739 foreach (XmlNode value in color.ChildNodes)
740 {
741 string attribute = ReaderUtils.GetAttribute(value, "rgb");
742 if (attribute != null)
743 {
744 this.styleReaderContainer.AddMruColor(attribute);
745 }
746 }
747 }
748 }
749 }
750
757 private static string GetColor(XmlNode node, string fallback)
758 {
759 XmlNode childNode = ReaderUtils.GetChildNode(node, "color");
760 if (childNode != null)
761 {
762 string color = ReaderUtils.GetAttribute(childNode, "rgb");
763 if (color != null)
764 {
765 return color;
766 }
767 }
768 return fallback;
769 }
770 #endregion
771 }
772}
StyleReader()
Default constructor - Must be defined for instantiation of the plug-ins.
Action< MemoryStream, Workbook, string, IOptions, int?> InlinePluginHandler
Reference to the ReaderPlugInHandler, to be used for post operations in the Execute method.
Workbook Workbook
Workbook reference where read data is stored (should not be null).
void Init(MemoryStream stream, Workbook workbook, IOptions readerOptions, Action< MemoryStream, Workbook, string, IOptions, int?> inlinePluginHandler)
Initialization method (interface implementation).
void Execute()
Method to execute the main logic of the plug-in (interface implementation).
IOptions Options
Reader options.
Class representing a collection of pre-processed styles and their components. This class is internall...
void AddStyleComponent(AbstractStyle component)
Adds a style component and determines the appropriate type of it automatically.
Exceptions.IOException IOException