diff --git a/ClosedXML/Excel/XLWorkbook_Load.cs b/ClosedXML/Excel/XLWorkbook_Load.cs index 1ea2246..7aa016e 100644 --- a/ClosedXML/Excel/XLWorkbook_Load.cs +++ b/ClosedXML/Excel/XLWorkbook_Load.cs @@ -1706,7 +1706,7 @@ if (source.Style != null) setBorder(source.Style.Value.ToClosedXml()); if (source.Color != null) - setColor(GetColor(source.Color)); + setColor(source.Color.ToClosedXMLColor(_colorList)); } } @@ -1731,22 +1731,22 @@ if (differentialFillFormat) { if (openXMLFill.PatternFill.BackgroundColor != null) - closedXMLFill.BackgroundColor = GetColor(openXMLFill.PatternFill.BackgroundColor); + closedXMLFill.BackgroundColor = openXMLFill.PatternFill.BackgroundColor.ToClosedXMLColor(_colorList); } else { // yes, source is foreground! if (openXMLFill.PatternFill.ForegroundColor != null) - closedXMLFill.BackgroundColor = GetColor(openXMLFill.PatternFill.ForegroundColor); + closedXMLFill.BackgroundColor = openXMLFill.PatternFill.ForegroundColor.ToClosedXMLColor(_colorList); } break; default: if (openXMLFill.PatternFill.ForegroundColor != null) - closedXMLFill.PatternColor = GetColor(openXMLFill.PatternFill.ForegroundColor); + closedXMLFill.PatternColor = openXMLFill.PatternFill.ForegroundColor.ToClosedXMLColor(_colorList); if (openXMLFill.PatternFill.BackgroundColor != null) - closedXMLFill.BackgroundColor = GetColor(openXMLFill.PatternFill.BackgroundColor); + closedXMLFill.BackgroundColor = openXMLFill.PatternFill.BackgroundColor.ToClosedXMLColor(_colorList); break; } } @@ -1756,9 +1756,9 @@ if (fontSource == null) return; fontBase.Bold = GetBoolean(fontSource.Elements().FirstOrDefault()); - var fontColor = GetColor(fontSource.Elements().FirstOrDefault()); - if (fontColor.HasValue) - fontBase.FontColor = fontColor; + var fontColor = fontSource.Elements().FirstOrDefault(); + if (fontColor != null) + fontBase.FontColor = fontColor.ToClosedXMLColor(_colorList); var fontFamilyNumbering = fontSource.Elements().FirstOrDefault(); @@ -2365,8 +2365,7 @@ if (xlConditionalFormat != null) { var negativeFillColor = conditionalFormattingRule.Descendants().SingleOrDefault(); - var color = new DocumentFormat.OpenXml.Spreadsheet.Color { Rgb = negativeFillColor.Rgb }; - xlConditionalFormat.Colors.Add(this.GetColor(color)); + xlConditionalFormat.Colors.Add(negativeFillColor.ToClosedXMLColor(_colorList)); } } } @@ -2397,7 +2396,7 @@ } foreach (var c in element.Elements()) { - conditionalFormat.Colors.Add(GetColor(c)); + conditionalFormat.Colors.Add(c.ToClosedXMLColor(_colorList)); } } @@ -2454,7 +2453,7 @@ if (sheetProperty == null) return; if (sheetProperty.TabColor != null) - ws.TabColor = GetColor(sheetProperty.TabColor); + ws.TabColor = sheetProperty.TabColor.ToClosedXMLColor(_colorList); if (sheetProperty.OutlineProperties != null) { @@ -2653,34 +2652,6 @@ Properties.Title = p.Title; } - private XLColor GetColor(ColorType color) - { - XLColor retVal = null; - if (color != null) - { - if (color.Rgb != null) - { - String htmlColor = "#" + color.Rgb.Value; - Color thisColor; - if (!_colorList.ContainsKey(htmlColor)) - { - thisColor = ColorStringParser.ParseFromHtml(htmlColor); - _colorList.Add(htmlColor, thisColor); - } - else - thisColor = _colorList[htmlColor]; - retVal = XLColor.FromColor(thisColor); - } - else if (color.Indexed != null && color.Indexed <= 64) - retVal = XLColor.FromIndex((Int32)color.Indexed.Value); - else if (color.Theme != null) - { - retVal = color.Tint != null ? XLColor.FromTheme((XLThemeColor)color.Theme.Value, color.Tint.Value) : XLColor.FromTheme((XLThemeColor)color.Theme.Value); - } - } - return retVal ?? XLColor.NoColor; - } - private void ApplyStyle(IXLStylized xlStylized, Int32 styleIndex, Stylesheet s, Fills fills, Borders borders, Fonts fonts, NumberingFormats numberingFormats) { @@ -2762,45 +2733,40 @@ if (bottomBorder.Style != null) xlBorder.BottomBorder = bottomBorder.Style.Value.ToClosedXml(); - var bottomBorderColor = GetColor(bottomBorder.Color); - if (bottomBorderColor.HasValue) - xlBorder.BottomBorderColor = bottomBorderColor.Key; + if (bottomBorder.Color != null) + xlBorder.BottomBorderColor = bottomBorder.Color.ToClosedXMLColor(_colorList).Key; } var topBorder = border.TopBorder; if (topBorder != null) { if (topBorder.Style != null) xlBorder.TopBorder = topBorder.Style.Value.ToClosedXml(); - var topBorderColor = GetColor(topBorder.Color); - if (topBorderColor.HasValue) - xlBorder.TopBorderColor = topBorderColor.Key; + if (topBorder.Color != null) + xlBorder.TopBorderColor = topBorder.Color.ToClosedXMLColor(_colorList).Key; } var leftBorder = border.LeftBorder; if (leftBorder != null) { if (leftBorder.Style != null) xlBorder.LeftBorder = leftBorder.Style.Value.ToClosedXml(); - var leftBorderColor = GetColor(leftBorder.Color); - if (leftBorderColor.HasValue) - xlBorder.LeftBorderColor = leftBorderColor.Key; + if (leftBorder.Color != null) + xlBorder.LeftBorderColor = leftBorder.Color.ToClosedXMLColor(_colorList).Key; } var rightBorder = border.RightBorder; if (rightBorder != null) { if (rightBorder.Style != null) xlBorder.RightBorder = rightBorder.Style.Value.ToClosedXml(); - var rightBorderColor = GetColor(rightBorder.Color); - if (rightBorderColor.HasValue) - xlBorder.RightBorderColor = rightBorderColor.Key; + if (rightBorder.Color != null) + xlBorder.RightBorderColor = rightBorder.Color.ToClosedXMLColor(_colorList).Key; } var diagonalBorder = border.DiagonalBorder; if (diagonalBorder != null) { if (diagonalBorder.Style != null) xlBorder.DiagonalBorder = diagonalBorder.Style.Value.ToClosedXml(); - var diagonalBorderColor = GetColor(diagonalBorder.Color); - if (diagonalBorderColor.HasValue) - xlBorder.DiagonalBorderColor = diagonalBorderColor.Key; + if (diagonalBorder.Color != null) + xlBorder.DiagonalBorderColor = diagonalBorder.Color.ToClosedXMLColor(_colorList).Key; if (border.DiagonalDown != null) xlBorder.DiagonalDown = border.DiagonalDown; if (border.DiagonalUp != null) @@ -2821,9 +2787,8 @@ { xlFont.Bold = GetBoolean(font.Bold); - var fontColor = GetColor(font.Color); - if (fontColor.HasValue) - xlFont.FontColor = fontColor.Key; + if (font.Color != null) + xlFont.FontColor = font.Color.ToClosedXMLColor(_colorList).Key; if (font.FontFamilyNumbering != null && (font.FontFamilyNumbering).Val != null) { diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs index c92a39d..a00168b 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -1024,7 +1024,7 @@ { Val = rt.VerticalAlignment.ToOpenXml() }; var shadow = rt.Shadow ? new Shadow() : null; var fontSize = new FontSize { Val = rt.FontSize }; - var color = GetNewColor(rt.FontColor); + var color = new Color().FromClosedXMLColor(rt.FontColor); var fontName = new RunFont { Val = rt.FontName }; var fontFamilyNumbering = new FontFamily { Val = (Int32)rt.FontFamilyNumbering }; @@ -3837,7 +3837,7 @@ var leftBorder = new LeftBorder { Style = borderInfo.Border.LeftBorder.ToOpenXml() }; if (borderInfo.Border.LeftBorderColor != XLBorderValue.Default.LeftBorderColor || ignoreMod) { - var leftBorderColor = GetNewColor(borderInfo.Border.LeftBorderColor); + var leftBorderColor = new Color().FromClosedXMLColor(borderInfo.Border.LeftBorderColor); leftBorder.AppendChild(leftBorderColor); } border.AppendChild(leftBorder); @@ -3848,7 +3848,7 @@ var rightBorder = new RightBorder { Style = borderInfo.Border.RightBorder.ToOpenXml() }; if (borderInfo.Border.RightBorderColor != XLBorderValue.Default.RightBorderColor || ignoreMod) { - var rightBorderColor = GetNewColor(borderInfo.Border.RightBorderColor); + var rightBorderColor = new Color().FromClosedXMLColor(borderInfo.Border.RightBorderColor); rightBorder.AppendChild(rightBorderColor); } border.AppendChild(rightBorder); @@ -3859,7 +3859,7 @@ var topBorder = new TopBorder { Style = borderInfo.Border.TopBorder.ToOpenXml() }; if (borderInfo.Border.TopBorderColor != XLBorderValue.Default.TopBorderColor || ignoreMod) { - var topBorderColor = GetNewColor(borderInfo.Border.TopBorderColor); + var topBorderColor = new Color().FromClosedXMLColor(borderInfo.Border.TopBorderColor); topBorder.AppendChild(topBorderColor); } border.AppendChild(topBorder); @@ -3870,7 +3870,7 @@ var bottomBorder = new BottomBorder { Style = borderInfo.Border.BottomBorder.ToOpenXml() }; if (borderInfo.Border.BottomBorderColor != XLBorderValue.Default.BottomBorderColor || ignoreMod) { - var bottomBorderColor = GetNewColor(borderInfo.Border.BottomBorderColor); + var bottomBorderColor = new Color().FromClosedXMLColor(borderInfo.Border.BottomBorderColor); bottomBorder.AppendChild(bottomBorderColor); } border.AppendChild(bottomBorder); @@ -3882,7 +3882,7 @@ if (borderInfo.Border.DiagonalBorderColor != XLBorderValue.Default.DiagonalBorderColor || ignoreMod) if (borderInfo.Border.DiagonalBorderColor != null) { - var DiagonalBorderColor = GetNewColor(borderInfo.Border.DiagonalBorderColor); + var DiagonalBorderColor = new Color().FromClosedXMLColor(borderInfo.Border.DiagonalBorderColor); DiagonalBorder.AppendChild(DiagonalBorderColor); } border.AppendChild(DiagonalBorder); @@ -3904,45 +3904,40 @@ { if (b.DiagonalBorder.Style != null) nb.DiagonalBorder = b.DiagonalBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.DiagonalBorder.Color); - if (bColor.HasValue) - nb.DiagonalBorderColor = bColor.Key; + if (b.DiagonalBorder.Color != null) + nb.DiagonalBorderColor = b.DiagonalBorder.Color.ToClosedXMLColor(_colorList).Key; } if (b.LeftBorder != null) { if (b.LeftBorder.Style != null) nb.LeftBorder = b.LeftBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.LeftBorder.Color); - if (bColor.HasValue) - nb.LeftBorderColor = bColor.Key; + if (b.LeftBorder.Color != null) + nb.LeftBorderColor = b.LeftBorder.Color.ToClosedXMLColor(_colorList).Key; } if (b.RightBorder != null) { if (b.RightBorder.Style != null) nb.RightBorder = b.RightBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.RightBorder.Color); - if (bColor.HasValue) - nb.RightBorderColor = bColor.Key; + if (b.RightBorder.Color != null) + nb.RightBorderColor = b.RightBorder.Color.ToClosedXMLColor(_colorList).Key; } if (b.TopBorder != null) { if (b.TopBorder.Style != null) nb.TopBorder = b.TopBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.TopBorder.Color); - if (bColor.HasValue) - nb.TopBorderColor = bColor.Key; + if (b.TopBorder.Color != null) + nb.TopBorderColor = b.TopBorder.Color.ToClosedXMLColor(_colorList).Key; } if (b.BottomBorder != null) { if (b.BottomBorder.Style != null) nb.BottomBorder = b.BottomBorder.Style.Value.ToClosedXml(); - var bColor = GetColor(b.BottomBorder.Color); - if (bColor.HasValue) - nb.BottomBorderColor = bColor.Key; + if (b.BottomBorder.Color != null) + nb.BottomBorderColor = b.BottomBorder.Color.ToClosedXMLColor(_colorList).Key; } return nb.Equals(xlBorder.Key); @@ -4014,61 +4009,18 @@ break; case XLFillPatternValues.Solid: + if (differentialFillFormat) { patternFill.AppendChild(new ForegroundColor { Auto = true }); - backgroundColor = new BackgroundColor(); - switch (fillInfo.Fill.BackgroundColor.ColorType) - { - case XLColorType.Color: - backgroundColor.Rgb = fillInfo.Fill.BackgroundColor.Color.ToHex(); - break; - - case XLColorType.Indexed: - // 64 is 'transparent' and should be ignored for differential formats - if (fillInfo.Fill.BackgroundColor.Indexed != 64) - backgroundColor.Indexed = (UInt32)fillInfo.Fill.BackgroundColor.Indexed; - break; - - case XLColorType.Theme: - backgroundColor.Theme = (UInt32)fillInfo.Fill.BackgroundColor.ThemeColor; - - if (fillInfo.Fill.BackgroundColor.ThemeTint != 0) - backgroundColor.Tint = fillInfo.Fill.BackgroundColor.ThemeTint; - - break; - } - + backgroundColor = new BackgroundColor().FromClosedXMLColor(fillInfo.Fill.BackgroundColor, true); if (backgroundColor.HasAttributes) patternFill.AppendChild(backgroundColor); } else { // ClosedXML Background color to be populated into OpenXML fgColor - foregroundColor = new ForegroundColor(); - switch (fillInfo.Fill.BackgroundColor.ColorType) - { - case XLColorType.Color: - foregroundColor.Rgb = fillInfo.Fill.BackgroundColor.Color.ToHex(); - break; - - case XLColorType.Indexed: - // 64 is 'transparent' and should be ignored for differential formats - if (fillInfo.Fill.BackgroundColor.Indexed != 64) - foregroundColor.Indexed = (UInt32)fillInfo.Fill.BackgroundColor.Indexed; - - //foregroundColor.Indexed = (UInt32)fillInfo.Fill.BackgroundColor.Indexed; - break; - - case XLColorType.Theme: - foregroundColor.Theme = (UInt32)fillInfo.Fill.BackgroundColor.ThemeColor; - - if (fillInfo.Fill.BackgroundColor.ThemeTint != 0) - foregroundColor.Tint = fillInfo.Fill.BackgroundColor.ThemeTint; - - break; - } - + foregroundColor = new ForegroundColor().FromClosedXMLColor(fillInfo.Fill.BackgroundColor); if (foregroundColor.HasAttributes) patternFill.AppendChild(foregroundColor); } @@ -4076,49 +4028,11 @@ default: - foregroundColor = new ForegroundColor(); - switch (fillInfo.Fill.PatternColor.ColorType) - { - case XLColorType.Color: - foregroundColor.Rgb = fillInfo.Fill.PatternColor.Color.ToHex(); - break; - - case XLColorType.Indexed: - foregroundColor.Indexed = (UInt32)fillInfo.Fill.PatternColor.Indexed; - break; - - case XLColorType.Theme: - foregroundColor.Theme = (UInt32)fillInfo.Fill.PatternColor.ThemeColor; - - if (fillInfo.Fill.PatternColor.ThemeTint != 0) - foregroundColor.Tint = fillInfo.Fill.PatternColor.ThemeTint; - - break; - } - + foregroundColor = new ForegroundColor().FromClosedXMLColor(fillInfo.Fill.PatternColor); if (foregroundColor.HasAttributes) patternFill.AppendChild(foregroundColor); - backgroundColor = new BackgroundColor(); - switch (fillInfo.Fill.BackgroundColor.ColorType) - { - case XLColorType.Color: - backgroundColor.Rgb = fillInfo.Fill.BackgroundColor.Color.ToHex(); - break; - - case XLColorType.Indexed: - backgroundColor.Indexed = (UInt32)fillInfo.Fill.BackgroundColor.Indexed; - break; - - case XLColorType.Theme: - backgroundColor.Theme = (UInt32)fillInfo.Fill.BackgroundColor.ThemeColor; - - if (fillInfo.Fill.BackgroundColor.ThemeTint != 0) - backgroundColor.Tint = fillInfo.Fill.BackgroundColor.ThemeTint; - - break; - } - + backgroundColor = new BackgroundColor().FromClosedXMLColor(fillInfo.Fill.BackgroundColor); if (backgroundColor.HasAttributes) patternFill.AppendChild(backgroundColor); @@ -4193,7 +4107,7 @@ var fontSize = fontInfo.Font.FontSize != XLFontValue.Default.FontSize || ignoreMod ? new FontSize { Val = fontInfo.Font.FontSize } : null; - var color = fontInfo.Font.FontColor != XLFontValue.Default.FontColor || ignoreMod ? GetNewColor(fontInfo.Font.FontColor) : null; + var color = fontInfo.Font.FontColor != XLFontValue.Default.FontColor || ignoreMod ? new Color().FromClosedXMLColor(fontInfo.Font.FontColor) : null; var fontName = fontInfo.Font.FontName != XLFontValue.Default.FontName || ignoreMod ? new FontName { Val = fontInfo.Font.FontName } @@ -4232,38 +4146,6 @@ return font; } - private static Color GetNewColor(XLColor xlColor) - { - var color = new Color(); - if (xlColor.ColorType == XLColorType.Color) - color.Rgb = xlColor.Color.ToHex(); - else if (xlColor.ColorType == XLColorType.Indexed) - color.Indexed = (UInt32)xlColor.Indexed; - else - { - color.Theme = (UInt32)xlColor.ThemeColor; - if (xlColor.ThemeTint != 0) - color.Tint = xlColor.ThemeTint; - } - return color; - } - - private static TabColor GetTabColor(XLColor xlColor) - { - var color = new TabColor(); - if (xlColor.ColorType == XLColorType.Color) - color.Rgb = xlColor.Color.ToHex(); - else if (xlColor.ColorType == XLColorType.Indexed) - color.Indexed = (UInt32)xlColor.Indexed; - else - { - color.Theme = (UInt32)xlColor.ThemeColor; - if (xlColor.ThemeTint != 0) - color.Tint = xlColor.ThemeTint; - } - return color; - } - private bool FontsAreEqual(Font f, XLFontValue xlFont) { var nf = XLFontValue.Default.Key; @@ -4286,9 +4168,8 @@ nf.Shadow = f.Shadow != null; if (f.FontSize != null) nf.FontSize = f.FontSize.Val; - var fColor = GetColor(f.Color); - if (fColor.HasValue) - nf.FontColor = fColor.Key; + if (f.Color != null) + nf.FontColor = f.Color.ToClosedXMLColor(_colorList).Key; if (f.FontName != null) nf.FontName = f.FontName.Val; if (f.FontFamilyNumbering != null) @@ -4389,7 +4270,7 @@ worksheetPart.Worksheet.SheetProperties = new SheetProperties(); worksheetPart.Worksheet.SheetProperties.TabColor = xlWorksheet.TabColor.HasValue - ? GetTabColor(xlWorksheet.TabColor) + ? new TabColor().FromClosedXMLColor(xlWorksheet.TabColor) : null; cm.SetElement(XLWorksheetContents.SheetProperties, worksheetPart.Worksheet.SheetProperties); diff --git a/ClosedXML/Utils/OpenXmlHelper.cs b/ClosedXML/Utils/OpenXmlHelper.cs index 3e1af4a..d908976 100644 --- a/ClosedXML/Utils/OpenXmlHelper.cs +++ b/ClosedXML/Utils/OpenXmlHelper.cs @@ -1,9 +1,50 @@ -using DocumentFormat.OpenXml; +// Keep this file CodeMaid organised and cleaned +using ClosedXML.Excel; +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Spreadsheet; +using System; +using System.Collections.Generic; +using Drawing = System.Drawing; +using X14 = DocumentFormat.OpenXml.Office2010.Excel; namespace ClosedXML.Utils { internal static class OpenXmlHelper { + #region Public Methods + + /// + /// Convert color in ClosedXML representation to specified OpenXML type. + /// + /// The descendant of . + /// The existing instance of ColorType. + /// Color in ClosedXML format. + /// Flag specifiying that the color should be saved in + /// differential format (affects the transparent color processing). + /// The original color in OpenXML format. + public static T FromClosedXMLColor(this ColorType openXMLColor, XLColor xlColor, bool isDifferential = false) + where T : ColorType + { + FillFromClosedXMLColor(openXMLColor, xlColor, isDifferential); + return (T)openXMLColor; + } + + /// + /// Convert color in ClosedXML representation to specified OpenXML type. + /// + /// The descendant of . + /// The existing instance of ColorType. + /// Color in ClosedXML format. + /// Flag specifiying that the color should be saved in + /// differential format (affects the transparent color processing). + /// The original color in OpenXML format. + public static T FromClosedXMLColor(this X14.ColorType openXMLColor, XLColor xlColor, bool isDifferential = false) + where T : X14.ColorType + { + FillFromClosedXMLColor(openXMLColor, xlColor, isDifferential); + return (T)openXMLColor; + } + public static BooleanValue GetBooleanValue(bool value, bool defaultValue) { return value == defaultValue ? null : new BooleanValue(value); @@ -13,5 +54,111 @@ { return (value?.HasValue ?? false) ? value.Value : defaultValue; } + + /// + /// Convert color in OpenXML representation to ClosedXML type. + /// + /// Color in OpenXML format. + /// The dictionary containing parsed colors to optimize performance. + /// The color in ClosedXML format. + public static XLColor ToClosedXMLColor(this ColorType openXMLColor, IDictionary colorCache = null) + { + return ConvertToClosedXMLColor(openXMLColor, colorCache); + } + + /// + /// Convert color in OpenXML representation to ClosedXML type. + /// + /// Color in OpenXML format. + /// The dictionary containing parsed colors to optimize performance. + /// The color in ClosedXML format. + public static XLColor ToClosedXMLColor(this X14.ColorType openXMLColor, IDictionary colorCache = null) + { + return ConvertToClosedXMLColor(openXMLColor, colorCache); + } + + #endregion Public Methods + + #region Private Methods + + /// + /// Here we perform the actual convertion from OpenXML color to ClosedXML color. + /// + /// OpenXML color. Must be either or . + /// Since these types do not implement a common interface we use dynamic. + /// The dictionary containing parsed colors to optimize performance. + /// The color in ClosedXML format. + private static XLColor ConvertToClosedXMLColor(dynamic openXMLColor, IDictionary colorCache ) + { + XLColor retVal = null; + if (openXMLColor != null) + { + if (openXMLColor.Rgb != null) + { + String htmlColor = "#" + openXMLColor.Rgb.Value; + Drawing.Color thisColor; + if (colorCache?.ContainsKey(htmlColor) ?? false) + { + thisColor = colorCache[htmlColor]; + } + else + { + thisColor = ColorStringParser.ParseFromHtml(htmlColor); + colorCache?.Add(htmlColor, thisColor); + } + + retVal = XLColor.FromColor(thisColor); + } + else if (openXMLColor.Indexed != null && openXMLColor.Indexed <= 64) + retVal = XLColor.FromIndex((Int32)openXMLColor.Indexed.Value); + else if (openXMLColor.Theme != null) + { + retVal = openXMLColor.Tint != null + ? XLColor.FromTheme((XLThemeColor)openXMLColor.Theme.Value, openXMLColor.Tint.Value) + : XLColor.FromTheme((XLThemeColor)openXMLColor.Theme.Value); + } + } + return retVal ?? XLColor.NoColor; + } + + /// + /// Initialize properties of the existing instance of the color in OpenXML format basing on properties of the color + /// in ClosedXML format. + /// + /// OpenXML color. Must be either or . + /// Since these types do not implement a common interface we use dynamic. + /// Color in ClosedXML format. + /// Flag specifiying that the color should be saved in + /// differential format (affects the transparent color processing). + private static void FillFromClosedXMLColor(dynamic openXMLColor, XLColor xlColor, bool isDifferential) + { + if (openXMLColor == null) + throw new ArgumentNullException(nameof(openXMLColor)); + + if (xlColor == null) + throw new ArgumentNullException(nameof(xlColor)); + + switch (xlColor.ColorType) + { + case XLColorType.Color: + openXMLColor.Rgb = xlColor.Color.ToHex(); + break; + + case XLColorType.Indexed: + // 64 is 'transparent' and should be ignored for differential formats + if (!isDifferential || xlColor.Indexed != 64) + openXMLColor.Indexed = (UInt32)xlColor.Indexed; + break; + + case XLColorType.Theme: + openXMLColor.Theme = (UInt32)xlColor.ThemeColor; + + if (xlColor.ThemeTint != 0) + openXMLColor.Tint = xlColor.ThemeTint; + break; + } + } + + #endregion Private Methods } } diff --git a/ClosedXML_Tests/Excel/Styles/ColorTests.cs b/ClosedXML_Tests/Excel/Styles/ColorTests.cs index 72cbb27..d631194 100644 --- a/ClosedXML_Tests/Excel/Styles/ColorTests.cs +++ b/ClosedXML_Tests/Excel/Styles/ColorTests.cs @@ -1,6 +1,9 @@ -using System.Drawing; using ClosedXML.Excel; +using ClosedXML.Utils; +using DocumentFormat.OpenXml.Spreadsheet; using NUnit.Framework; +using Color = System.Drawing.Color; +using X14 = DocumentFormat.OpenXml.Office2010.Excel; namespace ClosedXML_Tests.Excel { @@ -38,5 +41,137 @@ Assert.AreEqual(64, color.Indexed); Assert.AreEqual(Color.Transparent, color.Color); } + + [Test] + public void CanConvertXLColorToColorType() + { + var xlColor1 = XLColor.Red; + var xlColor2 = XLColor.FromIndex(20); + var xlColor3 = XLColor.FromTheme(XLThemeColor.Accent1); + var xlColor4 = XLColor.FromTheme(XLThemeColor.Accent2, 0.4); + + var color1 = new ForegroundColor().FromClosedXMLColor(xlColor1); + var color2 = new ForegroundColor().FromClosedXMLColor(xlColor2); + var color3 = new BackgroundColor().FromClosedXMLColor(xlColor3); + var color4 = new BackgroundColor().FromClosedXMLColor(xlColor4); + + Assert.AreEqual("FFFF0000", color1.Rgb.Value); + Assert.IsNull(color1.Indexed); + Assert.IsNull(color1.Theme); + Assert.IsNull(color1.Tint); + + Assert.IsNull(color2.Rgb); + Assert.AreEqual(20, color2.Indexed.Value); + Assert.IsNull(color2.Theme); + Assert.IsNull(color2.Tint); + + Assert.IsNull(color3.Rgb); + Assert.IsNull(color3.Indexed); + Assert.AreEqual(4, color3.Theme.Value); + Assert.IsNull(color3.Tint); + + Assert.IsNull(color4.Rgb); + Assert.IsNull(color4.Indexed); + Assert.AreEqual(5, color4.Theme.Value); + Assert.AreEqual(0.4, color4.Tint.Value); + } + + [Test] + public void CanConvertXlColorToX14ColorType() + { + var xlColor1 = XLColor.Red; + var xlColor2 = XLColor.FromIndex(20); + var xlColor3 = XLColor.FromTheme(XLThemeColor.Accent1); + var xlColor4 = XLColor.FromTheme(XLThemeColor.Accent2, 0.4); + + var color1 = new X14.AxisColor().FromClosedXMLColor(xlColor1); + var color2 = new X14.BorderColor().FromClosedXMLColor(xlColor2); + var color3 = new X14.FillColor().FromClosedXMLColor(xlColor3); + var color4 = new X14.HighMarkerColor().FromClosedXMLColor(xlColor4); + + Assert.AreEqual("FFFF0000", color1.Rgb.Value); + Assert.IsNull(color1.Indexed); + Assert.IsNull(color1.Theme); + Assert.IsNull(color1.Tint); + + Assert.IsNull(color2.Rgb); + Assert.AreEqual(20, color2.Indexed.Value); + Assert.IsNull(color2.Theme); + Assert.IsNull(color2.Tint); + + Assert.IsNull(color3.Rgb); + Assert.IsNull(color3.Indexed); + Assert.AreEqual(4, color3.Theme.Value); + Assert.IsNull(color3.Tint); + + Assert.IsNull(color4.Rgb); + Assert.IsNull(color4.Indexed); + Assert.AreEqual(5, color4.Theme.Value); + Assert.AreEqual(0.4, color4.Tint.Value); + } + + [Test] + public void CanConvertColorTypeToXlColor() + { + var color1 = new ForegroundColor { Rgb = new DocumentFormat.OpenXml.HexBinaryValue("FFFF0000") }; + var color2 = new ForegroundColor { Indexed = new DocumentFormat.OpenXml.UInt32Value((uint)20) }; + var color3 = new BackgroundColor { Theme = new DocumentFormat.OpenXml.UInt32Value((uint)4) }; + var color4 = new BackgroundColor + { + Theme = new DocumentFormat.OpenXml.UInt32Value((uint)4), + Tint = new DocumentFormat.OpenXml.DoubleValue(0.4) + }; + + var xlColor1 = color1.ToClosedXMLColor(); + var xlColor2 = color2.ToClosedXMLColor(); + var xlColor3 = color3.ToClosedXMLColor(); + var xlColor4 = color4.ToClosedXMLColor(); + + Assert.AreEqual(XLColorType.Color, xlColor1.ColorType); + Assert.AreEqual(XLColor.Red.Color, xlColor1.Color); + + Assert.AreEqual(XLColorType.Indexed, xlColor2.ColorType); + Assert.AreEqual(20, xlColor2.Indexed); + + Assert.AreEqual(XLColorType.Theme, xlColor3.ColorType); + Assert.AreEqual(XLThemeColor.Accent1, xlColor3.ThemeColor); + Assert.AreEqual(0, xlColor3.ThemeTint, XLHelper.Epsilon); + + Assert.AreEqual(XLColorType.Theme, xlColor4.ColorType); + Assert.AreEqual(XLThemeColor.Accent1, xlColor4.ThemeColor); + Assert.AreEqual(0.4, xlColor4.ThemeTint, XLHelper.Epsilon); + } + + [Test] + public void CanConvertX14ColorTypeToXlColor() + { + var color1 = new X14.AxisColor { Rgb = new DocumentFormat.OpenXml.HexBinaryValue("FFFF0000") }; + var color2 = new X14.BorderColor { Indexed = new DocumentFormat.OpenXml.UInt32Value((uint)20) }; + var color3 = new X14.FillColor { Theme = new DocumentFormat.OpenXml.UInt32Value((uint)4) }; + var color4 = new X14.HighMarkerColor + { + Theme = new DocumentFormat.OpenXml.UInt32Value((uint)4), + Tint = new DocumentFormat.OpenXml.DoubleValue(0.4) + }; + + var xlColor1 = color1.ToClosedXMLColor(); + var xlColor2 = color2.ToClosedXMLColor(); + var xlColor3 = color3.ToClosedXMLColor(); + var xlColor4 = color4.ToClosedXMLColor(); + + Assert.AreEqual(XLColorType.Color, xlColor1.ColorType); + Assert.AreEqual(XLColor.Red.Color, xlColor1.Color); + + Assert.AreEqual(XLColorType.Indexed, xlColor2.ColorType); + Assert.AreEqual(20, xlColor2.Indexed); + + Assert.AreEqual(XLColorType.Theme, xlColor3.ColorType); + Assert.AreEqual(XLThemeColor.Accent1, xlColor3.ThemeColor); + Assert.AreEqual(0, xlColor3.ThemeTint, XLHelper.Epsilon); + + Assert.AreEqual(XLColorType.Theme, xlColor4.ColorType); + Assert.AreEqual(XLThemeColor.Accent1, xlColor4.ThemeColor); + Assert.AreEqual(0.4, xlColor4.ThemeTint, XLHelper.Epsilon); + } } -} \ No newline at end of file +}