37 private Stream stream;
39 private ReaderOptions options;
45 public virtual string DocumentType {
get {
return @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; } }
79 public void Init(Stream stream,
Workbook workbook, IOptions readerOptions, Action<Stream, Workbook, string, IOptions, int?> inlinePluginHandler)
82 this.Workbook = workbook;
83 this.Options = readerOptions;
84 this.options = readerOptions as ReaderOptions;
85 this.InlinePluginHandler = inlinePluginHandler;
99 using (XmlReader reader = XmlReader.Create(stream, XmlStreamUtils.CreateSettings()))
101 while (reader.Read())
103 if (reader.NodeType != XmlNodeType.Element)
107 switch (reader.LocalName.ToLowerInvariant())
110 GetNumberFormats(reader);
133 Workbook.AuxiliaryData.SetData(PlugInUUID.StyleReader, PlugInUUID.StyleEntity, styleReaderContainer);
137 throw new IOException(
"The XML entry could not be read from the input stream. Please see the inner exception:", ex);
144 private void HandleMruColors()
146 List<string> mruColors = styleReaderContainer.GetMruColors();
147 foreach (
string color
in mruColors)
157 private void GetNumberFormats(XmlReader reader)
159 using (XmlReader subtree = reader.ReadSubtree())
162 while (subtree.Read())
164 if (!XmlStreamUtils.IsElement(subtree,
"numFmt"))
168 NumberFormat numberFormat =
new NumberFormat();
169 int id = ParserUtils.ParseInt(subtree.GetAttribute(
"numFmtId"));
170 string code = subtree.GetAttribute(
"formatCode");
171 if (
string.IsNullOrEmpty(code))
173 if (options.EnforceStrictValidation)
175 throw new Exceptions.FormatException(
"A format code cannot be null or empty, but was read so in the styles");
179 numberFormat.CustomFormatID = id;
180 numberFormat.Number = FormatNumber.Custom;
181 numberFormat.InternalID = id;
182 numberFormat.CustomFormatCode = code;
183 this.styleReaderContainer.AddStyleComponent(numberFormat);
192 private void GetBorders(XmlReader reader)
194 using (XmlReader subtree = reader.ReadSubtree())
197 while (subtree.Read())
199 if (!XmlStreamUtils.IsElement(subtree,
"border"))
203 Border borderStyle =
new Border();
204 string diagonalDown = subtree.GetAttribute(
"diagonalDown");
205 if (diagonalDown !=
null && ParserUtils.ParseBinaryBool(diagonalDown) == 1)
207 borderStyle.DiagonalDown =
true;
209 string diagonalUp = subtree.GetAttribute(
"diagonalUp");
210 if (diagonalUp !=
null && ParserUtils.ParseBinaryBool(diagonalUp) == 1)
212 borderStyle.DiagonalUp =
true;
214 StyleValue sideStyle;
216 using (XmlReader borderSubtree = subtree.ReadSubtree())
218 borderSubtree.Read();
219 while (borderSubtree.Read())
221 if (borderSubtree.NodeType != XmlNodeType.Element)
225 switch (borderSubtree.LocalName.ToLowerInvariant())
228 ReadBorderSide(borderSubtree, out sideStyle, out sideColor);
229 borderStyle.DiagonalStyle = sideStyle;
230 borderStyle.DiagonalColor = sideColor;
233 ReadBorderSide(borderSubtree, out sideStyle, out sideColor);
234 borderStyle.TopStyle = sideStyle;
235 borderStyle.TopColor = sideColor;
238 ReadBorderSide(borderSubtree, out sideStyle, out sideColor);
239 borderStyle.BottomStyle = sideStyle;
240 borderStyle.BottomColor = sideColor;
243 ReadBorderSide(borderSubtree, out sideStyle, out sideColor);
244 borderStyle.LeftStyle = sideStyle;
245 borderStyle.LeftColor = sideColor;
248 ReadBorderSide(borderSubtree, out sideStyle, out sideColor);
249 borderStyle.RightStyle = sideStyle;
250 borderStyle.RightColor = sideColor;
255 borderStyle.InternalID = this.styleReaderContainer.GetNextBorderId();
256 this.styleReaderContainer.AddStyleComponent(borderStyle);
265 private static void ReadBorderSide(XmlReader reader, out StyleValue style, out
string color)
267 style = StyleValue.None;
268 color = Border.DefaultBorderColor;
269 string styleAttr = reader.GetAttribute(
"style");
270 if (styleAttr !=
null)
272 style = Border.GetStyleEnum(styleAttr);
274 if (reader.IsEmptyElement)
278 using (XmlReader subtree = reader.ReadSubtree())
281 while (subtree.Read())
283 if (subtree.NodeType == XmlNodeType.Element
284 && subtree.LocalName.Equals(
"color", StringComparison.OrdinalIgnoreCase))
286 string rgb = subtree.GetAttribute(
"rgb");
301 private void GetFills(XmlReader reader)
303 using (XmlReader subtree = reader.ReadSubtree())
306 while (subtree.Read())
308 if (!XmlStreamUtils.IsElement(subtree,
"fill"))
312 Fill fillStyle =
new Fill();
313 using (XmlReader fillSubtree = subtree.ReadSubtree())
316 while (fillSubtree.Read())
318 if (!XmlStreamUtils.IsElement(fillSubtree,
"patternFill"))
322 fillStyle.PatternFill = Fill.GetPatternEnum(fillSubtree.GetAttribute(
"patternType") ??
string.Empty);
323 using (XmlReader patternSubtree = fillSubtree.ReadSubtree())
325 patternSubtree.Read();
326 while (patternSubtree.Read())
328 if (patternSubtree.NodeType != XmlNodeType.Element)
332 if (patternSubtree.LocalName.Equals(
"fgColor", StringComparison.OrdinalIgnoreCase))
334 fillStyle.ForegroundColor = ReadColorFromNode(patternSubtree);
336 else if (patternSubtree.LocalName.Equals(
"bgColor", StringComparison.OrdinalIgnoreCase))
338 fillStyle.BackgroundColor = ReadColorFromNode(patternSubtree);
344 fillStyle.InternalID = this.styleReaderContainer.GetNextFillId();
345 this.styleReaderContainer.AddStyleComponent(fillStyle);
353 private static Color ReadColorFromNode(XmlReader reader)
355 string autoAttr = reader.GetAttribute(
"auto");
356 if (!
string.IsNullOrEmpty(autoAttr) && ParserUtils.ParseBinaryBool(autoAttr) == 1)
358 return Color.CreateAuto();
360 string rgbAttr = reader.GetAttribute(
"rgb");
361 if (!
string.IsNullOrEmpty(rgbAttr))
363 return Color.CreateRgb(rgbAttr);
365 string indexedAttr = reader.GetAttribute(
"indexed");
366 if (!
string.IsNullOrEmpty(indexedAttr))
368 return Color.CreateIndexed(ParserUtils.ParseInt(indexedAttr));
370 string themeAttr = reader.GetAttribute(
"theme");
371 if (!
string.IsNullOrEmpty(themeAttr))
373 int themeIndex = ParserUtils.ParseInt(themeAttr);
374 string tintAttr = reader.GetAttribute(
"tint");
376 if (!
string.IsNullOrEmpty(tintAttr))
378 tint = ParserUtils.ParseDouble(tintAttr);
380 return Color.CreateTheme((Theme.ColorSchemeElement)themeIndex, tint);
382 string systemAttr = reader.GetAttribute(
"system");
383 if (!
string.IsNullOrEmpty(systemAttr))
385 return Color.CreateSystem(
new SystemColor(SystemColor.MapStringToValue(systemAttr)));
387 return Color.CreateNone();
394 private void GetFonts(XmlReader reader)
396 using (XmlReader subtree = reader.ReadSubtree())
399 while (subtree.Read())
401 if (!XmlStreamUtils.IsElement(subtree,
"font"))
405 Font fontStyle =
new Font();
406 ReadFontElement(subtree, fontStyle);
407 fontStyle.InternalID = this.styleReaderContainer.GetNextFontId();
408 this.styleReaderContainer.AddStyleComponent(fontStyle);
416 private static void ReadFontElement(XmlReader reader, Font fontStyle)
418 using (XmlReader fontSubtree = reader.ReadSubtree())
421 while (fontSubtree.Read())
423 if (fontSubtree.NodeType != XmlNodeType.Element)
428 switch (fontSubtree.LocalName.ToLowerInvariant())
431 fontStyle.Bold =
true;
434 fontStyle.Italic =
true;
437 fontStyle.Strike =
true;
440 fontStyle.Outline =
true;
443 fontStyle.Shadow =
true;
446 fontStyle.Condense =
true;
449 fontStyle.Extend =
true;
452 val = fontSubtree.GetAttribute(
"val");
453 fontStyle.Underline = val ==
null ? Font.UnderlineValue.Single : Font.GetUnderlineEnum(val);
456 fontStyle.VerticalAlign = Font.GetVerticalTextAlignEnum(fontSubtree.GetAttribute(
"val"));
459 fontStyle.Size = ParserUtils.ParseFloat(fontSubtree.GetAttribute(
"val"));
462 string themeVal = fontSubtree.GetAttribute(
"theme");
463 if (themeVal !=
null)
465 fontStyle.ColorValue = Color.CreateTheme(ParseFontColorSchemeElement(themeVal));
467 string rgbVal = fontSubtree.GetAttribute(
"rgb");
470 fontStyle.ColorValue = Color.CreateRgb(rgbVal);
474 fontStyle.Name = fontSubtree.GetAttribute(
"val");
477 val = fontSubtree.GetAttribute(
"val");
480 fontStyle.Family = ParseFontFamilyValue(val);
484 val = fontSubtree.GetAttribute(
"val");
490 fontStyle.Scheme = SchemeValue.Major;
493 fontStyle.Scheme = SchemeValue.Minor;
499 val = fontSubtree.GetAttribute(
"val");
502 fontStyle.Charset = ParseFontCharsetValue(val);
513 private static ColorSchemeElement ParseFontColorSchemeElement(
string value)
517 case "1":
return ColorSchemeElement.Light1;
518 case "2":
return ColorSchemeElement.Dark2;
519 case "3":
return ColorSchemeElement.Light2;
520 case "4":
return ColorSchemeElement.Accent1;
521 case "5":
return ColorSchemeElement.Accent2;
522 case "6":
return ColorSchemeElement.Accent3;
523 case "7":
return ColorSchemeElement.Accent4;
524 case "8":
return ColorSchemeElement.Accent5;
525 case "9":
return ColorSchemeElement.Accent6;
526 case "10":
return ColorSchemeElement.Hyperlink;
527 case "11":
return ColorSchemeElement.FollowedHyperlink;
528 default:
return ColorSchemeElement.Dark1;
535 private static FontFamilyValue ParseFontFamilyValue(
string value)
539 case "1":
return FontFamilyValue.Roman;
540 case "2":
return FontFamilyValue.Swiss;
541 case "3":
return FontFamilyValue.Modern;
542 case "4":
return FontFamilyValue.Script;
543 case "5":
return FontFamilyValue.Decorative;
544 case "6":
return FontFamilyValue.Reserved1;
545 case "7":
return FontFamilyValue.Reserved2;
546 case "8":
return FontFamilyValue.Reserved3;
547 case "9":
return FontFamilyValue.Reserved4;
548 case "10":
return FontFamilyValue.Reserved5;
549 case "11":
return FontFamilyValue.Reserved6;
550 case "12":
return FontFamilyValue.Reserved7;
551 case "13":
return FontFamilyValue.Reserved8;
552 case "14":
return FontFamilyValue.Reserved9;
553 default:
return FontFamilyValue.NotApplicable;
560 private static CharsetValue ParseFontCharsetValue(
string value)
564 case "0":
return CharsetValue.ANSI;
565 case "1":
return CharsetValue.Default;
566 case "2":
return CharsetValue.Symbols;
567 case "77":
return CharsetValue.Macintosh;
568 case "128":
return CharsetValue.JIS;
569 case "129":
return CharsetValue.Hangul;
570 case "130":
return CharsetValue.Johab;
571 case "134":
return CharsetValue.GBK;
572 case "136":
return CharsetValue.Big5;
573 case "161":
return CharsetValue.Greek;
574 case "162":
return CharsetValue.Turkish;
575 case "163":
return CharsetValue.Vietnamese;
576 case "177":
return CharsetValue.Hebrew;
577 case "178":
return CharsetValue.Arabic;
578 case "186":
return CharsetValue.Baltic;
579 case "204":
return CharsetValue.Russian;
580 case "222":
return CharsetValue.Thai;
581 case "238":
return CharsetValue.EasternEuropean;
582 case "255":
return CharsetValue.OEM;
583 default:
return CharsetValue.ApplicationDefined;
592 private void GetCellXfs(XmlReader reader)
594 using (XmlReader subtree = reader.ReadSubtree())
597 while (subtree.Read())
599 if (!XmlStreamUtils.IsElement(subtree,
"xf"))
603 CellXf cellXfStyle =
new CellXf();
604 string applyAlignment = subtree.GetAttribute(
"applyAlignment");
605 if (applyAlignment !=
null)
607 cellXfStyle.ForceApplyAlignment = ParserUtils.ParseBinaryBool(applyAlignment) == 1;
609 string numFmtIdStr = subtree.GetAttribute(
"numFmtId");
610 string borderIdStr = subtree.GetAttribute(
"borderId");
611 string fillIdStr = subtree.GetAttribute(
"fillId");
612 string fontIdStr = subtree.GetAttribute(
"fontId");
613 if (!subtree.IsEmptyElement)
615 using (XmlReader xfSubtree = subtree.ReadSubtree())
618 while (xfSubtree.Read())
620 if (xfSubtree.NodeType != XmlNodeType.Element)
624 if (xfSubtree.LocalName.Equals(
"alignment", StringComparison.OrdinalIgnoreCase))
626 ReadXfAlignment(xfSubtree, cellXfStyle);
628 else if (xfSubtree.LocalName.Equals(
"protection", StringComparison.OrdinalIgnoreCase))
630 ReadXfProtection(xfSubtree, cellXfStyle);
635 cellXfStyle.InternalID = this.styleReaderContainer.GetNextCellXFId();
636 this.styleReaderContainer.AddStyleComponent(cellXfStyle);
638 Style style =
new Style();
642 hasId = ParserUtils.TryParseInt(numFmtIdStr, out
id);
643 NumberFormat format = this.styleReaderContainer.GetNumberFormat(
id);
644 if (!hasId || format ==
null)
646 FormatNumber formatNumber;
647 NumberFormat.TryParseFormatNumber(
id, out formatNumber);
648 format =
new NumberFormat
650 Number = formatNumber,
653 this.styleReaderContainer.AddStyleComponent(format);
655 hasId = ParserUtils.TryParseInt(borderIdStr, out
id);
656 Border border = this.styleReaderContainer.GetBorder(
id);
657 if (!hasId || border ==
null)
661 InternalID = this.styleReaderContainer.GetNextBorderId()
664 hasId = ParserUtils.TryParseInt(fillIdStr, out
id);
665 Fill fill = this.styleReaderContainer.GetFill(
id);
666 if (!hasId || fill ==
null)
670 InternalID = this.styleReaderContainer.GetNextFillId()
673 hasId = ParserUtils.TryParseInt(fontIdStr, out
id);
674 Font font = this.styleReaderContainer.GetFont(
id);
675 if (!hasId || font ==
null)
679 InternalID = this.styleReaderContainer.GetNextFontId()
682 style.CurrentNumberFormat = format;
683 style.CurrentBorder = border;
684 style.CurrentFill = fill;
685 style.CurrentFont = font;
686 style.CurrentCellXf = cellXfStyle;
687 style.InternalID = this.styleReaderContainer.GetNextStyleId();
688 this.styleReaderContainer.AddStyleComponent(style);
696 private static void ReadXfAlignment(XmlReader reader, CellXf cellXfStyle)
698 string shrinkToFit = reader.GetAttribute(
"shrinkToFit");
699 if (shrinkToFit !=
null && ParserUtils.ParseBinaryBool(shrinkToFit) == 1)
701 cellXfStyle.Alignment = TextBreakValue.ShrinkToFit;
703 string wrapText = reader.GetAttribute(
"wrapText");
704 if (wrapText !=
null && wrapText ==
"1")
706 cellXfStyle.Alignment = TextBreakValue.WrapText;
708 cellXfStyle.HorizontalAlign = CellXf.GetHorizontalAlignEnum(reader.GetAttribute(
"horizontal") ??
string.Empty);
709 cellXfStyle.VerticalAlign = CellXf.GetVerticalAlignEnum(reader.GetAttribute(
"vertical") ??
string.Empty);
710 string indent = reader.GetAttribute(
"indent");
713 cellXfStyle.Indent = ParserUtils.ParseInt(indent);
715 string textRotation = reader.GetAttribute(
"textRotation");
716 if (textRotation !=
null)
718 int rotation = ParserUtils.ParseInt(textRotation);
719 cellXfStyle.TextRotation = rotation > 90 ? 90 - rotation : rotation;
726 private static void ReadXfProtection(XmlReader reader, CellXf cellXfStyle)
728 string hidden = reader.GetAttribute(
"hidden");
729 if (hidden !=
null && hidden ==
"1")
731 cellXfStyle.Hidden =
true;
733 string locked = reader.GetAttribute(
"locked");
734 if (locked !=
null && locked ==
"0")
736 cellXfStyle.Locked =
false;
744 private void GetColors(XmlReader reader)
746 using (XmlReader subtree = reader.ReadSubtree())
749 while (subtree.Read())
751 if (subtree.NodeType == XmlNodeType.Element
752 && subtree.LocalName.Equals(
"mruColors", StringComparison.OrdinalIgnoreCase))
754 ReadMruColors(subtree);
763 private void ReadMruColors(XmlReader reader)
765 using (XmlReader subtree = reader.ReadSubtree())
768 while (subtree.Read())
770 if (subtree.NodeType == XmlNodeType.Element
771 && subtree.LocalName.Equals(
"color", StringComparison.OrdinalIgnoreCase))
773 string rgb = subtree.GetAttribute(
"rgb");
776 this.styleReaderContainer.AddMruColor(rgb);