diff --git a/ClosedXML/Excel/Caching/IXLRepository.cs b/ClosedXML/Excel/Caching/IXLRepository.cs new file mode 100644 index 0000000..dd3574b --- /dev/null +++ b/ClosedXML/Excel/Caching/IXLRepository.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + /// + /// Base interface for an abstract repository. + /// + internal interface IXLRepository + { + /// + /// Clear the repository; + /// + void Clear(); + } + + internal interface IXLRepository : IXLRepository, IEnumerable + where Tkey : struct, IEquatable + where Tvalue : class + { + /// + /// Put the into the repository under the specified + /// if there is no such key present. + /// + /// Key to identify the value. + /// Value to put into the repository if key does not exist. + /// Value stored in the repository under the specified . If key already existed + /// returned value may differ from the input one. + Tvalue Store(Tkey key, Tvalue value); + } +} diff --git a/ClosedXML/Excel/Caching/XLAlignmentRepository.cs b/ClosedXML/Excel/Caching/XLAlignmentRepository.cs new file mode 100644 index 0000000..1e091ae --- /dev/null +++ b/ClosedXML/Excel/Caching/XLAlignmentRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLAlignmentRepository : XLRepositoryBase + { + #region Constructors + + public XLAlignmentRepository(Func createNew) + : base(createNew) + { + } + + public XLAlignmentRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLBorderRepository.cs b/ClosedXML/Excel/Caching/XLBorderRepository.cs new file mode 100644 index 0000000..2350e61 --- /dev/null +++ b/ClosedXML/Excel/Caching/XLBorderRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLBorderRepository : XLRepositoryBase + { + #region Constructors + + public XLBorderRepository(Func createNew) + : base(createNew) + { + } + + public XLBorderRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLColorRepository.cs b/ClosedXML/Excel/Caching/XLColorRepository.cs new file mode 100644 index 0000000..d6d671b --- /dev/null +++ b/ClosedXML/Excel/Caching/XLColorRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLColorRepository : XLRepositoryBase + { + #region Constructors + + public XLColorRepository(Func createNew) + : base(createNew) + { + } + + public XLColorRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLFillRepository.cs b/ClosedXML/Excel/Caching/XLFillRepository.cs new file mode 100644 index 0000000..1dbb79a --- /dev/null +++ b/ClosedXML/Excel/Caching/XLFillRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLFillRepository : XLRepositoryBase + { + #region Constructors + + public XLFillRepository(Func createNew) + : base(createNew) + { + } + + public XLFillRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLFontRepository.cs b/ClosedXML/Excel/Caching/XLFontRepository.cs new file mode 100644 index 0000000..ba619ef --- /dev/null +++ b/ClosedXML/Excel/Caching/XLFontRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLFontRepository : XLRepositoryBase + { + #region Constructors + + public XLFontRepository(Func createNew) + : base(createNew) + { + } + + public XLFontRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLNumberFormatRepository.cs b/ClosedXML/Excel/Caching/XLNumberFormatRepository.cs new file mode 100644 index 0000000..80e9d10 --- /dev/null +++ b/ClosedXML/Excel/Caching/XLNumberFormatRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLNumberFormatRepository : XLRepositoryBase + { + #region Constructors + + public XLNumberFormatRepository(Func createNew) + : base(createNew) + { + } + + public XLNumberFormatRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLProtectionRepository.cs b/ClosedXML/Excel/Caching/XLProtectionRepository.cs new file mode 100644 index 0000000..44e7de3 --- /dev/null +++ b/ClosedXML/Excel/Caching/XLProtectionRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLProtectionRepository : XLRepositoryBase + { + #region Constructors + + public XLProtectionRepository(Func createNew) + : base(createNew) + { + } + + public XLProtectionRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLRepositoryBase.cs b/ClosedXML/Excel/Caching/XLRepositoryBase.cs new file mode 100644 index 0000000..5d2c5fe --- /dev/null +++ b/ClosedXML/Excel/Caching/XLRepositoryBase.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Collections; + +namespace ClosedXML.Excel.Caching +{ + internal abstract class XLRepositoryBase : IXLRepository + { + public abstract void Clear(); + } + + internal abstract class XLRepositoryBase : XLRepositoryBase, IXLRepository + where Tkey : struct, IEquatable + where Tvalue : class + { + const int CONCURRENCY_LEVEL = 4; + const int INITIAL_CAPACITY = 1000; + + private readonly ConcurrentDictionary _storage; + private readonly Func _createNew; + protected XLRepositoryBase(Func createNew) + : this(createNew, EqualityComparer.Default) + { + } + + protected XLRepositoryBase(Func createNew, IEqualityComparer comparer) + { + _storage = new ConcurrentDictionary(CONCURRENCY_LEVEL, INITIAL_CAPACITY, comparer); + _createNew = createNew; + } + + /// + /// Check if the specified key is presented in the repository. + /// + /// Key to look for. + /// Value from the repository stored under specified key or null if key does + /// not exist or the entry under this key has already bee GCed. + /// True if entry exists and alive, false otherwise. + public bool ContainsKey(Tkey key, out Tvalue value) + { + WeakReference cachedReference; + if (_storage.TryGetValue(key, out cachedReference)) + { + value = cachedReference.Target as Tvalue; + return (value != null); + } + value = null; + return false; + } + + /// + /// Put the entity into the repository under the specified key if no other entity with + /// the same key is presented. + /// + /// Key to identify the entity. + /// Entity to store. + /// Entity that is stored in the repository under the specified key + /// (it can be either the or another entity that has been added to + /// the repository before.) + public Tvalue Store(Tkey key, Tvalue value) + { + if (value == null) + return null; + + if (!_storage.ContainsKey(key)) + { + _storage.TryAdd(key, new WeakReference(value)); + return value; + } + else + { + var cachedReference = _storage[key]; + var storedValue = cachedReference.Target as Tvalue; + if (storedValue == null) + { + _storage.TryAdd(key, new WeakReference(value)); + return value; + } + return storedValue; + } + } + + /// + /// Create a new entity using specified key and put it into the repository or + /// return the existing entity ith this key. + /// + public Tvalue GetOrCreate(Tkey key) + { + WeakReference cachedReference; + if (_storage.TryGetValue(key, out cachedReference)) + { + var storedValue = cachedReference.Target as Tvalue; + if (storedValue != null) + { + return storedValue; + } + else + { + WeakReference _; + _storage.TryRemove(key, out _); + } + } + + var value = _createNew(key); + return Store(key, value); + } + + public override void Clear() + { + _storage.Clear(); + } + + /// + /// Enumerate items in repository removing "dead" entries. + /// + public IEnumerator GetEnumerator() + { + return _storage + .Select(pair => + { + var val = pair.Value.Target as Tvalue; + if (val == null) + { + WeakReference _; + _storage.TryRemove(pair.Key, out _); + } + return val; + }) + .Where(val => val != null) + .GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/ClosedXML/Excel/Caching/XLStyleRepository.cs b/ClosedXML/Excel/Caching/XLStyleRepository.cs new file mode 100644 index 0000000..d5105d4 --- /dev/null +++ b/ClosedXML/Excel/Caching/XLStyleRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + internal sealed class XLStyleRepository : XLRepositoryBase + { + #region Constructors + + public XLStyleRepository(Func createNew) + : base(createNew) + { + } + + public XLStyleRepository(Func createNew, IEqualityComparer comparer) + : base(createNew, comparer) + { + } + + #endregion Constructors + } +} diff --git a/ClosedXML/Excel/Caching/XLWorkbookElementRepositoryBase.cs b/ClosedXML/Excel/Caching/XLWorkbookElementRepositoryBase.cs new file mode 100644 index 0000000..a001f12 --- /dev/null +++ b/ClosedXML/Excel/Caching/XLWorkbookElementRepositoryBase.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel.Caching +{ + /// + /// Base repository for elements. + /// + internal abstract class XLWorkbookElementRepositoryBase : XLRepositoryBase + where Tkey : struct, IEquatable + where Tvalue : class + { + public XLWorkbook Workbook { get; private set; } + + public XLWorkbookElementRepositoryBase(XLWorkbook workbook, Func createNew) + : this(workbook, createNew, EqualityComparer.Default) + { + } + + public XLWorkbookElementRepositoryBase(XLWorkbook workbook, Func createNew, IEqualityComparer сomparer) + : base(createNew, сomparer) + { + Workbook = workbook; + } + } +} diff --git a/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/Excel/Cells/XLCell.cs index 30fca92..dab1b88 100644 --- a/ClosedXML/Excel/Cells/XLCell.cs +++ b/ClosedXML/Excel/Cells/XLCell.cs @@ -16,7 +16,7 @@ using ClosedXML.Extensions; [DebuggerDisplay("{Address}")] - internal class XLCell : IXLCell, IXLStylized + internal class XLCell : XLStylizedBase, IXLCell, IXLStylized { public static readonly DateTime BaseDate = new DateTime(1899, 12, 30); @@ -73,31 +73,34 @@ internal XLDataType _dataType; private XLHyperlink _hyperlink; private XLRichText _richText; - private Int32? _styleCacheId; public bool SettingHyperlink; public int SharedStringId; private string _formulaA1; private string _formulaR1C1; - private IXLStyle _style; #endregion Fields #region Constructor - public XLCell(XLWorksheet worksheet, XLAddress address, Int32 styleId) - : this(worksheet, address) - { - SetStyle(styleId); - } - - public XLCell(XLWorksheet worksheet, XLAddress address) + internal XLCell(XLWorksheet worksheet, XLAddress address, XLStyleValue styleValue) + : base(styleValue) { Address = address; ShareString = true; _worksheet = worksheet; } + public XLCell(XLWorksheet worksheet, XLAddress address, IXLStyle style) + : this(worksheet, address, (style as XLStyle).Value) + { + } + + public XLCell(XLWorksheet worksheet, XLAddress address) + : this(worksheet, address, XLStyle.Default.Value) + { + } + #endregion Constructor public XLWorksheet Worksheet @@ -227,7 +230,7 @@ { _cellValue = value.ToString(); _dataType = XLDataType.Text; - if (_cellValue.Contains(Environment.NewLine) && !GetStyleForRead().Alignment.WrapText) + if (_cellValue.Contains(Environment.NewLine) && !style.Alignment.WrapText) Style.Alignment.WrapText = true; } else if (value is TimeSpan) @@ -353,7 +356,7 @@ return cValue; } else - return cValue; + return cValue; } /// @@ -907,13 +910,6 @@ return InsertData(dataTable.Rows); } - public IXLStyle Style - { - get { return GetStyle(); } - - set { SetStyle(value); } - } - public IXLCell SetDataType(XLDataType dataType) { DataType = dataType; @@ -1157,10 +1153,10 @@ if (SettingHyperlink) return; - if (GetStyleForRead().Font.FontColor.Equals(_worksheet.Style.Font.FontColor)) + if (GetStyleForRead().Font.FontColor.Equals(_worksheet.StyleValue.Font.FontColor)) Style.Font.FontColor = XLColor.FromTheme(XLThemeColor.Hyperlink); - if (GetStyleForRead().Font.Underline == _worksheet.Style.Font.Underline) + if (GetStyleForRead().Font.Underline == _worksheet.StyleValue.Font.Underline) Style.Font.Underline = XLFontUnderlineValues.Single; } } @@ -1213,8 +1209,8 @@ { var style = GetStyleForRead(); _richText = _cellValue.Length == 0 - ? new XLRichText(style.Font) - : new XLRichText(GetFormattedString(), style.Font); + ? new XLRichText(new XLFont(Style as XLStyle, style.Font)) + : new XLRichText(GetFormattedString(), new XLFont(Style as XLStyle, style.Font)); } return _richText; @@ -1263,17 +1259,17 @@ if (includeNormalFormats) { - if (!Style.Equals(Worksheet.Style) || IsMerged() || HasComment || HasDataValidation) + if (!StyleValue.Equals(Worksheet.StyleValue) || IsMerged() || HasComment || HasDataValidation) return false; - if (_style == null) + if (StyleValue.Equals(Worksheet.StyleValue)) { XLRow row; - if (Worksheet.Internals.RowsCollection.TryGetValue(_rowNumber, out row) && !row.Style.Equals(Worksheet.Style)) + if (Worksheet.Internals.RowsCollection.TryGetValue(_rowNumber, out row) && !row.StyleValue.Equals(Worksheet.StyleValue)) return false; XLColumn column; - if (Worksheet.Internals.ColumnsCollection.TryGetValue(_columnNumber, out column) && !column.Style.Equals(Worksheet.Style)) + if (Worksheet.Internals.ColumnsCollection.TryGetValue(_columnNumber, out column) && !column.StyleValue.Equals(Worksheet.StyleValue)) return false; } } @@ -1570,27 +1566,20 @@ #region IXLStylized Members - public Boolean StyleChanged { get; set; } - - public IEnumerable Styles + public override IEnumerable Styles { get { - UpdatingStyle = true; yield return Style; - UpdatingStyle = false; } } - public bool UpdatingStyle { get; set; } - - public IXLStyle InnerStyle + protected override IEnumerable Children { - get { return Style; } - set { Style = value; } + get { yield break; } } - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { @@ -1705,51 +1694,19 @@ #region Styles - private IXLStyle GetStyle() + private XLStyleValue GetStyleForRead() { - if (_style != null) - return _style; - - return _style = new XLStyle(this, Worksheet.Workbook.GetStyleById(StyleCacheId())); - } - - private IXLStyle GetStyleForRead() - { - return Worksheet.Workbook.GetStyleById(GetStyleId()); - } - - public Int32 GetStyleId() - { - if (StyleChanged) - SetStyle(Style); - - return StyleCacheId(); + return StyleValue; } private void SetStyle(IXLStyle styleToUse) { - _styleCacheId = Worksheet.Workbook.GetStyleId(styleToUse); - _style = null; - StyleChanged = false; - } - - private void SetStyle(Int32 styleId) - { - _styleCacheId = styleId; - _style = null; - StyleChanged = false; - } - - public Int32 StyleCacheId() - { - if (!_styleCacheId.HasValue) - _styleCacheId = Worksheet.GetStyleId(); - return _styleCacheId.Value; + Style = styleToUse; } public Boolean IsDefaultWorksheetStyle() { - return !_styleCacheId.HasValue && !StyleChanged || GetStyleId() == Worksheet.GetStyleId(); + return StyleValue == Worksheet.StyleValue; } #endregion Styles @@ -2254,8 +2211,7 @@ { CopyValuesFrom(otherCell); - if (otherCell._styleCacheId.HasValue) - SetStyle(otherCell._style ?? otherCell.Worksheet.Workbook.GetStyleById(otherCell._styleCacheId.Value)); + InnerStyle = otherCell.InnerStyle; if (copyDataValidations) { diff --git a/ClosedXML/Excel/Cells/XLCells.cs b/ClosedXML/Excel/Cells/XLCells.cs index 1fbc0be..413ddfe 100644 --- a/ClosedXML/Excel/Cells/XLCells.cs +++ b/ClosedXML/Excel/Cells/XLCells.cs @@ -6,16 +6,13 @@ { using System.Linq; - internal class XLCells : IXLCells, IXLStylized, IEnumerable + internal class XLCells : XLStylizedBase, IXLCells, IXLStylized, IEnumerable { - public Boolean StyleChanged { get; set; } - #region Fields private readonly bool _includeFormats; private readonly List _rangeAddresses = new List(); private readonly bool _usedCellsOnly; - private IXLStyle _style; private readonly Func _predicate; #endregion Fields @@ -23,8 +20,8 @@ #region Constructor public XLCells(bool usedCellsOnly, bool includeFormats, Func predicate = null) + :base(XLStyle.Default.Value) { - _style = new XLStyle(this, XLWorkbook.DefaultStyle); _usedCellsOnly = usedCellsOnly; _includeFormats = includeFormats; _predicate = predicate; @@ -170,16 +167,6 @@ return GetEnumerator(); } - public IXLStyle Style - { - get { return _style; } - set - { - _style = new XLStyle(this, value); - this.ForEach(c => c.Style = _style); - } - } - public Object Value { set { this.ForEach(c => c.Value = value); } @@ -220,28 +207,26 @@ #endregion IXLCells Members #region IXLStylized Members - - public IEnumerable Styles + public override IEnumerable Styles { get { - UpdatingStyle = true; - yield return _style; + yield return Style; foreach (XLCell c in this) yield return c.Style; - UpdatingStyle = false; } } - public Boolean UpdatingStyle { get; set; } - - public IXLStyle InnerStyle + protected override IEnumerable Children { - get { return _style; } - set { _style = new XLStyle(this, value); } + get + { + foreach (XLCell c in this) + yield return c; + } } - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { diff --git a/ClosedXML/Excel/Cells/XLCellsCollection.cs b/ClosedXML/Excel/Cells/XLCellsCollection.cs index 8f11a98..2a70742 100644 --- a/ClosedXML/Excel/Cells/XLCellsCollection.cs +++ b/ClosedXML/Excel/Cells/XLCellsCollection.cs @@ -144,33 +144,6 @@ } } - internal HashSet GetStyleIds(Int32 initial) - { - HashSet ids = new HashSet(); - ids.Add(initial); - foreach (var row in rowsCollection.Values) - { - foreach (var cell in row.Values) - { - Int32? id = null; - - if (cell.StyleChanged) - id = cell.GetStyleId(); - else if (cell.StyleCacheId() != cell.Worksheet.GetStyleId()) - { - id = cell.GetStyleId(); - } - - if (id.HasValue && !ids.Contains(id.Value)) - { - ids.Add(id.Value); - } - } - } - return ids; - } - - internal IEnumerable GetCellsUsed(Int32 rowStart, Int32 columnStart, Int32 rowEnd, Int32 columnEnd, Boolean includeFormats, Func predicate = null) diff --git a/ClosedXML/Excel/Columns/XLColumn.cs b/ClosedXML/Excel/Columns/XLColumn.cs index 9a94c32..791c595 100644 --- a/ClosedXML/Excel/Columns/XLColumn.cs +++ b/ClosedXML/Excel/Columns/XLColumn.cs @@ -23,7 +23,9 @@ : base( new XLRangeAddress(new XLAddress(xlColumnParameters.Worksheet, 1, column, false, false), new XLAddress(xlColumnParameters.Worksheet, XLHelper.MaxRowNumber, column, false, - false))) + false)), + xlColumnParameters.IsReference ? xlColumnParameters.Worksheet.Internals.ColumnsCollection[column].StyleValue + : (xlColumnParameters.DefaultStyle as XLStyle).Value) { SetColumnNumber(column); @@ -32,7 +34,6 @@ SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); else { - SetStyle(xlColumnParameters.DefaultStyleId); _width = xlColumnParameters.Worksheet.ColumnWidth; } } @@ -41,7 +42,8 @@ : base( new XLRangeAddress(new XLAddress(column.Worksheet, 1, column.ColumnNumber(), false, false), new XLAddress(column.Worksheet, XLHelper.MaxRowNumber, column.ColumnNumber(), - false, false))) + false, false)), + column.StyleValue) { _width = column._width; IsReference = column.IsReference; @@ -50,7 +52,6 @@ _collapsed = column._collapsed; _isHidden = column._isHidden; _outlineLevel = column._outlineLevel; - SetStyle(column.GetStyleId()); } #endregion Constructor @@ -61,35 +62,30 @@ { get { - UpdatingStyle = true; - - yield return Style; + if (IsReference) + yield return Worksheet.Internals.ColumnsCollection[ColumnNumber()].Style; + else + yield return Style; int column = ColumnNumber(); foreach (XLCell cell in Worksheet.Internals.CellsCollection.GetCellsInColumn(column)) yield return cell.Style; - - UpdatingStyle = false; } } - public override Boolean UpdatingStyle { get; set; } - - public override IXLStyle InnerStyle + protected override IEnumerable Children { get { - return IsReference - ? Worksheet.Internals.ColumnsCollection[ColumnNumber()].InnerStyle - : GetStyle(); - } - set - { + int column = ColumnNumber(); if (IsReference) - Worksheet.Internals.ColumnsCollection[ColumnNumber()].InnerStyle = value; + yield return Worksheet.Internals.ColumnsCollection[column]; else - SetStyle(value); + { + foreach (XLCell cell in Worksheet.Internals.CellsCollection.GetCellsInColumn(column)) + yield return cell; + } } } @@ -176,45 +172,6 @@ return Cells(firstRow + ":" + lastRow); } - public override IXLStyle Style - { - get { return IsReference ? Worksheet.Internals.ColumnsCollection[ColumnNumber()].Style : GetStyle(); } - set - { - if (IsReference) - Worksheet.Internals.ColumnsCollection[ColumnNumber()].Style = value; - else - { - SetStyle(value); - - Int32 minRow = 1; - Int32 maxRow = 0; - int column = ColumnNumber(); - if (Worksheet.Internals.CellsCollection.ColumnsUsed.ContainsKey(column)) - { - minRow = Worksheet.Internals.CellsCollection.MinRowInColumn(column); - maxRow = Worksheet.Internals.CellsCollection.MaxRowInColumn(column); - } - - if (Worksheet.Internals.RowsCollection.Count > 0) - { - Int32 minInCollection = Worksheet.Internals.RowsCollection.Keys.Min(); - Int32 maxInCollection = Worksheet.Internals.RowsCollection.Keys.Max(); - if (minInCollection < minRow) - minRow = minInCollection; - if (maxInCollection > maxRow) - maxRow = maxInCollection; - } - - if (minRow > 0 && maxRow > 0) - { - for (Int32 ro = minRow; ro <= maxRow; ro++) - Worksheet.Cell(ro, column).Style = value; - } - } - } - } - public new IXLColumns InsertColumnsAfter(Int32 numberOfColumns) { int columnNum = ColumnNumber(); @@ -262,7 +219,7 @@ { var internalColumn = Worksheet.Internals.ColumnsCollection[newColumn.ColumnNumber()]; internalColumn._width = Width; - internalColumn.SetStyle(Style); + internalColumn.InnerStyle = InnerStyle; internalColumn._collapsed = Collapsed; internalColumn._isHidden = IsHidden; internalColumn._outlineLevel = OutlineLevel; @@ -310,12 +267,15 @@ && !autoFilterRows.Contains(t.AutoFilter.Range.FirstRow().RowNumber())) .Select(t => t.AutoFilter.Range.FirstRow().RowNumber())); - foreach (XLCell c in Column(startRow, endRow).CellsUsed()) + XLStyle cellStyle = null; + foreach (var c in Column(startRow, endRow).CellsUsed().Cast()) { if (c.IsMerged()) continue; + if (cellStyle == null || cellStyle.Value != c.StyleValue) + cellStyle = c.Style as XLStyle; Double thisWidthMax = 0; - Int32 textRotation = c.Style.Alignment.TextRotation; + Int32 textRotation = cellStyle.Alignment.TextRotation; if (c.HasRichText || textRotation != 0 || c.InnerText.Contains(Environment.NewLine)) { var kpList = new List>(); @@ -348,7 +308,7 @@ String s = arr[i]; if (i < arrCount - 1) s += Environment.NewLine; - kpList.Add(new KeyValuePair(c.Style.Font, s)); + kpList.Add(new KeyValuePair(cellStyle.Font, s)); } } @@ -451,7 +411,7 @@ #endregion if (rotated) } else - thisWidthMax = c.Style.Font.GetWidth(c.GetFormattedString(), fontCache); + thisWidthMax = cellStyle.Font.GetWidth(c.GetFormattedString(), fontCache); if (autoFilterRows.Contains(c.Address.RowNumber)) thisWidthMax += 2.7148; // Allow room for arrow icon in autofilter @@ -607,7 +567,7 @@ column.Clear(); var newColumn = (XLColumn)column; newColumn._width = _width; - newColumn.Style = GetStyle(); + newColumn.InnerStyle = InnerStyle; using (var asRange = AsRange()) asRange.CopyTo(column).Dispose(); @@ -780,7 +740,7 @@ public override Boolean IsEmpty(Boolean includeFormats) { - if (includeFormats && !Style.Equals(Worksheet.Style)) + if (includeFormats && !StyleValue.Equals(Worksheet.StyleValue)) return false; return base.IsEmpty(includeFormats); diff --git a/ClosedXML/Excel/Columns/XLColumnParameters.cs b/ClosedXML/Excel/Columns/XLColumnParameters.cs index 2842a5b..bf7056b 100644 --- a/ClosedXML/Excel/Columns/XLColumnParameters.cs +++ b/ClosedXML/Excel/Columns/XLColumnParameters.cs @@ -5,13 +5,13 @@ { internal class XLColumnParameters { - public XLColumnParameters(XLWorksheet worksheet, Int32 defaultStyleId, Boolean isReference) + public XLColumnParameters(XLWorksheet worksheet, IXLStyle defaultStyle, Boolean isReference) { Worksheet = worksheet; - DefaultStyleId = defaultStyleId; + DefaultStyle = defaultStyle; IsReference = isReference; } - public Int32 DefaultStyleId { get; set; } + public IXLStyle DefaultStyle { get; private set; } public XLWorksheet Worksheet { get; private set; } public Boolean IsReference { get; private set; } } diff --git a/ClosedXML/Excel/Columns/XLColumns.cs b/ClosedXML/Excel/Columns/XLColumns.cs index 05f7a7d..8a992d2 100644 --- a/ClosedXML/Excel/Columns/XLColumns.cs +++ b/ClosedXML/Excel/Columns/XLColumns.cs @@ -6,17 +6,15 @@ { using System.Collections; - internal class XLColumns : IXLColumns, IXLStylized + internal class XLColumns : XLStylizedBase, IXLColumns, IXLStylized { - public Boolean StyleChanged { get; set; } private readonly List _columns = new List(); private readonly XLWorksheet _worksheet; - internal IXLStyle style; public XLColumns(XLWorksheet worksheet) + : base(XLStyle.Default.Value) { _worksheet = worksheet; - style = new XLStyle(this, XLWorkbook.DefaultStyle); } #region IXLColumns Members @@ -31,23 +29,6 @@ return GetEnumerator(); } - public IXLStyle Style - { - get { return style; } - set - { - style = new XLStyle(this, value); - - if (_worksheet != null) - _worksheet.Style = value; - else - { - foreach (XLColumn column in _columns) - column.Style = value; - } - } - } - public Double Width { set @@ -217,12 +198,11 @@ #region IXLStylized Members - public IEnumerable Styles + public override IEnumerable Styles { get { - UpdatingStyle = true; - yield return style; + yield return Style; if (_worksheet != null) yield return _worksheet.Style; else @@ -232,19 +212,24 @@ yield return s; } } - UpdatingStyle = false; } } - public Boolean UpdatingStyle { get; set; } - - public IXLStyle InnerStyle + protected override IEnumerable Children { - get { return style; } - set { style = new XLStyle(this, value); } + get + { + if (_worksheet != null) + yield return _worksheet; + else + { + foreach (XLColumn column in _columns) + yield return column; + } + } } - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFCellIsConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFCellIsConverter.cs index dfad5bc..2a3bf8e 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFCellIsConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFCellIsConverter.cs @@ -10,9 +10,9 @@ String val = GetQuoted(cf.Values[1]); var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; conditionalFormattingRule.Operator = cf.Operator.ToOpenXml(); diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs index 5e33f41..435e690 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs @@ -9,9 +9,9 @@ { String val = cf.Values[1].Value; var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; conditionalFormattingRule.Operator = ConditionalFormattingOperatorValues.ContainsText; conditionalFormattingRule.Text = val; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFDatesOccuringConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFDatesOccuringConverter.cs index 24e1129..a1375b7 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFDatesOccuringConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFDatesOccuringConverter.cs @@ -23,9 +23,9 @@ public ConditionalFormattingRule Convert(IXLConditionalFormat cf, int priority, XLWorkbook.SaveContext context) { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; conditionalFormattingRule.TimePeriod = cf.TimePeriod.ToOpenXml(); diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs index 230f0f6..a65194a 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs @@ -9,9 +9,9 @@ { String val = cf.Values[1].Value; var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; conditionalFormattingRule.Operator = ConditionalFormattingOperatorValues.EndsWith; conditionalFormattingRule.Text = val; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsBlankConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsBlankConverter.cs index fdd7442..07eccac 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsBlankConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsBlankConverter.cs @@ -8,9 +8,9 @@ public ConditionalFormattingRule Convert(IXLConditionalFormat cf, int priority, XLWorkbook.SaveContext context) { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; var formula = new Formula { Text = "LEN(TRIM(" + cf.Range.RangeAddress.FirstAddress.ToStringRelative(false) + "))=0" }; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsErrorConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsErrorConverter.cs index 88ad11c..1cfb4fe 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsErrorConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsErrorConverter.cs @@ -8,9 +8,9 @@ public ConditionalFormattingRule Convert(IXLConditionalFormat cf, int priority, XLWorkbook.SaveContext context) { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; var formula = new Formula { Text = "ISERROR(" + cf.Range.RangeAddress.FirstAddress.ToStringRelative(false) + ")" }; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotBlankConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotBlankConverter.cs index 134a763..4e36698 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotBlankConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotBlankConverter.cs @@ -8,9 +8,9 @@ public ConditionalFormattingRule Convert(IXLConditionalFormat cf, int priority, XLWorkbook.SaveContext context) { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; var formula = new Formula { Text = "LEN(TRIM(" + cf.Range.RangeAddress.FirstAddress.ToStringRelative(false) + "))>0" }; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotContainsConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotContainsConverter.cs index a0342f1..8849d74 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotContainsConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotContainsConverter.cs @@ -9,9 +9,9 @@ { String val = cf.Values[1].Value; var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; conditionalFormattingRule.Operator = ConditionalFormattingOperatorValues.NotContains; conditionalFormattingRule.Text = val; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotErrorConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotErrorConverter.cs index 57ccd6f..51b794b 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotErrorConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotErrorConverter.cs @@ -8,9 +8,9 @@ public ConditionalFormattingRule Convert(IXLConditionalFormat cf, int priority, XLWorkbook.SaveContext context) { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; var formula = new Formula { Text = "NOT(ISERROR(" + cf.Range.RangeAddress.FirstAddress.ToStringRelative(false) + "))" }; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFStartsWithConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFStartsWithConverter.cs index 6442a59..5f1721e 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFStartsWithConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFStartsWithConverter.cs @@ -9,9 +9,9 @@ { String val = cf.Values[1].Value; var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; conditionalFormattingRule.Operator = ConditionalFormattingOperatorValues.BeginsWith; conditionalFormattingRule.Text = val; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFTopConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFTopConverter.cs index 9a1f572..cc4accc 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFTopConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFTopConverter.cs @@ -9,9 +9,9 @@ { UInt32 val = UInt32.Parse(cf.Values[1].Value); var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; conditionalFormattingRule.Percent = cf.Percent; conditionalFormattingRule.Rank = val; diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFUniqueConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFUniqueConverter.cs index bba890e..7c5035e 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFUniqueConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFUniqueConverter.cs @@ -8,9 +8,9 @@ public ConditionalFormattingRule Convert(IXLConditionalFormat cf, int priority, XLWorkbook.SaveContext context) { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + var cfStyle = (cf.Style as XLStyle).Value; + if (!cfStyle.Equals(XLWorkbook.DefaultStyleValue)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cfStyle.Key]; return conditionalFormattingRule; } diff --git a/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs b/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs index 7c47c57..3ff620a 100644 --- a/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs +++ b/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs @@ -5,7 +5,7 @@ namespace ClosedXML.Excel { - internal class XLConditionalFormat : IXLConditionalFormat, IXLStylized + internal class XLConditionalFormat : XLStylizedBase, IXLConditionalFormat, IXLStylized { private sealed class FullEqualityComparer : IEqualityComparer { @@ -34,12 +34,11 @@ var xxFormulas = xx.Values.Values.Where(v => v.IsFormula).Select(f => ((XLCell)x.Range.FirstCell()).GetFormulaR1C1(f.Value)); var yyFormulas = yy.Values.Values.Where(v => v.IsFormula).Select(f => ((XLCell)y.Range.FirstCell()).GetFormulaR1C1(f.Value)); - var xStyle = xx._style ?? xx.Range.Worksheet.Workbook.GetStyleById(xx._styleCacheId); - var yStyle = yy._style ?? yy.Range.Worksheet.Workbook.GetStyleById(yy._styleCacheId); + var xStyle = xx.StyleValue; + var yStyle = yy.StyleValue; return Equals(xStyle, yStyle) && xx.CopyDefaultModify == yy.CopyDefaultModify - && xx.UpdatingStyle == yy.UpdatingStyle && xx.ConditionalFormatType == yy.ConditionalFormatType && xx.TimePeriod == yy.TimePeriod && xx.IconSetStyle == yy.IconSetStyle @@ -61,16 +60,15 @@ public int GetHashCode(IXLConditionalFormat obj) { var xx = (XLConditionalFormat)obj; - var xStyle = xx._style ?? xx.Range.Worksheet.Workbook.GetStyleById(xx._styleCacheId); + var xStyle = (obj.Style as XLStyle).Value; var xValues = xx.Values.Values.Where(v => !v.IsFormula).Select(v => v.Value) .Union(xx.Values.Values.Where(v => v.IsFormula).Select(f => ((XLCell)obj.Range.FirstCell()).GetFormulaR1C1(f.Value))); unchecked { var hashCode = xStyle.GetHashCode(); - hashCode = (hashCode * 397) ^ xx._styleCacheId; + hashCode = (hashCode * 397) ^ xx.StyleValue.GetHashCode(); hashCode = (hashCode * 397) ^ xx.CopyDefaultModify.GetHashCode(); - hashCode = (hashCode * 397) ^ xx.UpdatingStyle.GetHashCode(); hashCode = (hashCode * 397) ^ xValues.GetHashCode(); hashCode = (hashCode * 397) ^ (xx.Colors != null ? xx.Colors.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (xx.ContentTypes != null ? xx.ContentTypes.GetHashCode() : 0); @@ -104,10 +102,10 @@ } public XLConditionalFormat(XLRange range, Boolean copyDefaultModify = false) + : base(XLStyle.Default.Value) { Id = Guid.NewGuid(); Range = range; - Style = new XLStyle(this, range.Worksheet.Style); Values = new XLDictionary(); Colors = new XLDictionary(); ContentTypes = new XLDictionary(); @@ -117,10 +115,10 @@ } public XLConditionalFormat(XLConditionalFormat conditionalFormat, IXLRange targetRange) + : base(conditionalFormat.StyleValue) { Range = targetRange; Id = Guid.NewGuid(); - Style = new XLStyle(this, conditionalFormat.Style); Values = new XLDictionary(conditionalFormat.Values); Colors = new XLDictionary(conditionalFormat.Colors); ContentTypes = new XLDictionary(conditionalFormat.ContentTypes); @@ -144,45 +142,25 @@ public Guid Id { get; internal set; } internal Int32 OriginalPriority { get; set; } public Boolean CopyDefaultModify { get; set; } - private IXLStyle _style; - private Int32 _styleCacheId; - public IXLStyle Style { get { return GetStyle(); } set { SetStyle(value); } } - private IXLStyle GetStyle() - { - //return _style; - if (_style != null) - return _style; - return _style = new XLStyle(this, Range.Worksheet.Workbook.GetStyleById(_styleCacheId), CopyDefaultModify); - } - private void SetStyle(IXLStyle styleToUse) - { - //_style = new XLStyle(this, styleToUse); - _styleCacheId = Range.Worksheet.Workbook.GetStyleId(styleToUse); - _style = null; - StyleChanged = false; - } - - public IEnumerable Styles + public override IEnumerable Styles { get { - UpdatingStyle = true; yield return Style; - UpdatingStyle = false; } } - public bool UpdatingStyle { get; set; } - - public IXLStyle InnerStyle { get; set; } - - public IXLRanges RangesUsed + protected override IEnumerable Children + { + get { yield break; } + } + + public override IXLRanges RangesUsed { get { return new XLRanges(); } } - public bool StyleChanged { get; set; } public XLDictionary Values { get; private set; } public XLDictionary Colors { get; private set; } public XLDictionary ContentTypes { get; private set; } @@ -213,7 +191,7 @@ public void CopyFrom(IXLConditionalFormat other) { - Style = other.Style; + InnerStyle = other.Style; ConditionalFormatType = other.ConditionalFormatType; TimePeriod = other.TimePeriod; IconSetStyle = other.IconSetStyle; diff --git a/ClosedXML/Excel/Hyperlinks/XLHyperlink_public.cs b/ClosedXML/Excel/Hyperlinks/XLHyperlink_public.cs index 376809a..cbc96f5 100644 --- a/ClosedXML/Excel/Hyperlinks/XLHyperlink_public.cs +++ b/ClosedXML/Excel/Hyperlinks/XLHyperlink_public.cs @@ -102,9 +102,9 @@ if (Cell == null) return; Worksheet.Hyperlinks.Delete(Cell.Address); if (Cell.Style.Font.FontColor.Equals(XLColor.FromTheme(XLThemeColor.Hyperlink))) - Cell.Style.Font.FontColor = Worksheet.Style.Font.FontColor; + Cell.Style.Font.FontColor = Worksheet.StyleValue.Font.FontColor; - Cell.Style.Font.Underline = Worksheet.Style.Font.Underline; + Cell.Style.Font.Underline = Worksheet.StyleValue.Font.Underline; } } } diff --git a/ClosedXML/Excel/Ranges/XLRange.cs b/ClosedXML/Excel/Ranges/XLRange.cs index 4f5f4d2..fbee6dd 100644 --- a/ClosedXML/Excel/Ranges/XLRange.cs +++ b/ClosedXML/Excel/Ranges/XLRange.cs @@ -9,7 +9,7 @@ #region Constructor public XLRange(XLRangeParameters xlRangeParameters) - : base(xlRangeParameters.RangeAddress) + : base(xlRangeParameters.RangeAddress, (xlRangeParameters.DefaultStyle as XLStyle).Value) { RangeParameters = new XLRangeParameters(xlRangeParameters.RangeAddress, xlRangeParameters.DefaultStyle); @@ -19,7 +19,6 @@ SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); //xlRangeParameters.IgnoreEvents = true; } - SetStyle(xlRangeParameters.DefaultStyle); } #endregion Constructor @@ -246,7 +245,7 @@ foreach (IXLCell c in Range(1, 1, columnCount, rowCount).Cells()) { - var border = new XLBorder(this, c.Style.Border); + var border = (c.Style as XLStyle).Value.Border; c.Style.Border.TopBorder = border.LeftBorder; c.Style.Border.TopBorderColor = border.LeftBorderColor; c.Style.Border.LeftBorder = border.TopBorder; @@ -743,7 +742,7 @@ var oldCell = rngToTranspose.Cell(ro, co); var newKey = rngToTranspose.Cell(co, ro).Address; // new XLAddress(Worksheet, c.Address.ColumnNumber, c.Address.RowNumber); - var newCell = new XLCell(Worksheet, newKey, oldCell.GetStyleId()); + var newCell = new XLCell(Worksheet, newKey, oldCell.StyleValue); newCell.CopyFrom(oldCell, true); cellsToInsert.Add(new XLSheetPoint(newKey.RowNumber, newKey.ColumnNumber), newCell); cellsToDelete.Add(new XLSheetPoint(oldCell.Address.RowNumber, oldCell.Address.ColumnNumber)); diff --git a/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/Excel/Ranges/XLRangeBase.cs index 5c9e661..f2a9831 100644 --- a/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -9,45 +9,18 @@ namespace ClosedXML.Excel { - internal abstract class XLRangeBase : IXLRangeBase, IXLStylized + internal abstract class XLRangeBase : XLStylizedBase, IXLRangeBase, IXLStylized { - public Boolean StyleChanged { get; set; } - #region Fields - private IXLStyle _style; private XLSortElements _sortRows; private XLSortElements _sortColumns; #endregion Fields - - private Int32 _styleCacheId; - - protected void SetStyle(IXLStyle styleToUse) - { - _styleCacheId = Worksheet.Workbook.GetStyleId(styleToUse); - _style = null; - StyleChanged = false; - } - - protected void SetStyle(Int32 styleId) - { - _styleCacheId = styleId; - _style = null; - StyleChanged = false; - } - - public Int32 GetStyleId() - { - if (StyleChanged) - SetStyle(Style); - - return _styleCacheId; - } - + protected IXLStyle GetStyle() { - return _style ?? (_style = new XLStyle(this, Worksheet.Workbook.GetStyleById(_styleCacheId))); + return Style; } #region Constructor @@ -55,7 +28,8 @@ private static Int32 IdCounter = 0; private readonly Int32 Id; - protected XLRangeBase(XLRangeAddress rangeAddress) + protected XLRangeBase(XLRangeAddress rangeAddress, XLStyleValue styleValue) + : base(styleValue) { Id = ++IdCounter; @@ -209,7 +183,7 @@ #region IXLStylized Members - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { @@ -218,6 +192,23 @@ } } + protected override IEnumerable Children + { + get + { + foreach (var cell in Cells().OfType()) + yield return cell; + } + } + + public override IEnumerable Styles + { + get + { + foreach (IXLCell cell in Cells()) + yield return cell.Style; + } + } #endregion IXLStylized Members #endregion Public properties @@ -471,12 +462,6 @@ ); } - public virtual IXLStyle Style - { - get { return GetStyle(); } - set { Cells().ForEach(c => c.Style = value); } - } - IXLRange IXLRangeBase.AsRange() { return AsRange(); @@ -548,30 +533,7 @@ } #endregion IXLRangeBase Members - - #region IXLStylized Members - - public virtual IEnumerable Styles - { - get - { - UpdatingStyle = true; - foreach (IXLCell cell in Cells()) - yield return cell.Style; - UpdatingStyle = false; - } - } - - public virtual Boolean UpdatingStyle { get; set; } - - public virtual IXLStyle InnerStyle - { - get { return GetStyle(); } - set { SetStyle(value); } - } - - #endregion IXLStylized Members - + public IXLCells Search(String searchText, CompareOptions compareOptions = CompareOptions.Ordinal, Boolean searchFormulae = false) { var culture = CultureInfo.CurrentCulture; @@ -841,19 +803,18 @@ if (cell != null) return cell; - Int32 styleId = GetStyleId(); - Int32 worksheetStyleId = Worksheet.GetStyleId(); + var styleValue = this.StyleValue; - if (styleId == worksheetStyleId) + if (styleValue == Worksheet.StyleValue) { XLRow row; XLColumn column; if (Worksheet.Internals.RowsCollection.TryGetValue(absRow, out row) - && row.GetStyleId() != worksheetStyleId) - styleId = row.GetStyleId(); + && row.StyleValue != Worksheet.StyleValue) + styleValue = row.StyleValue; else if (Worksheet.Internals.ColumnsCollection.TryGetValue(absColumn, out column) - && column.GetStyleId() != worksheetStyleId) - styleId = column.GetStyleId(); + && column.StyleValue != Worksheet.StyleValue) + styleValue = column.StyleValue; } var absoluteAddress = new XLAddress(this.Worksheet, absRow, @@ -861,15 +822,9 @@ cellAddressInRange.FixedRow, cellAddressInRange.FixedColumn); - Int32 newCellStyleId = styleId; - - XLCell newCell; // If the default style for this range base is empty, but the worksheet // has a default style, use the worksheet's default style - if (styleId == 0 && worksheetStyleId != 0 || styleId == worksheetStyleId) - newCell = new XLCell(Worksheet, absoluteAddress); - else - newCell = new XLCell(Worksheet, absoluteAddress, newCellStyleId); + XLCell newCell = new XLCell(Worksheet, absoluteAddress, styleValue); Worksheet.Internals.CellsCollection.Add(absRow, absColumn, newCell); return newCell; @@ -1152,7 +1107,7 @@ var oldCell = Worksheet.Internals.CellsCollection.GetCell(ro, co) ?? Worksheet.Cell(oldKey); - var newCell = new XLCell(Worksheet, newKey, oldCell.GetStyleId()); + var newCell = new XLCell(Worksheet, newKey, oldCell.StyleValue); newCell.CopyValuesFrom(oldCell); newCell.FormulaA1 = oldCell.FormulaA1; cellsToInsert.Add(newKey, newCell); @@ -1175,7 +1130,7 @@ { int newColumn = c.Address.ColumnNumber + numberOfColumns; var newKey = new XLAddress(Worksheet, c.Address.RowNumber, newColumn, false, false); - var newCell = new XLCell(Worksheet, newKey, c.GetStyleId()); + var newCell = new XLCell(Worksheet, newKey, c.StyleValue); newCell.CopyValuesFrom(c); newCell.FormulaA1 = c.FormulaA1; cellsToInsert.Add(newKey, newCell); @@ -1370,7 +1325,7 @@ var oldCell = Worksheet.Internals.CellsCollection.GetCell(ro, co); if (oldCell != null) { - var newCell = new XLCell(Worksheet, newKey, oldCell.GetStyleId()); + var newCell = new XLCell(Worksheet, newKey, oldCell.StyleValue); newCell.CopyValuesFrom(oldCell); newCell.FormulaA1 = oldCell.FormulaA1; cellsToInsert.Add(newKey, newCell); @@ -1394,7 +1349,7 @@ { int newRow = c.Address.RowNumber + numberOfRows; var newKey = new XLAddress(Worksheet, newRow, c.Address.ColumnNumber, false, false); - var newCell = new XLCell(Worksheet, newKey, c.GetStyleId()); + var newCell = new XLCell(Worksheet, newKey, c.StyleValue); newCell.CopyValuesFrom(c); newCell.FormulaA1 = c.FormulaA1; cellsToInsert.Add(newKey, newCell); @@ -1535,7 +1490,7 @@ var newKey = new XLAddress(Worksheet, c.Address.RowNumber - rowModifier, c.Address.ColumnNumber - columnModifier, false, false); - var newCell = new XLCell(Worksheet, newKey, c.GetStyleId()); + var newCell = new XLCell(Worksheet, newKey, c.StyleValue); newCell.CopyValuesFrom(c); newCell.FormulaA1 = c.FormulaA1; cellsToDelete.Add(c.Address); diff --git a/ClosedXML/Excel/Ranges/XLRangeColumn.cs b/ClosedXML/Excel/Ranges/XLRangeColumn.cs index 08103f0..c027859 100644 --- a/ClosedXML/Excel/Ranges/XLRangeColumn.cs +++ b/ClosedXML/Excel/Ranges/XLRangeColumn.cs @@ -8,13 +8,12 @@ #region Constructor public XLRangeColumn(XLRangeParameters rangeParameters, bool quickLoad) - : base(rangeParameters.RangeAddress) + : base(rangeParameters.RangeAddress, (rangeParameters.DefaultStyle as XLStyle).Value) { if (quickLoad) return; SubscribeToShiftedRows((range, rowsShifted) => this.WorksheetRangeShiftedRows(range, rowsShifted)); SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); - SetStyle(rangeParameters.DefaultStyle); } public XLRangeColumn(XLRangeParameters rangeParameters, bool quickLoad, IXLTable table) diff --git a/ClosedXML/Excel/Ranges/XLRangeColumns.cs b/ClosedXML/Excel/Ranges/XLRangeColumns.cs index 5e5fffb..170cd3f 100644 --- a/ClosedXML/Excel/Ranges/XLRangeColumns.cs +++ b/ClosedXML/Excel/Ranges/XLRangeColumns.cs @@ -6,15 +6,12 @@ { using System.Collections; - internal class XLRangeColumns : IXLRangeColumns, IXLStylized + internal class XLRangeColumns : XLStylizedBase, IXLRangeColumns, IXLStylized { - public Boolean StyleChanged { get; set; } private readonly List _ranges = new List(); - private IXLStyle _style; - public XLRangeColumns() + public XLRangeColumns() : base(XLWorkbook.DefaultStyleValue) { - _style = new XLStyle(this, XLWorkbook.DefaultStyle); } #region IXLRangeColumns Members @@ -49,16 +46,6 @@ return GetEnumerator(); } - public IXLStyle Style - { - get { return _style; } - set - { - _style = new XLStyle(this, value); - _ranges.ForEach(r => r.Style = value); - } - } - public IXLCells Cells() { var cells = new XLCells(false, false); @@ -92,13 +79,12 @@ #endregion IXLRangeColumns Members #region IXLStylized Members - - public IEnumerable Styles + + public override IEnumerable Styles { get { - UpdatingStyle = true; - yield return _style; + yield return Style; foreach (XLRangeColumn rng in _ranges) { yield return rng.Style; @@ -109,19 +95,19 @@ rng.RangeAddress.LastAddress.ColumnNumber)) yield return r.Style; } - UpdatingStyle = false; } } - public Boolean UpdatingStyle { get; set; } - - public IXLStyle InnerStyle + protected override IEnumerable Children { - get { return _style; } - set { _style = new XLStyle(this, value); } + get + { + foreach (var range in _ranges) + yield return range; + } } - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { diff --git a/ClosedXML/Excel/Ranges/XLRangeRow.cs b/ClosedXML/Excel/Ranges/XLRangeRow.cs index 6b1b83e..bd0034c 100644 --- a/ClosedXML/Excel/Ranges/XLRangeRow.cs +++ b/ClosedXML/Excel/Ranges/XLRangeRow.cs @@ -8,7 +8,7 @@ #region Constructor public XLRangeRow(XLRangeParameters rangeParameters, bool quickLoad) - : base(rangeParameters.RangeAddress) + : base(rangeParameters.RangeAddress, (rangeParameters.DefaultStyle as XLStyle).Value) { RangeParameters = rangeParameters; if (quickLoad) return; @@ -17,7 +17,6 @@ SubscribeToShiftedRows((range, rowsShifted) => this.WorksheetRangeShiftedRows(range, rowsShifted)); SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); } - SetStyle(rangeParameters.DefaultStyle); } #endregion Constructor diff --git a/ClosedXML/Excel/Ranges/XLRangeRows.cs b/ClosedXML/Excel/Ranges/XLRangeRows.cs index 6fb9fcc..553e493 100644 --- a/ClosedXML/Excel/Ranges/XLRangeRows.cs +++ b/ClosedXML/Excel/Ranges/XLRangeRows.cs @@ -6,15 +6,12 @@ { using System.Collections; - internal class XLRangeRows : IXLRangeRows, IXLStylized + internal class XLRangeRows : XLStylizedBase, IXLRangeRows, IXLStylized { - public Boolean StyleChanged { get; set; } private readonly List _ranges = new List(); - private IXLStyle _style; - public XLRangeRows() + public XLRangeRows() : base(XLStyle.Default.Value) { - _style = new XLStyle(this, XLWorkbook.DefaultStyle); } #region IXLRangeRows Members @@ -49,16 +46,6 @@ return GetEnumerator(); } - public IXLStyle Style - { - get { return _style; } - set - { - _style = new XLStyle(this, value); - _ranges.ForEach(r => r.Style = value); - } - } - public IXLCells Cells() { var cells = new XLCells(false, false); @@ -93,12 +80,11 @@ #region IXLStylized Members - public IEnumerable Styles + public override IEnumerable Styles { get { - UpdatingStyle = true; - yield return _style; + yield return Style; foreach (XLRangeRow rng in _ranges) { yield return rng.Style; @@ -109,19 +95,20 @@ rng.RangeAddress.LastAddress.ColumnNumber)) yield return r.Style; } - UpdatingStyle = false; } } - public Boolean UpdatingStyle { get; set; } - - public IXLStyle InnerStyle + protected override IEnumerable Children { - get { return _style; } - set { _style = new XLStyle(this, value); } + get + { + foreach (var range in _ranges) + yield return range; + } } - public IXLRanges RangesUsed + + public override IXLRanges RangesUsed { get { diff --git a/ClosedXML/Excel/Ranges/XLRanges.cs b/ClosedXML/Excel/Ranges/XLRanges.cs index 63c5458..b97fc4b 100644 --- a/ClosedXML/Excel/Ranges/XLRanges.cs +++ b/ClosedXML/Excel/Ranges/XLRanges.cs @@ -6,14 +6,12 @@ { using System.Collections; - internal class XLRanges : IXLRanges, IXLStylized + internal class XLRanges : XLStylizedBase, IXLRanges, IXLStylized { private readonly List _ranges = new List(); - private IXLStyle _style; - public XLRanges() + public XLRanges() : base(XLWorkbook.DefaultStyleValue) { - _style = new XLStyle(this, XLWorkbook.DefaultStyle); } #region IXLRanges Members @@ -82,17 +80,6 @@ return GetEnumerator(); } - public IXLStyle Style - { - get { return _style; } - set - { - _style = new XLStyle(this, value); - foreach (XLRange rng in _ranges) - rng.Style = value; - } - } - public Boolean Contains(IXLCell cell) { return _ranges.Any(r => r.RangeAddress.IsValid && r.Contains(cell)); @@ -174,14 +161,11 @@ #region IXLStylized Members - public Boolean StyleChanged { get; set; } - - public IEnumerable Styles + public override IEnumerable Styles { get { - UpdatingStyle = true; - yield return _style; + yield return Style; foreach (XLRange rng in _ranges) { yield return rng.Style; @@ -192,19 +176,19 @@ rng.RangeAddress.LastAddress.ColumnNumber)) yield return r.Style; } - UpdatingStyle = false; } } - public Boolean UpdatingStyle { get; set; } - - public IXLStyle InnerStyle + protected override IEnumerable Children { - get { return _style; } - set { _style = new XLStyle(this, value); } + get + { + foreach (XLRange rng in _ranges) + yield return rng; + } } - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { return this; } } @@ -220,9 +204,14 @@ public override bool Equals(object obj) { - var other = obj as XLRanges; + return Equals(obj as XLRanges); + } + + public bool Equals(XLRanges other) + { if (other == null) return false; + return _ranges.Count == other._ranges.Count && _ranges.Select(thisRange => Enumerable.Contains(other._ranges, thisRange)).All(foundOne => foundOne); } diff --git a/ClosedXML/Excel/Rows/XLRow.cs b/ClosedXML/Excel/Rows/XLRow.cs index 2e660e0..e52827d 100644 --- a/ClosedXML/Excel/Rows/XLRow.cs +++ b/ClosedXML/Excel/Rows/XLRow.cs @@ -21,7 +21,10 @@ public XLRow(Int32 row, XLRowParameters xlRowParameters) : base(new XLRangeAddress(new XLAddress(xlRowParameters.Worksheet, row, 1, false, false), new XLAddress(xlRowParameters.Worksheet, row, XLHelper.MaxColumnNumber, false, - false))) + false)), + xlRowParameters.IsReference ? xlRowParameters.Worksheet.Internals.RowsCollection[row].StyleValue + : (xlRowParameters.DefaultStyle as XLStyle).Value + ) { SetRowNumber(row); @@ -29,16 +32,14 @@ if (IsReference) SubscribeToShiftedRows((range, rowShifted) => this.WorksheetRangeShiftedRows(range, rowShifted)); else - { - SetStyle(xlRowParameters.DefaultStyleId); _height = xlRowParameters.Worksheet.RowHeight; - } } public XLRow(XLRow row) : base(new XLRangeAddress(new XLAddress(row.Worksheet, row.RowNumber(), 1, false, false), new XLAddress(row.Worksheet, row.RowNumber(), XLHelper.MaxColumnNumber, false, - false))) + false)), + row.StyleValue) { _height = row._height; IsReference = row.IsReference; @@ -49,7 +50,6 @@ _isHidden = row._isHidden; _outlineLevel = row._outlineLevel; HeightChanged = row.HeightChanged; - SetStyle(row.GetStyleId()); } #endregion Constructor @@ -60,35 +60,30 @@ { get { - UpdatingStyle = true; - - yield return Style; + if (IsReference) + yield return Worksheet.Internals.RowsCollection[RowNumber()].Style; + else + yield return Style; int row = RowNumber(); foreach (XLCell cell in Worksheet.Internals.CellsCollection.GetCellsInRow(row)) yield return cell.Style; - - UpdatingStyle = false; } } - public override Boolean UpdatingStyle { get; set; } - - public override IXLStyle InnerStyle + protected override IEnumerable Children { get { - return IsReference - ? Worksheet.Internals.RowsCollection[RowNumber()].InnerStyle - : GetStyle(); - } - set - { + int row = RowNumber(); if (IsReference) - Worksheet.Internals.RowsCollection[RowNumber()].InnerStyle = value; + yield return Worksheet.Internals.RowsCollection[row]; else - SetStyle(value); + { + foreach (XLCell cell in Worksheet.Internals.CellsCollection.GetCellsInRow(row)) + yield return cell; + } } } @@ -183,7 +178,7 @@ { var internalRow = Worksheet.Internals.RowsCollection[newRow.RowNumber()]; internalRow._height = Height; - internalRow.SetStyle(Style); + internalRow.InnerStyle = InnerStyle; internalRow._collapsed = Collapsed; internalRow._isHidden = IsHidden; internalRow._outlineLevel = OutlineLevel; @@ -290,7 +285,7 @@ foreach (XLCell c in from XLCell c in Row(startColumn, endColumn).CellsUsed() where !c.IsMerged() select c) { Double thisHeight; - Int32 textRotation = c.Style.Alignment.TextRotation; + Int32 textRotation = c.StyleValue.Alignment.TextRotation; if (c.HasRichText || textRotation != 0 || c.InnerText.Contains(Environment.NewLine)) { var kpList = new List>(); @@ -393,46 +388,6 @@ } } - public override IXLStyle Style - { - get - { - return IsReference ? Worksheet.Internals.RowsCollection[RowNumber()].Style : GetStyle(); - } - set - { - if (IsReference) - Worksheet.Internals.RowsCollection[RowNumber()].Style = value; - else - { - SetStyle(value); - - Int32 minColumn = 1; - Int32 maxColumn = 0; - int row = RowNumber(); - if (Worksheet.Internals.CellsCollection.RowsUsed.ContainsKey(row)) - { - minColumn = Worksheet.Internals.CellsCollection.MinColumnInRow(row); - maxColumn = Worksheet.Internals.CellsCollection.MaxColumnInRow(row); - } - - if (Worksheet.Internals.ColumnsCollection.Count > 0) - { - Int32 minInCollection = Worksheet.Internals.ColumnsCollection.Keys.Min(); - Int32 maxInCollection = Worksheet.Internals.ColumnsCollection.Keys.Max(); - if (minInCollection < minColumn) - minColumn = minInCollection; - if (maxInCollection > maxColumn) - maxColumn = maxInCollection; - } - if (minColumn > 0 && maxColumn > 0) - { - for (Int32 co = minColumn; co <= maxColumn; co++) - Worksheet.Cell(row, co).Style = value; - } - } - } - } public Int32 OutlineLevel { @@ -544,7 +499,7 @@ row.Clear(); var newRow = (XLRow)row; newRow._height = _height; - newRow.Style = GetStyle(); + newRow.InnerStyle = GetStyle(); using (var asRange = AsRange()) asRange.CopyTo(row).Dispose(); @@ -652,11 +607,11 @@ Worksheet.Internals.RowsCollection[RowNumber()].SetStyleNoColumns(value); else { - SetStyle(value); + InnerStyle = value; int row = RowNumber(); foreach (XLCell c in Worksheet.Internals.CellsCollection.GetCellsInRow(row)) - c.Style = value; + c.InnerStyle = value; } } @@ -720,7 +675,7 @@ public override Boolean IsEmpty(Boolean includeFormats) { - if (includeFormats && !Style.Equals(Worksheet.Style)) + if (includeFormats && !StyleValue.Equals(Worksheet.StyleValue)) return false; return base.IsEmpty(includeFormats); diff --git a/ClosedXML/Excel/Rows/XLRowParameters.cs b/ClosedXML/Excel/Rows/XLRowParameters.cs index 975b813..db9394e 100644 --- a/ClosedXML/Excel/Rows/XLRowParameters.cs +++ b/ClosedXML/Excel/Rows/XLRowParameters.cs @@ -5,14 +5,14 @@ { internal class XLRowParameters { - public XLRowParameters(XLWorksheet worksheet, Int32 defaultStyleId, Boolean isReference = true) + public XLRowParameters(XLWorksheet worksheet, IXLStyle defaultStyle, Boolean isReference = true) { Worksheet = worksheet; - DefaultStyleId = defaultStyleId; + DefaultStyle = defaultStyle; IsReference = isReference; } - public Int32 DefaultStyleId { get; set; } + public IXLStyle DefaultStyle { get; private set; } public XLWorksheet Worksheet { get; private set; } public Boolean IsReference { get; private set; } } diff --git a/ClosedXML/Excel/Rows/XLRows.cs b/ClosedXML/Excel/Rows/XLRows.cs index 1853bd5..8494f8f 100644 --- a/ClosedXML/Excel/Rows/XLRows.cs +++ b/ClosedXML/Excel/Rows/XLRows.cs @@ -6,17 +6,14 @@ { using System.Collections; - internal class XLRows : IXLRows, IXLStylized + internal class XLRows : XLStylizedBase, IXLRows, IXLStylized { - public Boolean StyleChanged { get; set; } private readonly List _rows = new List(); private readonly XLWorksheet _worksheet; - internal IXLStyle style; - public XLRows(XLWorksheet worksheet) + public XLRows(XLWorksheet worksheet) : base(XLWorkbook.DefaultStyleValue) { _worksheet = worksheet; - style = new XLStyle(this, XLWorkbook.DefaultStyle); } #region IXLRows Members @@ -31,23 +28,6 @@ return GetEnumerator(); } - public IXLStyle Style - { - get { return style; } - set - { - style = new XLStyle(this, value); - - if (_worksheet != null) - _worksheet.Style = value; - else - { - foreach (XLRow row in _rows) - row.Style = value; - } - } - } - public double Height { set @@ -211,13 +191,25 @@ #endregion IXLRows Members #region IXLStylized Members - - public IEnumerable Styles + protected override IEnumerable Children { get { - UpdatingStyle = true; - yield return style; + if (_worksheet != null) + yield return _worksheet; + else + { + foreach (XLRow row in _rows) + yield return row; + } + } + } + + public override IEnumerable Styles + { + get + { + yield return Style; if (_worksheet != null) yield return _worksheet.Style; else @@ -227,19 +219,10 @@ yield return s; } } - UpdatingStyle = false; } } - - public Boolean UpdatingStyle { get; set; } - - public IXLStyle InnerStyle - { - get { return style; } - set { style = new XLStyle(this, value); } - } - - public IXLRanges RangesUsed + + public override IXLRanges RangesUsed { get { diff --git a/ClosedXML/Excel/Style/Colors/XLColor_Internal.cs b/ClosedXML/Excel/Style/Colors/XLColor_Internal.cs index dcea153..3919bf8 100644 --- a/ClosedXML/Excel/Style/Colors/XLColor_Internal.cs +++ b/ClosedXML/Excel/Style/Colors/XLColor_Internal.cs @@ -5,64 +5,54 @@ { public partial class XLColor { - private XLColor(XLColor defaultColor) - { - var dColor = defaultColor; - if (dColor._colorType == XLColorType.Color) - _color = dColor._color; - else if (dColor._colorType == XLColorType.Theme) - { - _themeColor = dColor._themeColor; - _themeTint = dColor._themeTint; - } - else - { - _indexed = dColor._indexed; - } + internal XLColorKey Key { get; private set; } - HasValue = true; - _hashCode = dColor._hashCode; - _colorType = dColor._colorType; + private XLColor(XLColor defaultColor) : this(defaultColor.Key) + { } - private XLColor() + private XLColor() : this(new XLColorKey()) { HasValue = false; - _hashCode = 0; } - private XLColor(Color color) + private XLColor(Color color) : this(new XLColorKey { - _color = color; - _hashCode = 13 ^ color.ToArgb(); - HasValue = true; - _colorType = XLColorType.Color; + Color = color, + ColorType = XLColorType.Color + }) + { } - private XLColor(Int32 index) + private XLColor(Int32 index) : this(new XLColorKey { - _indexed = index; - _hashCode = 11 ^ _indexed; - HasValue = true; - _colorType = XLColorType.Indexed; + Indexed = index, + ColorType = XLColorType.Indexed + }) + { } - private XLColor(XLThemeColor themeColor) + private XLColor(XLThemeColor themeColor) : this(new XLColorKey { - _themeColor = themeColor; - _themeTint = 0; - _hashCode = 7 ^ _themeColor.GetHashCode() ^ _themeTint.GetHashCode(); - HasValue = true; - _colorType = XLColorType.Theme; + ThemeColor = themeColor, + ColorType = XLColorType.Theme + }) + { } - private XLColor(XLThemeColor themeColor, Double themeTint) + private XLColor(XLThemeColor themeColor, Double themeTint) : this(new XLColorKey { - _themeColor = themeColor; - _themeTint = themeTint; - _hashCode = 7 ^ _themeColor.GetHashCode() ^ _themeTint.GetHashCode(); + ThemeColor = themeColor, + ThemeTint = themeTint, + ColorType = XLColorType.Theme + }) + { + } + + internal XLColor(XLColorKey key) + { + Key = key; HasValue = true; - _colorType = XLColorType.Theme; } } } diff --git a/ClosedXML/Excel/Style/Colors/XLColor_Public.cs b/ClosedXML/Excel/Style/Colors/XLColor_Public.cs index ce6031a..a75edcf 100644 --- a/ClosedXML/Excel/Style/Colors/XLColor_Public.cs +++ b/ClosedXML/Excel/Style/Colors/XLColor_Public.cs @@ -36,34 +36,27 @@ /// private const Int32 TOOLTIPCOLORINDEX = 81; - private readonly XLColorType _colorType; - private int _hashCode; - private readonly Int32 _indexed; - private readonly XLThemeColor _themeColor; - private readonly Double _themeTint; - - private Color _color; public Boolean HasValue { get; private set; } public XLColorType ColorType { - get { return _colorType; } + get { return Key.ColorType; } } public Color Color { get { - if (_colorType == XLColorType.Theme) + if (ColorType == XLColorType.Theme) throw new InvalidOperationException("Cannot convert theme color to Color."); - if (_colorType == XLColorType.Indexed) - if (_indexed == TOOLTIPCOLORINDEX) + if (ColorType == XLColorType.Indexed) + if (Indexed == TOOLTIPCOLORINDEX) return Color.FromArgb(255, Color.Black); else - return IndexedColors[_indexed].Color; + return IndexedColors[Indexed].Color; - return _color; + return Key.Color; } } @@ -75,7 +68,7 @@ throw new InvalidOperationException("Cannot convert theme color to indexed color."); if (ColorType == XLColorType.Indexed) - return _indexed; + return Key.Indexed; throw new InvalidOperationException("Cannot convert Color to indexed color."); } @@ -86,7 +79,7 @@ get { if (ColorType == XLColorType.Theme) - return _themeColor; + return Key.ThemeColor; if (ColorType == XLColorType.Indexed) throw new InvalidOperationException("Cannot convert indexed color to theme color."); @@ -100,12 +93,12 @@ get { if (ColorType == XLColorType.Theme) - return _themeTint; + return Key.ThemeTint; if (ColorType == XLColorType.Indexed) throw new InvalidOperationException("Cannot extract theme tint from an indexed color."); - return _color.A / 255.0; + return Color.A / 255.0; } } @@ -113,23 +106,7 @@ public bool Equals(XLColor other) { - if (_colorType == other._colorType) - { - if (_colorType == XLColorType.Color) - { - // .NET Color.Equals() will return false for Color.FromArgb(255, 255, 255, 255) == Color.White - // Therefore we compare the ToArgb() values - return _color.ToArgb() == other._color.ToArgb(); - } - if (_colorType == XLColorType.Theme) - { - return _themeColor == other._themeColor - && Math.Abs(_themeTint - other._themeTint) < XLHelper.Epsilon; - } - return _indexed == other._indexed; - } - - return false; + return Key == other.Key; } #endregion IEquatable Members @@ -141,28 +118,21 @@ public override int GetHashCode() { - if (_hashCode == 0) - { - if (_colorType == XLColorType.Color) - _hashCode = _color.GetHashCode(); - else if (_colorType == XLColorType.Theme) - _hashCode = _themeColor.GetHashCode() ^ _themeTint.GetHashCode(); - else - _hashCode = _indexed; - } - - return _hashCode; + var hashCode = 229333804; + hashCode = hashCode * -1521134295 + HasValue.GetHashCode(); + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; } public override string ToString() { - if (_colorType == XLColorType.Color) + if (ColorType == XLColorType.Color) return Color.ToHex(); - if (_colorType == XLColorType.Theme) - return String.Format("Color Theme: {0}, Tint: {1}", _themeColor.ToString(), _themeTint.ToString()); + if (ColorType == XLColorType.Theme) + return String.Format("Color Theme: {0}, Tint: {1}", ThemeColor.ToString(), ThemeTint.ToString()); - return "Color Index: " + _indexed; + return "Color Index: " + Indexed; } public static Boolean operator ==(XLColor left, XLColor right) diff --git a/ClosedXML/Excel/Style/Colors/XLColor_Static.cs b/ClosedXML/Excel/Style/Colors/XLColor_Static.cs index efd6b7c..c4628bc 100644 --- a/ClosedXML/Excel/Style/Colors/XLColor_Static.cs +++ b/ClosedXML/Excel/Style/Colors/XLColor_Static.cs @@ -1,3 +1,4 @@ +using ClosedXML.Excel.Caching; using ClosedXML.Utils; using System; using System.Collections.Generic; @@ -7,21 +8,23 @@ { public partial class XLColor { + private static readonly XLColorRepository Repository = new XLColorRepository(key => new XLColor(key)); + private static readonly Dictionary ByColor = new Dictionary(); private static readonly Object ByColorLock = new Object(); + internal static XLColor FromKey(XLColorKey key) + { + return Repository.GetOrCreate(key); + } + public static XLColor FromColor(Color color) { - XLColor ret; - lock (ByColorLock) + return FromKey(new XLColorKey { - if (!ByColor.TryGetValue(color, out ret)) - { - ret = new XLColor(color); - ByColor.Add(color, ret); - } - } - return ret; + ColorType = XLColorType.Color, + Color = color + }); } public static XLColor FromArgb(Int32 argb) @@ -56,67 +59,32 @@ return FromColor(ColorStringParser.ParseFromHtml(htmlColor)); } - private static readonly Dictionary ByIndex = new Dictionary(); - private static readonly Object ByIndexLock = new Object(); - public static XLColor FromIndex(Int32 index) { - XLColor ret; - lock (ByIndexLock) + return FromKey(new XLColorKey { - if (!ByIndex.TryGetValue(index, out ret)) - { - ret = new XLColor(index); - ByIndex.Add(index, ret); - } - } - return ret; + ColorType = XLColorType.Indexed, + Indexed = index + }); } - private static readonly Dictionary ByTheme = new Dictionary(); - private static readonly Object ByThemeLock = new Object(); - public static XLColor FromTheme(XLThemeColor themeColor) { - XLColor ret; - lock (ByThemeLock) + return FromKey(new XLColorKey { - if (!ByTheme.TryGetValue(themeColor, out ret)) - { - ret = new XLColor(themeColor); - ByTheme.Add(themeColor, ret); - } - } - return ret; + ColorType = XLColorType.Theme, + ThemeColor = themeColor + }); } - private static readonly Dictionary> ByThemeTint = new Dictionary>(); - private static readonly Object ByThemeTintLock = new Object(); - public static XLColor FromTheme(XLThemeColor themeColor, Double themeTint) { - XLColor ret; - lock (ByThemeTintLock) + return FromKey(new XLColorKey { - Dictionary themeTints; - if (ByThemeTint.TryGetValue(themeColor, out themeTints)) - { - if (!themeTints.TryGetValue(themeTint, out ret)) - { - ret = new XLColor(themeColor, themeTint); - themeTints.Add(themeTint, ret); - } - } - else - { - themeTints = new Dictionary(); - ret = new XLColor(themeColor, themeTint); - themeTints.Add(themeTint, ret); - - ByThemeTint.Add(themeColor, themeTints); - } - } - return ret; + ColorType = XLColorType.Theme, + ThemeColor = themeColor, + ThemeTint = themeTint + }); } private static Dictionary _indexedColors; @@ -202,741 +170,1475 @@ } private static XLColor noColor = new XLColor(); + public static XLColor NoColor { get { return noColor; } } public static XLColor AliceBlue { get { return FromColor(Color.AliceBlue); } } + public static XLColor AntiqueWhite { get { return FromColor(Color.AntiqueWhite); } } + public static XLColor Aqua { get { return FromColor(Color.Aqua); } } + public static XLColor Aquamarine { get { return FromColor(Color.Aquamarine); } } + public static XLColor Azure { get { return FromColor(Color.Azure); } } + public static XLColor Beige { get { return FromColor(Color.Beige); } } + public static XLColor Bisque { get { return FromColor(Color.Bisque); } } + public static XLColor Black { get { return FromColor(Color.Black); } } + public static XLColor BlanchedAlmond { get { return FromColor(Color.BlanchedAlmond); } } + public static XLColor Blue { get { return FromColor(Color.Blue); } } + public static XLColor BlueViolet { get { return FromColor(Color.BlueViolet); } } + public static XLColor Brown { get { return FromColor(Color.Brown); } } + public static XLColor BurlyWood { get { return FromColor(Color.BurlyWood); } } + public static XLColor CadetBlue { get { return FromColor(Color.CadetBlue); } } + public static XLColor Chartreuse { get { return FromColor(Color.Chartreuse); } } + public static XLColor Chocolate { get { return FromColor(Color.Chocolate); } } + public static XLColor Coral { get { return FromColor(Color.Coral); } } + public static XLColor CornflowerBlue { get { return FromColor(Color.CornflowerBlue); } } + public static XLColor Cornsilk { get { return FromColor(Color.Cornsilk); } } + public static XLColor Crimson { get { return FromColor(Color.Crimson); } } + public static XLColor Cyan { get { return FromColor(Color.Cyan); } } + public static XLColor DarkBlue { get { return FromColor(Color.DarkBlue); } } + public static XLColor DarkCyan { get { return FromColor(Color.DarkCyan); } } + public static XLColor DarkGoldenrod { get { return FromColor(Color.DarkGoldenrod); } } + public static XLColor DarkGray { get { return FromColor(Color.DarkGray); } } + public static XLColor DarkGreen { get { return FromColor(Color.DarkGreen); } } + public static XLColor DarkKhaki { get { return FromColor(Color.DarkKhaki); } } + public static XLColor DarkMagenta { get { return FromColor(Color.DarkMagenta); } } + public static XLColor DarkOliveGreen { get { return FromColor(Color.DarkOliveGreen); } } + public static XLColor DarkOrange { get { return FromColor(Color.DarkOrange); } } + public static XLColor DarkOrchid { get { return FromColor(Color.DarkOrchid); } } + public static XLColor DarkRed { get { return FromColor(Color.DarkRed); } } + public static XLColor DarkSalmon { get { return FromColor(Color.DarkSalmon); } } + public static XLColor DarkSeaGreen { get { return FromColor(Color.DarkSeaGreen); } } + public static XLColor DarkSlateBlue { get { return FromColor(Color.DarkSlateBlue); } } + public static XLColor DarkSlateGray { get { return FromColor(Color.DarkSlateGray); } } + public static XLColor DarkTurquoise { get { return FromColor(Color.DarkTurquoise); } } + public static XLColor DarkViolet { get { return FromColor(Color.DarkViolet); } } + public static XLColor DeepPink { get { return FromColor(Color.DeepPink); } } + public static XLColor DeepSkyBlue { get { return FromColor(Color.DeepSkyBlue); } } + public static XLColor DimGray { get { return FromColor(Color.DimGray); } } + public static XLColor DodgerBlue { get { return FromColor(Color.DodgerBlue); } } + public static XLColor Firebrick { get { return FromColor(Color.Firebrick); } } + public static XLColor FloralWhite { get { return FromColor(Color.FloralWhite); } } + public static XLColor ForestGreen { get { return FromColor(Color.ForestGreen); } } + public static XLColor Fuchsia { get { return FromColor(Color.Fuchsia); } } + public static XLColor Gainsboro { get { return FromColor(Color.Gainsboro); } } + public static XLColor GhostWhite { get { return FromColor(Color.GhostWhite); } } + public static XLColor Gold { get { return FromColor(Color.Gold); } } + public static XLColor Goldenrod { get { return FromColor(Color.Goldenrod); } } + public static XLColor Gray { get { return FromColor(Color.Gray); } } + public static XLColor Green { get { return FromColor(Color.Green); } } + public static XLColor GreenYellow { get { return FromColor(Color.GreenYellow); } } + public static XLColor Honeydew { get { return FromColor(Color.Honeydew); } } + public static XLColor HotPink { get { return FromColor(Color.HotPink); } } + public static XLColor IndianRed { get { return FromColor(Color.IndianRed); } } + public static XLColor Indigo { get { return FromColor(Color.Indigo); } } + public static XLColor Ivory { get { return FromColor(Color.Ivory); } } + public static XLColor Khaki { get { return FromColor(Color.Khaki); } } + public static XLColor Lavender { get { return FromColor(Color.Lavender); } } + public static XLColor LavenderBlush { get { return FromColor(Color.LavenderBlush); } } + public static XLColor LawnGreen { get { return FromColor(Color.LawnGreen); } } + public static XLColor LemonChiffon { get { return FromColor(Color.LemonChiffon); } } + public static XLColor LightBlue { get { return FromColor(Color.LightBlue); } } + public static XLColor LightCoral { get { return FromColor(Color.LightCoral); } } + public static XLColor LightCyan { get { return FromColor(Color.LightCyan); } } + public static XLColor LightGoldenrodYellow { get { return FromColor(Color.LightGoldenrodYellow); } } + public static XLColor LightGray { get { return FromColor(Color.LightGray); } } + public static XLColor LightGreen { get { return FromColor(Color.LightGreen); } } + public static XLColor LightPink { get { return FromColor(Color.LightPink); } } + public static XLColor LightSalmon { get { return FromColor(Color.LightSalmon); } } + public static XLColor LightSeaGreen { get { return FromColor(Color.LightSeaGreen); } } + public static XLColor LightSkyBlue { get { return FromColor(Color.LightSkyBlue); } } + public static XLColor LightSlateGray { get { return FromColor(Color.LightSlateGray); } } + public static XLColor LightSteelBlue { get { return FromColor(Color.LightSteelBlue); } } + public static XLColor LightYellow { get { return FromColor(Color.LightYellow); } } + public static XLColor Lime { get { return FromColor(Color.Lime); } } + public static XLColor LimeGreen { get { return FromColor(Color.LimeGreen); } } + public static XLColor Linen { get { return FromColor(Color.Linen); } } + public static XLColor Magenta { get { return FromColor(Color.Magenta); } } + public static XLColor Maroon { get { return FromColor(Color.Maroon); } } + public static XLColor MediumAquamarine { get { return FromColor(Color.MediumAquamarine); } } + public static XLColor MediumBlue { get { return FromColor(Color.MediumBlue); } } + public static XLColor MediumOrchid { get { return FromColor(Color.MediumOrchid); } } + public static XLColor MediumPurple { get { return FromColor(Color.MediumPurple); } } + public static XLColor MediumSeaGreen { get { return FromColor(Color.MediumSeaGreen); } } + public static XLColor MediumSlateBlue { get { return FromColor(Color.MediumSlateBlue); } } + public static XLColor MediumSpringGreen { get { return FromColor(Color.MediumSpringGreen); } } + public static XLColor MediumTurquoise { get { return FromColor(Color.MediumTurquoise); } } + public static XLColor MediumVioletRed { get { return FromColor(Color.MediumVioletRed); } } + public static XLColor MidnightBlue { get { return FromColor(Color.MidnightBlue); } } + public static XLColor MintCream { get { return FromColor(Color.MintCream); } } + public static XLColor MistyRose { get { return FromColor(Color.MistyRose); } } + public static XLColor Moccasin { get { return FromColor(Color.Moccasin); } } + public static XLColor NavajoWhite { get { return FromColor(Color.NavajoWhite); } } + public static XLColor Navy { get { return FromColor(Color.Navy); } } + public static XLColor OldLace { get { return FromColor(Color.OldLace); } } + public static XLColor Olive { get { return FromColor(Color.Olive); } } + public static XLColor OliveDrab { get { return FromColor(Color.OliveDrab); } } + public static XLColor Orange { get { return FromColor(Color.Orange); } } + public static XLColor OrangeRed { get { return FromColor(Color.OrangeRed); } } + public static XLColor Orchid { get { return FromColor(Color.Orchid); } } + public static XLColor PaleGoldenrod { get { return FromColor(Color.PaleGoldenrod); } } + public static XLColor PaleGreen { get { return FromColor(Color.PaleGreen); } } + public static XLColor PaleTurquoise { get { return FromColor(Color.PaleTurquoise); } } + public static XLColor PaleVioletRed { get { return FromColor(Color.PaleVioletRed); } } + public static XLColor PapayaWhip { get { return FromColor(Color.PapayaWhip); } } + public static XLColor PeachPuff { get { return FromColor(Color.PeachPuff); } } + public static XLColor Peru { get { return FromColor(Color.Peru); } } + public static XLColor Pink { get { return FromColor(Color.Pink); } } + public static XLColor Plum { get { return FromColor(Color.Plum); } } + public static XLColor PowderBlue { get { return FromColor(Color.PowderBlue); } } + public static XLColor Purple { get { return FromColor(Color.Purple); } } + public static XLColor Red { get { return FromColor(Color.Red); } } + public static XLColor RosyBrown { get { return FromColor(Color.RosyBrown); } } + public static XLColor RoyalBlue { get { return FromColor(Color.RoyalBlue); } } + public static XLColor SaddleBrown { get { return FromColor(Color.SaddleBrown); } } + public static XLColor Salmon { get { return FromColor(Color.Salmon); } } + public static XLColor SandyBrown { get { return FromColor(Color.SandyBrown); } } + public static XLColor SeaGreen { get { return FromColor(Color.SeaGreen); } } + public static XLColor SeaShell { get { return FromColor(Color.SeaShell); } } + public static XLColor Sienna { get { return FromColor(Color.Sienna); } } + public static XLColor Silver { get { return FromColor(Color.Silver); } } + public static XLColor SkyBlue { get { return FromColor(Color.SkyBlue); } } + public static XLColor SlateBlue { get { return FromColor(Color.SlateBlue); } } + public static XLColor SlateGray { get { return FromColor(Color.SlateGray); } } + public static XLColor Snow { get { return FromColor(Color.Snow); } } + public static XLColor SpringGreen { get { return FromColor(Color.SpringGreen); } } + public static XLColor SteelBlue { get { return FromColor(Color.SteelBlue); } } + public static XLColor Tan { get { return FromColor(Color.Tan); } } + public static XLColor Teal { get { return FromColor(Color.Teal); } } + public static XLColor Thistle { get { return FromColor(Color.Thistle); } } + public static XLColor Tomato { get { return FromColor(Color.Tomato); } } + public static XLColor Turquoise { get { return FromColor(Color.Turquoise); } } + public static XLColor Violet { get { return FromColor(Color.Violet); } } + public static XLColor Wheat { get { return FromColor(Color.Wheat); } } + public static XLColor White { get { return FromColor(Color.White); } } + public static XLColor WhiteSmoke { get { return FromColor(Color.WhiteSmoke); } } + public static XLColor Yellow { get { return FromColor(Color.Yellow); } } + public static XLColor YellowGreen { get { return FromColor(Color.YellowGreen); } } + public static XLColor AirForceBlue { get { return FromHtml("#FF5D8AA8"); } } + public static XLColor Alizarin { get { return FromHtml("#FFE32636"); } } + public static XLColor Almond { get { return FromHtml("#FFEFDECD"); } } + public static XLColor Amaranth { get { return FromHtml("#FFE52B50"); } } + public static XLColor Amber { get { return FromHtml("#FFFFBF00"); } } + public static XLColor AmberSaeEce { get { return FromHtml("#FFFF7E00"); } } + public static XLColor AmericanRose { get { return FromHtml("#FFFF033E"); } } + public static XLColor Amethyst { get { return FromHtml("#FF9966CC"); } } + public static XLColor AntiFlashWhite { get { return FromHtml("#FFF2F3F4"); } } + public static XLColor AntiqueBrass { get { return FromHtml("#FFCD9575"); } } + public static XLColor AntiqueFuchsia { get { return FromHtml("#FF915C83"); } } + public static XLColor AppleGreen { get { return FromHtml("#FF8DB600"); } } + public static XLColor Apricot { get { return FromHtml("#FFFBCEB1"); } } + public static XLColor Aquamarine1 { get { return FromHtml("#FF7FFFD0"); } } + public static XLColor ArmyGreen { get { return FromHtml("#FF4B5320"); } } + public static XLColor Arsenic { get { return FromHtml("#FF3B444B"); } } + public static XLColor ArylideYellow { get { return FromHtml("#FFE9D66B"); } } + public static XLColor AshGrey { get { return FromHtml("#FFB2BEB5"); } } + public static XLColor Asparagus { get { return FromHtml("#FF87A96B"); } } + public static XLColor AtomicTangerine { get { return FromHtml("#FFFF9966"); } } + public static XLColor Auburn { get { return FromHtml("#FF6D351A"); } } + public static XLColor Aureolin { get { return FromHtml("#FFFDEE00"); } } + public static XLColor Aurometalsaurus { get { return FromHtml("#FF6E7F80"); } } + public static XLColor Awesome { get { return FromHtml("#FFFF2052"); } } + public static XLColor AzureColorWheel { get { return FromHtml("#FF007FFF"); } } + public static XLColor BabyBlue { get { return FromHtml("#FF89CFF0"); } } + public static XLColor BabyBlueEyes { get { return FromHtml("#FFA1CAF1"); } } + public static XLColor BabyPink { get { return FromHtml("#FFF4C2C2"); } } + public static XLColor BallBlue { get { return FromHtml("#FF21ABCD"); } } + public static XLColor BananaMania { get { return FromHtml("#FFFAE7B5"); } } + public static XLColor BattleshipGrey { get { return FromHtml("#FF848482"); } } + public static XLColor Bazaar { get { return FromHtml("#FF98777B"); } } + public static XLColor BeauBlue { get { return FromHtml("#FFBCD4E6"); } } + public static XLColor Beaver { get { return FromHtml("#FF9F8170"); } } + public static XLColor Bistre { get { return FromHtml("#FF3D2B1F"); } } + public static XLColor Bittersweet { get { return FromHtml("#FFFE6F5E"); } } + public static XLColor BleuDeFrance { get { return FromHtml("#FF318CE7"); } } + public static XLColor BlizzardBlue { get { return FromHtml("#FFACE5EE"); } } + public static XLColor Blond { get { return FromHtml("#FFFAF0BE"); } } + public static XLColor BlueBell { get { return FromHtml("#FFA2A2D0"); } } + public static XLColor BlueGray { get { return FromHtml("#FF6699CC"); } } + public static XLColor BlueGreen { get { return FromHtml("#FF00DDDD"); } } + public static XLColor BluePigment { get { return FromHtml("#FF333399"); } } + public static XLColor BlueRyb { get { return FromHtml("#FF0247FE"); } } + public static XLColor Blush { get { return FromHtml("#FFDE5D83"); } } + public static XLColor Bole { get { return FromHtml("#FF79443B"); } } + public static XLColor BondiBlue { get { return FromHtml("#FF0095B6"); } } + public static XLColor BostonUniversityRed { get { return FromHtml("#FFCC0000"); } } + public static XLColor BrandeisBlue { get { return FromHtml("#FF0070FF"); } } + public static XLColor Brass { get { return FromHtml("#FFB5A642"); } } + public static XLColor BrickRed { get { return FromHtml("#FFCB4154"); } } + public static XLColor BrightCerulean { get { return FromHtml("#FF1DACD6"); } } + public static XLColor BrightGreen { get { return FromHtml("#FF66FF00"); } } + public static XLColor BrightLavender { get { return FromHtml("#FFBF94E4"); } } + public static XLColor BrightMaroon { get { return FromHtml("#FFC32148"); } } + public static XLColor BrightPink { get { return FromHtml("#FFFF007F"); } } + public static XLColor BrightTurquoise { get { return FromHtml("#FF08E8DE"); } } + public static XLColor BrightUbe { get { return FromHtml("#FFD19FE8"); } } + public static XLColor BrilliantLavender { get { return FromHtml("#FFF4BBFF"); } } + public static XLColor BrilliantRose { get { return FromHtml("#FFFF55A3"); } } + public static XLColor BrinkPink { get { return FromHtml("#FFFB607F"); } } + public static XLColor BritishRacingGreen { get { return FromHtml("#FF004225"); } } + public static XLColor Bronze { get { return FromHtml("#FFCD7F32"); } } + public static XLColor BrownTraditional { get { return FromHtml("#FF964B00"); } } + public static XLColor BubbleGum { get { return FromHtml("#FFFFC1CC"); } } + public static XLColor Bubbles { get { return FromHtml("#FFE7FEFF"); } } + public static XLColor Buff { get { return FromHtml("#FFF0DC82"); } } + public static XLColor BulgarianRose { get { return FromHtml("#FF480607"); } } + public static XLColor Burgundy { get { return FromHtml("#FF800020"); } } + public static XLColor BurntOrange { get { return FromHtml("#FFCC5500"); } } + public static XLColor BurntSienna { get { return FromHtml("#FFE97451"); } } + public static XLColor BurntUmber { get { return FromHtml("#FF8A3324"); } } + public static XLColor Byzantine { get { return FromHtml("#FFBD33A4"); } } + public static XLColor Byzantium { get { return FromHtml("#FF702963"); } } + public static XLColor Cadet { get { return FromHtml("#FF536872"); } } + public static XLColor CadetGrey { get { return FromHtml("#FF91A3B0"); } } + public static XLColor CadmiumGreen { get { return FromHtml("#FF006B3C"); } } + public static XLColor CadmiumOrange { get { return FromHtml("#FFED872D"); } } + public static XLColor CadmiumRed { get { return FromHtml("#FFE30022"); } } + public static XLColor CadmiumYellow { get { return FromHtml("#FFFFF600"); } } + public static XLColor CalPolyPomonaGreen { get { return FromHtml("#FF1E4D2B"); } } + public static XLColor CambridgeBlue { get { return FromHtml("#FFA3C1AD"); } } + public static XLColor Camel { get { return FromHtml("#FFC19A6B"); } } + public static XLColor CamouflageGreen { get { return FromHtml("#FF78866B"); } } + public static XLColor CanaryYellow { get { return FromHtml("#FFFFEF00"); } } + public static XLColor CandyAppleRed { get { return FromHtml("#FFFF0800"); } } + public static XLColor CandyPink { get { return FromHtml("#FFE4717A"); } } + public static XLColor CaputMortuum { get { return FromHtml("#FF592720"); } } + public static XLColor Cardinal { get { return FromHtml("#FFC41E3A"); } } + public static XLColor CaribbeanGreen { get { return FromHtml("#FF00CC99"); } } + public static XLColor Carmine { get { return FromHtml("#FF960018"); } } + public static XLColor CarminePink { get { return FromHtml("#FFEB4C42"); } } + public static XLColor CarmineRed { get { return FromHtml("#FFFF0038"); } } + public static XLColor CarnationPink { get { return FromHtml("#FFFFA6C9"); } } + public static XLColor Carnelian { get { return FromHtml("#FFB31B1B"); } } + public static XLColor CarolinaBlue { get { return FromHtml("#FF99BADD"); } } + public static XLColor CarrotOrange { get { return FromHtml("#FFED9121"); } } + public static XLColor Ceil { get { return FromHtml("#FF92A1CF"); } } + public static XLColor Celadon { get { return FromHtml("#FFACE1AF"); } } + public static XLColor CelestialBlue { get { return FromHtml("#FF4997D0"); } } + public static XLColor Cerise { get { return FromHtml("#FFDE3163"); } } + public static XLColor CerisePink { get { return FromHtml("#FFEC3B83"); } } + public static XLColor Cerulean { get { return FromHtml("#FF007BA7"); } } + public static XLColor CeruleanBlue { get { return FromHtml("#FF2A52BE"); } } + public static XLColor Chamoisee { get { return FromHtml("#FFA0785A"); } } + public static XLColor Champagne { get { return FromHtml("#FFF7E7CE"); } } + public static XLColor Charcoal { get { return FromHtml("#FF36454F"); } } + public static XLColor ChartreuseTraditional { get { return FromHtml("#FFDFFF00"); } } + public static XLColor CherryBlossomPink { get { return FromHtml("#FFFFB7C5"); } } + public static XLColor Chocolate1 { get { return FromHtml("#FF7B3F00"); } } + public static XLColor ChromeYellow { get { return FromHtml("#FFFFA700"); } } + public static XLColor Cinereous { get { return FromHtml("#FF98817B"); } } + public static XLColor Cinnabar { get { return FromHtml("#FFE34234"); } } + public static XLColor Citrine { get { return FromHtml("#FFE4D00A"); } } + public static XLColor ClassicRose { get { return FromHtml("#FFFBCCE7"); } } + public static XLColor Cobalt { get { return FromHtml("#FF0047AB"); } } + public static XLColor ColumbiaBlue { get { return FromHtml("#FF9BDDFF"); } } + public static XLColor CoolBlack { get { return FromHtml("#FF002E63"); } } + public static XLColor CoolGrey { get { return FromHtml("#FF8C92AC"); } } + public static XLColor Copper { get { return FromHtml("#FFB87333"); } } + public static XLColor CopperRose { get { return FromHtml("#FF996666"); } } + public static XLColor Coquelicot { get { return FromHtml("#FFFF3800"); } } + public static XLColor CoralPink { get { return FromHtml("#FFF88379"); } } + public static XLColor CoralRed { get { return FromHtml("#FFFF4040"); } } + public static XLColor Cordovan { get { return FromHtml("#FF893F45"); } } + public static XLColor Corn { get { return FromHtml("#FFFBEC5D"); } } + public static XLColor CornellRed { get { return FromHtml("#FFB31B1B"); } } + public static XLColor CosmicLatte { get { return FromHtml("#FFFFF8E7"); } } + public static XLColor CottonCandy { get { return FromHtml("#FFFFBCD9"); } } + public static XLColor Cream { get { return FromHtml("#FFFFFDD0"); } } + public static XLColor CrimsonGlory { get { return FromHtml("#FFBE0032"); } } + public static XLColor CyanProcess { get { return FromHtml("#FF00B7EB"); } } + public static XLColor Daffodil { get { return FromHtml("#FFFFFF31"); } } + public static XLColor Dandelion { get { return FromHtml("#FFF0E130"); } } + public static XLColor DarkBrown { get { return FromHtml("#FF654321"); } } + public static XLColor DarkByzantium { get { return FromHtml("#FF5D3954"); } } + public static XLColor DarkCandyAppleRed { get { return FromHtml("#FFA40000"); } } + public static XLColor DarkCerulean { get { return FromHtml("#FF08457E"); } } + public static XLColor DarkChampagne { get { return FromHtml("#FFC2B280"); } } + public static XLColor DarkChestnut { get { return FromHtml("#FF986960"); } } + public static XLColor DarkCoral { get { return FromHtml("#FFCD5B45"); } } + public static XLColor DarkElectricBlue { get { return FromHtml("#FF536878"); } } + public static XLColor DarkGreen1 { get { return FromHtml("#FF013220"); } } + public static XLColor DarkJungleGreen { get { return FromHtml("#FF1A2421"); } } + public static XLColor DarkLava { get { return FromHtml("#FF483C32"); } } + public static XLColor DarkLavender { get { return FromHtml("#FF734F96"); } } + public static XLColor DarkMidnightBlue { get { return FromHtml("#FF003366"); } } + public static XLColor DarkPastelBlue { get { return FromHtml("#FF779ECB"); } } + public static XLColor DarkPastelGreen { get { return FromHtml("#FF03C03C"); } } + public static XLColor DarkPastelPurple { get { return FromHtml("#FF966FD6"); } } + public static XLColor DarkPastelRed { get { return FromHtml("#FFC23B22"); } } + public static XLColor DarkPink { get { return FromHtml("#FFE75480"); } } + public static XLColor DarkPowderBlue { get { return FromHtml("#FF003399"); } } + public static XLColor DarkRaspberry { get { return FromHtml("#FF872657"); } } + public static XLColor DarkScarlet { get { return FromHtml("#FF560319"); } } + public static XLColor DarkSienna { get { return FromHtml("#FF3C1414"); } } + public static XLColor DarkSpringGreen { get { return FromHtml("#FF177245"); } } + public static XLColor DarkTan { get { return FromHtml("#FF918151"); } } + public static XLColor DarkTangerine { get { return FromHtml("#FFFFA812"); } } + public static XLColor DarkTaupe { get { return FromHtml("#FF483C32"); } } + public static XLColor DarkTerraCotta { get { return FromHtml("#FFCC4E5C"); } } + public static XLColor DartmouthGreen { get { return FromHtml("#FF00693E"); } } + public static XLColor DavysGrey { get { return FromHtml("#FF555555"); } } + public static XLColor DebianRed { get { return FromHtml("#FFD70A53"); } } + public static XLColor DeepCarmine { get { return FromHtml("#FFA9203E"); } } + public static XLColor DeepCarminePink { get { return FromHtml("#FFEF3038"); } } + public static XLColor DeepCarrotOrange { get { return FromHtml("#FFE9692C"); } } + public static XLColor DeepCerise { get { return FromHtml("#FFDA3287"); } } + public static XLColor DeepChampagne { get { return FromHtml("#FFFAD6A5"); } } + public static XLColor DeepChestnut { get { return FromHtml("#FFB94E48"); } } + public static XLColor DeepFuchsia { get { return FromHtml("#FFC154C1"); } } + public static XLColor DeepJungleGreen { get { return FromHtml("#FF004B49"); } } + public static XLColor DeepLilac { get { return FromHtml("#FF9955BB"); } } + public static XLColor DeepMagenta { get { return FromHtml("#FFCC00CC"); } } + public static XLColor DeepPeach { get { return FromHtml("#FFFFCBA4"); } } + public static XLColor DeepSaffron { get { return FromHtml("#FFFF9933"); } } + public static XLColor Denim { get { return FromHtml("#FF1560BD"); } } + public static XLColor Desert { get { return FromHtml("#FFC19A6B"); } } + public static XLColor DesertSand { get { return FromHtml("#FFEDC9AF"); } } + public static XLColor DogwoodRose { get { return FromHtml("#FFD71868"); } } + public static XLColor DollarBill { get { return FromHtml("#FF85BB65"); } } + public static XLColor Drab { get { return FromHtml("#FF967117"); } } + public static XLColor DukeBlue { get { return FromHtml("#FF00009C"); } } + public static XLColor EarthYellow { get { return FromHtml("#FFE1A95F"); } } + public static XLColor Ecru { get { return FromHtml("#FFC2B280"); } } + public static XLColor Eggplant { get { return FromHtml("#FF614051"); } } + public static XLColor Eggshell { get { return FromHtml("#FFF0EAD6"); } } + public static XLColor EgyptianBlue { get { return FromHtml("#FF1034A6"); } } + public static XLColor ElectricBlue { get { return FromHtml("#FF7DF9FF"); } } + public static XLColor ElectricCrimson { get { return FromHtml("#FFFF003F"); } } + public static XLColor ElectricIndigo { get { return FromHtml("#FF6F00FF"); } } + public static XLColor ElectricLavender { get { return FromHtml("#FFF4BBFF"); } } + public static XLColor ElectricLime { get { return FromHtml("#FFCCFF00"); } } + public static XLColor ElectricPurple { get { return FromHtml("#FFBF00FF"); } } + public static XLColor ElectricUltramarine { get { return FromHtml("#FF3F00FF"); } } + public static XLColor ElectricViolet { get { return FromHtml("#FF8F00FF"); } } + public static XLColor Emerald { get { return FromHtml("#FF50C878"); } } + public static XLColor EtonBlue { get { return FromHtml("#FF96C8A2"); } } + public static XLColor Fallow { get { return FromHtml("#FFC19A6B"); } } + public static XLColor FaluRed { get { return FromHtml("#FF801818"); } } + public static XLColor Fandango { get { return FromHtml("#FFB53389"); } } + public static XLColor FashionFuchsia { get { return FromHtml("#FFF400A1"); } } + public static XLColor Fawn { get { return FromHtml("#FFE5AA70"); } } + public static XLColor Feldgrau { get { return FromHtml("#FF4D5D53"); } } + public static XLColor FernGreen { get { return FromHtml("#FF4F7942"); } } + public static XLColor FerrariRed { get { return FromHtml("#FFFF2800"); } } + public static XLColor FieldDrab { get { return FromHtml("#FF6C541E"); } } + public static XLColor FireEngineRed { get { return FromHtml("#FFCE2029"); } } + public static XLColor Flame { get { return FromHtml("#FFE25822"); } } + public static XLColor FlamingoPink { get { return FromHtml("#FFFC8EAC"); } } + public static XLColor Flavescent { get { return FromHtml("#FFF7E98E"); } } + public static XLColor Flax { get { return FromHtml("#FFEEDC82"); } } + public static XLColor FluorescentOrange { get { return FromHtml("#FFFFBF00"); } } + public static XLColor FluorescentYellow { get { return FromHtml("#FFCCFF00"); } } + public static XLColor Folly { get { return FromHtml("#FFFF004F"); } } + public static XLColor ForestGreenTraditional { get { return FromHtml("#FF014421"); } } + public static XLColor FrenchBeige { get { return FromHtml("#FFA67B5B"); } } + public static XLColor FrenchBlue { get { return FromHtml("#FF0072BB"); } } + public static XLColor FrenchLilac { get { return FromHtml("#FF86608E"); } } + public static XLColor FrenchRose { get { return FromHtml("#FFF64A8A"); } } + public static XLColor FuchsiaPink { get { return FromHtml("#FFFF77FF"); } } + public static XLColor Fulvous { get { return FromHtml("#FFE48400"); } } + public static XLColor FuzzyWuzzy { get { return FromHtml("#FFCC6666"); } } + public static XLColor Gamboge { get { return FromHtml("#FFE49B0F"); } } + public static XLColor Ginger { get { return FromHtml("#FFF9F9FF"); } } + public static XLColor Glaucous { get { return FromHtml("#FF6082B6"); } } + public static XLColor GoldenBrown { get { return FromHtml("#FF996515"); } } + public static XLColor GoldenPoppy { get { return FromHtml("#FFFCC200"); } } + public static XLColor GoldenYellow { get { return FromHtml("#FFFFDF00"); } } + public static XLColor GoldMetallic { get { return FromHtml("#FFD4AF37"); } } + public static XLColor GrannySmithApple { get { return FromHtml("#FFA8E4A0"); } } + public static XLColor GrayAsparagus { get { return FromHtml("#FF465945"); } } + public static XLColor GreenPigment { get { return FromHtml("#FF00A550"); } } + public static XLColor GreenRyb { get { return FromHtml("#FF66B032"); } } + public static XLColor Grullo { get { return FromHtml("#FFA99A86"); } } + public static XLColor HalayaUbe { get { return FromHtml("#FF663854"); } } + public static XLColor HanBlue { get { return FromHtml("#FF446CCF"); } } + public static XLColor HanPurple { get { return FromHtml("#FF5218FA"); } } + public static XLColor HansaYellow { get { return FromHtml("#FFE9D66B"); } } + public static XLColor Harlequin { get { return FromHtml("#FF3FFF00"); } } + public static XLColor HarvardCrimson { get { return FromHtml("#FFC90016"); } } + public static XLColor HarvestGold { get { return FromHtml("#FFDA9100"); } } + public static XLColor Heliotrope { get { return FromHtml("#FFDF73FF"); } } + public static XLColor HollywoodCerise { get { return FromHtml("#FFF400A1"); } } + public static XLColor HookersGreen { get { return FromHtml("#FF007000"); } } + public static XLColor HotMagenta { get { return FromHtml("#FFFF1DCE"); } } + public static XLColor HunterGreen { get { return FromHtml("#FF355E3B"); } } + public static XLColor Iceberg { get { return FromHtml("#FF71A6D2"); } } + public static XLColor Icterine { get { return FromHtml("#FFFCF75E"); } } + public static XLColor Inchworm { get { return FromHtml("#FFB2EC5D"); } } + public static XLColor IndiaGreen { get { return FromHtml("#FF138808"); } } + public static XLColor IndianYellow { get { return FromHtml("#FFE3A857"); } } + public static XLColor IndigoDye { get { return FromHtml("#FF00416A"); } } + public static XLColor InternationalKleinBlue { get { return FromHtml("#FF002FA7"); } } + public static XLColor InternationalOrange { get { return FromHtml("#FFFF4F00"); } } + public static XLColor Iris { get { return FromHtml("#FF5A4FCF"); } } + public static XLColor Isabelline { get { return FromHtml("#FFF4F0EC"); } } + public static XLColor IslamicGreen { get { return FromHtml("#FF009000"); } } + public static XLColor Jade { get { return FromHtml("#FF00A86B"); } } + public static XLColor Jasper { get { return FromHtml("#FFD73B3E"); } } + public static XLColor JazzberryJam { get { return FromHtml("#FFA50B5E"); } } + public static XLColor Jonquil { get { return FromHtml("#FFFADA5E"); } } + public static XLColor JuneBud { get { return FromHtml("#FFBDDA57"); } } + public static XLColor JungleGreen { get { return FromHtml("#FF29AB87"); } } + public static XLColor KellyGreen { get { return FromHtml("#FF4CBB17"); } } + public static XLColor KhakiHtmlCssKhaki { get { return FromHtml("#FFC3B091"); } } + public static XLColor LanguidLavender { get { return FromHtml("#FFD6CADD"); } } + public static XLColor LapisLazuli { get { return FromHtml("#FF26619C"); } } + public static XLColor LaSalleGreen { get { return FromHtml("#FF087830"); } } + public static XLColor LaserLemon { get { return FromHtml("#FFFEFE22"); } } + public static XLColor Lava { get { return FromHtml("#FFCF1020"); } } + public static XLColor LavenderBlue { get { return FromHtml("#FFCCCCFF"); } } + public static XLColor LavenderFloral { get { return FromHtml("#FFB57EDC"); } } + public static XLColor LavenderGray { get { return FromHtml("#FFC4C3D0"); } } + public static XLColor LavenderIndigo { get { return FromHtml("#FF9457EB"); } } + public static XLColor LavenderPink { get { return FromHtml("#FFFBAED2"); } } + public static XLColor LavenderPurple { get { return FromHtml("#FF967BB6"); } } + public static XLColor LavenderRose { get { return FromHtml("#FFFBA0E3"); } } + public static XLColor Lemon { get { return FromHtml("#FFFFF700"); } } + public static XLColor LightApricot { get { return FromHtml("#FFFDD5B1"); } } + public static XLColor LightBrown { get { return FromHtml("#FFB5651D"); } } + public static XLColor LightCarminePink { get { return FromHtml("#FFE66771"); } } + public static XLColor LightCornflowerBlue { get { return FromHtml("#FF93CCEA"); } } + public static XLColor LightFuchsiaPink { get { return FromHtml("#FFF984EF"); } } + public static XLColor LightMauve { get { return FromHtml("#FFDCD0FF"); } } + public static XLColor LightPastelPurple { get { return FromHtml("#FFB19CD9"); } } + public static XLColor LightSalmonPink { get { return FromHtml("#FFFF9999"); } } + public static XLColor LightTaupe { get { return FromHtml("#FFB38B6D"); } } + public static XLColor LightThulianPink { get { return FromHtml("#FFE68FAC"); } } + public static XLColor LightYellow1 { get { return FromHtml("#FFFFFFED"); } } + public static XLColor Lilac { get { return FromHtml("#FFC8A2C8"); } } + public static XLColor LimeColorWheel { get { return FromHtml("#FFBFFF00"); } } + public static XLColor LincolnGreen { get { return FromHtml("#FF195905"); } } + public static XLColor Liver { get { return FromHtml("#FF534B4F"); } } + public static XLColor Lust { get { return FromHtml("#FFE62020"); } } + public static XLColor MacaroniAndCheese { get { return FromHtml("#FFFFBD88"); } } + public static XLColor MagentaDye { get { return FromHtml("#FFCA1F7B"); } } + public static XLColor MagentaProcess { get { return FromHtml("#FFFF0090"); } } + public static XLColor MagicMint { get { return FromHtml("#FFAAF0D1"); } } + public static XLColor Magnolia { get { return FromHtml("#FFF8F4FF"); } } + public static XLColor Mahogany { get { return FromHtml("#FFC04000"); } } + public static XLColor Maize { get { return FromHtml("#FFFBEC5D"); } } + public static XLColor MajorelleBlue { get { return FromHtml("#FF6050DC"); } } + public static XLColor Malachite { get { return FromHtml("#FF0BDA51"); } } + public static XLColor Manatee { get { return FromHtml("#FF979AAA"); } } + public static XLColor MangoTango { get { return FromHtml("#FFFF8243"); } } + public static XLColor MaroonX11 { get { return FromHtml("#FFB03060"); } } + public static XLColor Mauve { get { return FromHtml("#FFE0B0FF"); } } + public static XLColor Mauvelous { get { return FromHtml("#FFEF98AA"); } } + public static XLColor MauveTaupe { get { return FromHtml("#FF915F6D"); } } + public static XLColor MayaBlue { get { return FromHtml("#FF73C2FB"); } } + public static XLColor MeatBrown { get { return FromHtml("#FFE5B73B"); } } + public static XLColor MediumAquamarine1 { get { return FromHtml("#FF66DDAA"); } } + public static XLColor MediumCandyAppleRed { get { return FromHtml("#FFE2062C"); } } + public static XLColor MediumCarmine { get { return FromHtml("#FFAF4035"); } } + public static XLColor MediumChampagne { get { return FromHtml("#FFF3E5AB"); } } + public static XLColor MediumElectricBlue { get { return FromHtml("#FF035096"); } } + public static XLColor MediumJungleGreen { get { return FromHtml("#FF1C352D"); } } + public static XLColor MediumPersianBlue { get { return FromHtml("#FF0067A5"); } } + public static XLColor MediumRedViolet { get { return FromHtml("#FFBB3385"); } } + public static XLColor MediumSpringBud { get { return FromHtml("#FFC9DC87"); } } + public static XLColor MediumTaupe { get { return FromHtml("#FF674C47"); } } + public static XLColor Melon { get { return FromHtml("#FFFDBCB4"); } } + public static XLColor MidnightGreenEagleGreen { get { return FromHtml("#FF004953"); } } + public static XLColor MikadoYellow { get { return FromHtml("#FFFFC40C"); } } + public static XLColor Mint { get { return FromHtml("#FF3EB489"); } } + public static XLColor MintGreen { get { return FromHtml("#FF98FF98"); } } + public static XLColor ModeBeige { get { return FromHtml("#FF967117"); } } + public static XLColor MoonstoneBlue { get { return FromHtml("#FF73A9C2"); } } + public static XLColor MordantRed19 { get { return FromHtml("#FFAE0C00"); } } + public static XLColor MossGreen { get { return FromHtml("#FFADDFAD"); } } + public static XLColor MountainMeadow { get { return FromHtml("#FF30BA8F"); } } + public static XLColor MountbattenPink { get { return FromHtml("#FF997A8D"); } } + public static XLColor MsuGreen { get { return FromHtml("#FF18453B"); } } + public static XLColor Mulberry { get { return FromHtml("#FFC54B8C"); } } + public static XLColor Mustard { get { return FromHtml("#FFFFDB58"); } } + public static XLColor Myrtle { get { return FromHtml("#FF21421E"); } } + public static XLColor NadeshikoPink { get { return FromHtml("#FFF6ADC6"); } } + public static XLColor NapierGreen { get { return FromHtml("#FF2A8000"); } } + public static XLColor NaplesYellow { get { return FromHtml("#FFFADA5E"); } } + public static XLColor NeonCarrot { get { return FromHtml("#FFFFA343"); } } + public static XLColor NeonFuchsia { get { return FromHtml("#FFFE59C2"); } } + public static XLColor NeonGreen { get { return FromHtml("#FF39FF14"); } } + public static XLColor NonPhotoBlue { get { return FromHtml("#FFA4DDED"); } } + public static XLColor OceanBoatBlue { get { return FromHtml("#FFCC7422"); } } + public static XLColor Ochre { get { return FromHtml("#FFCC7722"); } } + public static XLColor OldGold { get { return FromHtml("#FFCFB53B"); } } + public static XLColor OldLavender { get { return FromHtml("#FF796878"); } } + public static XLColor OldMauve { get { return FromHtml("#FF673147"); } } + public static XLColor OldRose { get { return FromHtml("#FFC08081"); } } + public static XLColor OliveDrab7 { get { return FromHtml("#FF3C341F"); } } + public static XLColor Olivine { get { return FromHtml("#FF9AB973"); } } + public static XLColor Onyx { get { return FromHtml("#FF0F0F0F"); } } + public static XLColor OperaMauve { get { return FromHtml("#FFB784A7"); } } + public static XLColor OrangeColorWheel { get { return FromHtml("#FFFF7F00"); } } + public static XLColor OrangePeel { get { return FromHtml("#FFFF9F00"); } } + public static XLColor OrangeRyb { get { return FromHtml("#FFFB9902"); } } + public static XLColor OtterBrown { get { return FromHtml("#FF654321"); } } + public static XLColor OuCrimsonRed { get { return FromHtml("#FF990000"); } } + public static XLColor OuterSpace { get { return FromHtml("#FF414A4C"); } } + public static XLColor OutrageousOrange { get { return FromHtml("#FFFF6E4A"); } } + public static XLColor OxfordBlue { get { return FromHtml("#FF002147"); } } + public static XLColor PakistanGreen { get { return FromHtml("#FF00421B"); } } + public static XLColor PalatinateBlue { get { return FromHtml("#FF273BE2"); } } + public static XLColor PalatinatePurple { get { return FromHtml("#FF682860"); } } + public static XLColor PaleAqua { get { return FromHtml("#FFBCD4E6"); } } + public static XLColor PaleBrown { get { return FromHtml("#FF987654"); } } + public static XLColor PaleCarmine { get { return FromHtml("#FFAF4035"); } } + public static XLColor PaleCerulean { get { return FromHtml("#FF9BC4E2"); } } + public static XLColor PaleChestnut { get { return FromHtml("#FFDDADAF"); } } + public static XLColor PaleCopper { get { return FromHtml("#FFDA8A67"); } } + public static XLColor PaleCornflowerBlue { get { return FromHtml("#FFABCDEF"); } } + public static XLColor PaleGold { get { return FromHtml("#FFE6BE8A"); } } + public static XLColor PaleMagenta { get { return FromHtml("#FFF984E5"); } } + public static XLColor PalePink { get { return FromHtml("#FFFADADD"); } } + public static XLColor PaleRobinEggBlue { get { return FromHtml("#FF96DED1"); } } + public static XLColor PaleSilver { get { return FromHtml("#FFC9C0BB"); } } + public static XLColor PaleSpringBud { get { return FromHtml("#FFECEBBD"); } } + public static XLColor PaleTaupe { get { return FromHtml("#FFBC987E"); } } + public static XLColor PansyPurple { get { return FromHtml("#FF78184A"); } } + public static XLColor ParisGreen { get { return FromHtml("#FF50C878"); } } + public static XLColor PastelBlue { get { return FromHtml("#FFAEC6CF"); } } + public static XLColor PastelBrown { get { return FromHtml("#FF836953"); } } + public static XLColor PastelGray { get { return FromHtml("#FFCFCFC4"); } } + public static XLColor PastelGreen { get { return FromHtml("#FF77DD77"); } } + public static XLColor PastelMagenta { get { return FromHtml("#FFF49AC2"); } } + public static XLColor PastelOrange { get { return FromHtml("#FFFFB347"); } } + public static XLColor PastelPink { get { return FromHtml("#FFFFD1DC"); } } + public static XLColor PastelPurple { get { return FromHtml("#FFB39EB5"); } } + public static XLColor PastelRed { get { return FromHtml("#FFFF6961"); } } + public static XLColor PastelViolet { get { return FromHtml("#FFCB99C9"); } } + public static XLColor PastelYellow { get { return FromHtml("#FFFDFD96"); } } + public static XLColor PaynesGrey { get { return FromHtml("#FF40404F"); } } + public static XLColor Peach { get { return FromHtml("#FFFFE5B4"); } } + public static XLColor PeachOrange { get { return FromHtml("#FFFFCC99"); } } + public static XLColor PeachYellow { get { return FromHtml("#FFFADFAD"); } } + public static XLColor Pear { get { return FromHtml("#FFD1E231"); } } + public static XLColor Pearl { get { return FromHtml("#FFF0EAD6"); } } + public static XLColor Peridot { get { return FromHtml("#FFE6E200"); } } + public static XLColor Periwinkle { get { return FromHtml("#FFCCCCFF"); } } + public static XLColor PersianBlue { get { return FromHtml("#FF1C39BB"); } } + public static XLColor PersianGreen { get { return FromHtml("#FF00A693"); } } + public static XLColor PersianIndigo { get { return FromHtml("#FF32127A"); } } + public static XLColor PersianOrange { get { return FromHtml("#FFD99058"); } } + public static XLColor PersianPink { get { return FromHtml("#FFF77FBE"); } } + public static XLColor PersianPlum { get { return FromHtml("#FF701C1C"); } } + public static XLColor PersianRed { get { return FromHtml("#FFCC3333"); } } + public static XLColor PersianRose { get { return FromHtml("#FFFE28A2"); } } + public static XLColor Persimmon { get { return FromHtml("#FFEC5800"); } } + public static XLColor Phlox { get { return FromHtml("#FFDF00FF"); } } + public static XLColor PhthaloBlue { get { return FromHtml("#FF000F89"); } } + public static XLColor PhthaloGreen { get { return FromHtml("#FF123524"); } } + public static XLColor PiggyPink { get { return FromHtml("#FFFDDDE6"); } } + public static XLColor PineGreen { get { return FromHtml("#FF01796F"); } } + public static XLColor PinkOrange { get { return FromHtml("#FFFF9966"); } } + public static XLColor PinkPearl { get { return FromHtml("#FFE7ACCF"); } } + public static XLColor PinkSherbet { get { return FromHtml("#FFF78FA7"); } } + public static XLColor Pistachio { get { return FromHtml("#FF93C572"); } } + public static XLColor Platinum { get { return FromHtml("#FFE5E4E2"); } } + public static XLColor PlumTraditional { get { return FromHtml("#FF8E4585"); } } + public static XLColor PortlandOrange { get { return FromHtml("#FFFF5A36"); } } + public static XLColor PrincetonOrange { get { return FromHtml("#FFFF8F00"); } } + public static XLColor Prune { get { return FromHtml("#FF701C1C"); } } + public static XLColor PrussianBlue { get { return FromHtml("#FF003153"); } } + public static XLColor PsychedelicPurple { get { return FromHtml("#FFDF00FF"); } } + public static XLColor Puce { get { return FromHtml("#FFCC8899"); } } + public static XLColor Pumpkin { get { return FromHtml("#FFFF7518"); } } + public static XLColor PurpleHeart { get { return FromHtml("#FF69359C"); } } + public static XLColor PurpleMountainMajesty { get { return FromHtml("#FF9678B6"); } } + public static XLColor PurpleMunsell { get { return FromHtml("#FF9F00C5"); } } + public static XLColor PurplePizzazz { get { return FromHtml("#FFFE4EDA"); } } + public static XLColor PurpleTaupe { get { return FromHtml("#FF50404D"); } } + public static XLColor PurpleX11 { get { return FromHtml("#FFA020F0"); } } + public static XLColor RadicalRed { get { return FromHtml("#FFFF355E"); } } + public static XLColor Raspberry { get { return FromHtml("#FFE30B5D"); } } + public static XLColor RaspberryGlace { get { return FromHtml("#FF915F6D"); } } + public static XLColor RaspberryPink { get { return FromHtml("#FFE25098"); } } + public static XLColor RaspberryRose { get { return FromHtml("#FFB3446C"); } } + public static XLColor RawUmber { get { return FromHtml("#FF826644"); } } + public static XLColor RazzleDazzleRose { get { return FromHtml("#FFFF33CC"); } } + public static XLColor Razzmatazz { get { return FromHtml("#FFE3256B"); } } + public static XLColor RedMunsell { get { return FromHtml("#FFF2003C"); } } + public static XLColor RedNcs { get { return FromHtml("#FFC40233"); } } + public static XLColor RedPigment { get { return FromHtml("#FFED1C24"); } } + public static XLColor RedRyb { get { return FromHtml("#FFFE2712"); } } + public static XLColor Redwood { get { return FromHtml("#FFAB4E52"); } } + public static XLColor Regalia { get { return FromHtml("#FF522D80"); } } + public static XLColor RichBlack { get { return FromHtml("#FF004040"); } } + public static XLColor RichBrilliantLavender { get { return FromHtml("#FFF1A7FE"); } } + public static XLColor RichCarmine { get { return FromHtml("#FFD70040"); } } + public static XLColor RichElectricBlue { get { return FromHtml("#FF0892D0"); } } + public static XLColor RichLavender { get { return FromHtml("#FFA76BCF"); } } + public static XLColor RichLilac { get { return FromHtml("#FFB666D2"); } } + public static XLColor RichMaroon { get { return FromHtml("#FFB03060"); } } + public static XLColor RifleGreen { get { return FromHtml("#FF414833"); } } + public static XLColor RobinEggBlue { get { return FromHtml("#FF00CCCC"); } } + public static XLColor Rose { get { return FromHtml("#FFFF007F"); } } + public static XLColor RoseBonbon { get { return FromHtml("#FFF9429E"); } } + public static XLColor RoseEbony { get { return FromHtml("#FF674846"); } } + public static XLColor RoseGold { get { return FromHtml("#FFB76E79"); } } + public static XLColor RoseMadder { get { return FromHtml("#FFE32636"); } } + public static XLColor RosePink { get { return FromHtml("#FFFF66CC"); } } + public static XLColor RoseQuartz { get { return FromHtml("#FFAA98A9"); } } + public static XLColor RoseTaupe { get { return FromHtml("#FF905D5D"); } } + public static XLColor RoseVale { get { return FromHtml("#FFAB4E52"); } } + public static XLColor Rosewood { get { return FromHtml("#FF65000B"); } } + public static XLColor RossoCorsa { get { return FromHtml("#FFD40000"); } } + public static XLColor RoyalAzure { get { return FromHtml("#FF0038A8"); } } + public static XLColor RoyalBlueTraditional { get { return FromHtml("#FF002366"); } } + public static XLColor RoyalFuchsia { get { return FromHtml("#FFCA2C92"); } } + public static XLColor RoyalPurple { get { return FromHtml("#FF7851A9"); } } + public static XLColor Ruby { get { return FromHtml("#FFE0115F"); } } + public static XLColor Ruddy { get { return FromHtml("#FFFF0028"); } } + public static XLColor RuddyBrown { get { return FromHtml("#FFBB6528"); } } + public static XLColor RuddyPink { get { return FromHtml("#FFE18E96"); } } + public static XLColor Rufous { get { return FromHtml("#FFA81C07"); } } + public static XLColor Russet { get { return FromHtml("#FF80461B"); } } + public static XLColor Rust { get { return FromHtml("#FFB7410E"); } } + public static XLColor SacramentoStateGreen { get { return FromHtml("#FF00563F"); } } + public static XLColor SafetyOrangeBlazeOrange { get { return FromHtml("#FFFF6700"); } } + public static XLColor Saffron { get { return FromHtml("#FFF4C430"); } } + public static XLColor Salmon1 { get { return FromHtml("#FFFF8C69"); } } + public static XLColor SalmonPink { get { return FromHtml("#FFFF91A4"); } } + public static XLColor Sand { get { return FromHtml("#FFC2B280"); } } + public static XLColor SandDune { get { return FromHtml("#FF967117"); } } + public static XLColor Sandstorm { get { return FromHtml("#FFECD540"); } } + public static XLColor SandyTaupe { get { return FromHtml("#FF967117"); } } + public static XLColor Sangria { get { return FromHtml("#FF92000A"); } } + public static XLColor SapGreen { get { return FromHtml("#FF507D2A"); } } + public static XLColor Sapphire { get { return FromHtml("#FF082567"); } } + public static XLColor SatinSheenGold { get { return FromHtml("#FFCBA135"); } } + public static XLColor Scarlet { get { return FromHtml("#FFFF2000"); } } + public static XLColor SchoolBusYellow { get { return FromHtml("#FFFFD800"); } } + public static XLColor ScreaminGreen { get { return FromHtml("#FF76FF7A"); } } + public static XLColor SealBrown { get { return FromHtml("#FF321414"); } } + public static XLColor SelectiveYellow { get { return FromHtml("#FFFFBA00"); } } + public static XLColor Sepia { get { return FromHtml("#FF704214"); } } + public static XLColor Shadow { get { return FromHtml("#FF8A795D"); } } + public static XLColor ShamrockGreen { get { return FromHtml("#FF009E60"); } } + public static XLColor ShockingPink { get { return FromHtml("#FFFC0FC0"); } } + public static XLColor Sienna1 { get { return FromHtml("#FF882D17"); } } + public static XLColor Sinopia { get { return FromHtml("#FFCB410B"); } } + public static XLColor Skobeloff { get { return FromHtml("#FF007474"); } } + public static XLColor SkyMagenta { get { return FromHtml("#FFCF71AF"); } } + public static XLColor SmaltDarkPowderBlue { get { return FromHtml("#FF003399"); } } + public static XLColor SmokeyTopaz { get { return FromHtml("#FF933D41"); } } + public static XLColor SmokyBlack { get { return FromHtml("#FF100C08"); } } + public static XLColor SpiroDiscoBall { get { return FromHtml("#FF0FC0FC"); } } + public static XLColor SplashedWhite { get { return FromHtml("#FFFEFDFF"); } } + public static XLColor SpringBud { get { return FromHtml("#FFA7FC00"); } } + public static XLColor StPatricksBlue { get { return FromHtml("#FF23297A"); } } + public static XLColor StilDeGrainYellow { get { return FromHtml("#FFFADA5E"); } } + public static XLColor Straw { get { return FromHtml("#FFE4D96F"); } } + public static XLColor Sunglow { get { return FromHtml("#FFFFCC33"); } } + public static XLColor Sunset { get { return FromHtml("#FFFAD6A5"); } } + public static XLColor Tangelo { get { return FromHtml("#FFF94D00"); } } + public static XLColor Tangerine { get { return FromHtml("#FFF28500"); } } + public static XLColor TangerineYellow { get { return FromHtml("#FFFFCC00"); } } + public static XLColor Taupe { get { return FromHtml("#FF483C32"); } } + public static XLColor TaupeGray { get { return FromHtml("#FF8B8589"); } } + public static XLColor TeaGreen { get { return FromHtml("#FFD0F0C0"); } } + public static XLColor TealBlue { get { return FromHtml("#FF367588"); } } + public static XLColor TealGreen { get { return FromHtml("#FF006D5B"); } } + public static XLColor TeaRoseOrange { get { return FromHtml("#FFF88379"); } } + public static XLColor TeaRoseRose { get { return FromHtml("#FFF4C2C2"); } } + public static XLColor TennéTawny { get { return FromHtml("#FFCD5700"); } } + public static XLColor TerraCotta { get { return FromHtml("#FFE2725B"); } } + public static XLColor ThulianPink { get { return FromHtml("#FFDE6FA1"); } } + public static XLColor TickleMePink { get { return FromHtml("#FFFC89AC"); } } + public static XLColor TiffanyBlue { get { return FromHtml("#FF0ABAB5"); } } + public static XLColor TigersEye { get { return FromHtml("#FFE08D3C"); } } + public static XLColor Timberwolf { get { return FromHtml("#FFDBD7D2"); } } + public static XLColor TitaniumYellow { get { return FromHtml("#FFEEE600"); } } + public static XLColor Toolbox { get { return FromHtml("#FF746CC0"); } } + public static XLColor TractorRed { get { return FromHtml("#FFFD0E35"); } } + public static XLColor TropicalRainForest { get { return FromHtml("#FF00755E"); } } + public static XLColor TuftsBlue { get { return FromHtml("#FF417DC1"); } } + public static XLColor Tumbleweed { get { return FromHtml("#FFDEAA88"); } } + public static XLColor TurkishRose { get { return FromHtml("#FFB57281"); } } + public static XLColor Turquoise1 { get { return FromHtml("#FF30D5C8"); } } + public static XLColor TurquoiseBlue { get { return FromHtml("#FF00FFEF"); } } + public static XLColor TurquoiseGreen { get { return FromHtml("#FFA0D6B4"); } } + public static XLColor TuscanRed { get { return FromHtml("#FF823535"); } } + public static XLColor TwilightLavender { get { return FromHtml("#FF8A496B"); } } + public static XLColor TyrianPurple { get { return FromHtml("#FF66023C"); } } + public static XLColor UaBlue { get { return FromHtml("#FF0033AA"); } } + public static XLColor UaRed { get { return FromHtml("#FFD9004C"); } } + public static XLColor Ube { get { return FromHtml("#FF8878C3"); } } + public static XLColor UclaBlue { get { return FromHtml("#FF536895"); } } + public static XLColor UclaGold { get { return FromHtml("#FFFFB300"); } } + public static XLColor UfoGreen { get { return FromHtml("#FF3CD070"); } } + public static XLColor Ultramarine { get { return FromHtml("#FF120A8F"); } } + public static XLColor UltramarineBlue { get { return FromHtml("#FF4166F5"); } } + public static XLColor UltraPink { get { return FromHtml("#FFFF6FFF"); } } + public static XLColor Umber { get { return FromHtml("#FF635147"); } } + public static XLColor UnitedNationsBlue { get { return FromHtml("#FF5B92E5"); } } + public static XLColor UnmellowYellow { get { return FromHtml("#FFFFFF66"); } } + public static XLColor UpForestGreen { get { return FromHtml("#FF014421"); } } + public static XLColor UpMaroon { get { return FromHtml("#FF7B1113"); } } + public static XLColor UpsdellRed { get { return FromHtml("#FFAE2029"); } } + public static XLColor Urobilin { get { return FromHtml("#FFE1AD21"); } } + public static XLColor UscCardinal { get { return FromHtml("#FF990000"); } } + public static XLColor UscGold { get { return FromHtml("#FFFFCC00"); } } + public static XLColor UtahCrimson { get { return FromHtml("#FFD3003F"); } } + public static XLColor Vanilla { get { return FromHtml("#FFF3E5AB"); } } + public static XLColor VegasGold { get { return FromHtml("#FFC5B358"); } } + public static XLColor VenetianRed { get { return FromHtml("#FFC80815"); } } + public static XLColor Verdigris { get { return FromHtml("#FF43B3AE"); } } + public static XLColor Vermilion { get { return FromHtml("#FFE34234"); } } + public static XLColor Veronica { get { return FromHtml("#FFA020F0"); } } + public static XLColor Violet1 { get { return FromHtml("#FF8F00FF"); } } + public static XLColor VioletColorWheel { get { return FromHtml("#FF7F00FF"); } } + public static XLColor VioletRyb { get { return FromHtml("#FF8601AF"); } } + public static XLColor Viridian { get { return FromHtml("#FF40826D"); } } + public static XLColor VividAuburn { get { return FromHtml("#FF922724"); } } + public static XLColor VividBurgundy { get { return FromHtml("#FF9F1D35"); } } + public static XLColor VividCerise { get { return FromHtml("#FFDA1D81"); } } + public static XLColor VividTangerine { get { return FromHtml("#FFFFA089"); } } + public static XLColor VividViolet { get { return FromHtml("#FF9F00FF"); } } + public static XLColor WarmBlack { get { return FromHtml("#FF004242"); } } + public static XLColor Wenge { get { return FromHtml("#FF645452"); } } + public static XLColor WildBlueYonder { get { return FromHtml("#FFA2ADD0"); } } + public static XLColor WildStrawberry { get { return FromHtml("#FFFF43A4"); } } + public static XLColor WildWatermelon { get { return FromHtml("#FFFC6C85"); } } + public static XLColor Wisteria { get { return FromHtml("#FFC9A0DC"); } } + public static XLColor Xanadu { get { return FromHtml("#FF738678"); } } + public static XLColor YaleBlue { get { return FromHtml("#FF0F4D92"); } } + public static XLColor YellowMunsell { get { return FromHtml("#FFEFCC00"); } } + public static XLColor YellowNcs { get { return FromHtml("#FFFFD300"); } } + public static XLColor YellowProcess { get { return FromHtml("#FFFFEF00"); } } + public static XLColor YellowRyb { get { return FromHtml("#FFFEFE33"); } } + public static XLColor Zaffre { get { return FromHtml("#FF0014A8"); } } + public static XLColor ZinnwalditeBrown { get { return FromHtml("#FF2C1608"); } } + public static XLColor Transparent { get { return FromColor(Color.Transparent); } } } } diff --git a/ClosedXML/Excel/Style/IXLAlignment.cs b/ClosedXML/Excel/Style/IXLAlignment.cs index f516558..61a3301 100644 --- a/ClosedXML/Excel/Style/IXLAlignment.cs +++ b/ClosedXML/Excel/Style/IXLAlignment.cs @@ -30,7 +30,7 @@ Top } - public interface IXLAlignment: IEquatable + public interface IXLAlignment : IEquatable { /// /// Gets or sets the cell's horizontal alignment. @@ -46,30 +46,37 @@ /// Gets or sets the cell's text indentation. /// Int32 Indent { get; set; } + /// /// Gets or sets whether the cell's last line is justified or not. /// Boolean JustifyLastLine { get; set; } + /// /// Gets or sets the cell's reading order. /// XLAlignmentReadingOrderValues ReadingOrder { get; set; } + /// /// Gets or sets the cell's relative indent. /// Int32 RelativeIndent { get; set; } + /// /// Gets or sets whether the cell's font size should decrease to fit the contents. /// Boolean ShrinkToFit { get; set; } + /// /// Gets or sets the cell's text rotation. /// Int32 TextRotation { get; set; } + /// /// Gets or sets whether the cell's text should wrap if it doesn't fit. /// Boolean WrapText { get; set; } + /// /// Gets or sets wheter the cell's text should be displayed from to to bottom /// (as opposed to the normal left to right). @@ -77,15 +84,23 @@ Boolean TopToBottom { get; set; } IXLStyle SetHorizontal(XLAlignmentHorizontalValues value); - IXLStyle SetVertical(XLAlignmentVerticalValues value); - IXLStyle SetIndent(Int32 value); - IXLStyle SetJustifyLastLine(); IXLStyle SetJustifyLastLine(Boolean value); - IXLStyle SetReadingOrder(XLAlignmentReadingOrderValues value); - IXLStyle SetRelativeIndent(Int32 value); - IXLStyle SetShrinkToFit(); IXLStyle SetShrinkToFit(Boolean value); - IXLStyle SetTextRotation(Int32 value); - IXLStyle SetWrapText(); IXLStyle SetWrapText(Boolean value); - IXLStyle SetTopToBottom(); IXLStyle SetTopToBottom(Boolean value); + IXLStyle SetVertical(XLAlignmentVerticalValues value); + + IXLStyle SetIndent(Int32 value); + + IXLStyle SetJustifyLastLine(); IXLStyle SetJustifyLastLine(Boolean value); + + IXLStyle SetReadingOrder(XLAlignmentReadingOrderValues value); + + IXLStyle SetRelativeIndent(Int32 value); + + IXLStyle SetShrinkToFit(); IXLStyle SetShrinkToFit(Boolean value); + + IXLStyle SetTextRotation(Int32 value); + + IXLStyle SetWrapText(); IXLStyle SetWrapText(Boolean value); + + IXLStyle SetTopToBottom(); IXLStyle SetTopToBottom(Boolean value); } } diff --git a/ClosedXML/Excel/Style/IXLBorder.cs b/ClosedXML/Excel/Style/IXLBorder.cs index e83c61c..5c49df4 100644 --- a/ClosedXML/Excel/Style/IXLBorder.cs +++ b/ClosedXML/Excel/Style/IXLBorder.cs @@ -19,43 +19,71 @@ Thick, Thin } - public interface IXLBorder: IEquatable + + public interface IXLBorder : IEquatable { XLBorderStyleValues OutsideBorder { set; } + XLColor OutsideBorderColor { set; } + XLBorderStyleValues InsideBorder { set; } + XLColor InsideBorderColor { set; } XLBorderStyleValues LeftBorder { get; set; } + XLColor LeftBorderColor { get; set; } + XLBorderStyleValues RightBorder { get; set; } + XLColor RightBorderColor { get; set; } + XLBorderStyleValues TopBorder { get; set; } + XLColor TopBorderColor { get; set; } + XLBorderStyleValues BottomBorder { get; set; } + XLColor BottomBorderColor { get; set; } + Boolean DiagonalUp { get; set; } + Boolean DiagonalDown { get; set; } + XLBorderStyleValues DiagonalBorder { get; set; } + XLColor DiagonalBorderColor { get; set; } IXLStyle SetOutsideBorder(XLBorderStyleValues value); + IXLStyle SetOutsideBorderColor(XLColor value); + IXLStyle SetInsideBorder(XLBorderStyleValues value); + IXLStyle SetInsideBorderColor(XLColor value); IXLStyle SetLeftBorder(XLBorderStyleValues value); - IXLStyle SetLeftBorderColor(XLColor value); - IXLStyle SetRightBorder(XLBorderStyleValues value); - IXLStyle SetRightBorderColor(XLColor value); - IXLStyle SetTopBorder(XLBorderStyleValues value); - IXLStyle SetTopBorderColor(XLColor value); - IXLStyle SetBottomBorder(XLBorderStyleValues value); - IXLStyle SetBottomBorderColor(XLColor value); - IXLStyle SetDiagonalUp(); IXLStyle SetDiagonalUp(Boolean value); - IXLStyle SetDiagonalDown(); IXLStyle SetDiagonalDown(Boolean value); - IXLStyle SetDiagonalBorder(XLBorderStyleValues value); - IXLStyle SetDiagonalBorderColor(XLColor value); + IXLStyle SetLeftBorderColor(XLColor value); + + IXLStyle SetRightBorder(XLBorderStyleValues value); + + IXLStyle SetRightBorderColor(XLColor value); + + IXLStyle SetTopBorder(XLBorderStyleValues value); + + IXLStyle SetTopBorderColor(XLColor value); + + IXLStyle SetBottomBorder(XLBorderStyleValues value); + + IXLStyle SetBottomBorderColor(XLColor value); + + IXLStyle SetDiagonalUp(); IXLStyle SetDiagonalUp(Boolean value); + + IXLStyle SetDiagonalDown(); IXLStyle SetDiagonalDown(Boolean value); + + IXLStyle SetDiagonalBorder(XLBorderStyleValues value); + + IXLStyle SetDiagonalBorderColor(XLColor value); } } diff --git a/ClosedXML/Excel/Style/IXLFill.cs b/ClosedXML/Excel/Style/IXLFill.cs index fdc6359..69ac75f 100644 --- a/ClosedXML/Excel/Style/IXLFill.cs +++ b/ClosedXML/Excel/Style/IXLFill.cs @@ -28,7 +28,9 @@ public interface IXLFill : IEquatable { XLColor BackgroundColor { get; set; } + XLColor PatternColor { get; set; } + XLFillPatternValues PatternType { get; set; } IXLStyle SetBackgroundColor(XLColor value); diff --git a/ClosedXML/Excel/Style/IXLFontBase.cs b/ClosedXML/Excel/Style/IXLFontBase.cs index 77ac7a1..21b8288 100644 --- a/ClosedXML/Excel/Style/IXLFontBase.cs +++ b/ClosedXML/Excel/Style/IXLFontBase.cs @@ -2,18 +2,28 @@ namespace ClosedXML.Excel { - public interface IXLFontBase + public interface IXLFontBase { Boolean Bold { get; set; } + Boolean Italic { get; set; } + XLFontUnderlineValues Underline { get; set; } + Boolean Strikethrough { get; set; } + XLFontVerticalTextAlignmentValues VerticalAlignment { get; set; } + Boolean Shadow { get; set; } + Double FontSize { get; set; } + XLColor FontColor { get; set; } + String FontName { get; set; } + XLFontFamilyNumberingValues FontFamilyNumbering { get; set; } + XLFontCharSet FontCharSet { get; set; } } } diff --git a/ClosedXML/Excel/Style/IXLNumberFormatBase.cs b/ClosedXML/Excel/Style/IXLNumberFormatBase.cs index ac0e5d8..d334a93 100644 --- a/ClosedXML/Excel/Style/IXLNumberFormatBase.cs +++ b/ClosedXML/Excel/Style/IXLNumberFormatBase.cs @@ -1,13 +1,11 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ClosedXML.Excel { public interface IXLNumberFormatBase { Int32 NumberFormatId { get; set; } + String Format { get; set; } } } diff --git a/ClosedXML/Excel/Style/IXLProtection.cs b/ClosedXML/Excel/Style/IXLProtection.cs index 1a197e1..94d9153 100644 --- a/ClosedXML/Excel/Style/IXLProtection.cs +++ b/ClosedXML/Excel/Style/IXLProtection.cs @@ -5,10 +5,11 @@ public interface IXLProtection : IEquatable { Boolean Locked { get; set; } + Boolean Hidden { get; set; } IXLStyle SetLocked(); IXLStyle SetLocked(Boolean value); - IXLStyle SetHidden(); IXLStyle SetHidden(Boolean value); + IXLStyle SetHidden(); IXLStyle SetHidden(Boolean value); } } diff --git a/ClosedXML/Excel/Style/IXLStyle.cs b/ClosedXML/Excel/Style/IXLStyle.cs index 0edd7a3..259f568 100644 --- a/ClosedXML/Excel/Style/IXLStyle.cs +++ b/ClosedXML/Excel/Style/IXLStyle.cs @@ -2,14 +2,20 @@ namespace ClosedXML.Excel { - public interface IXLStyle: IEquatable + public interface IXLStyle : IEquatable { IXLAlignment Alignment { get; set; } + IXLBorder Border { get; set; } + IXLFill Fill { get; set; } + IXLFont Font { get; set; } + IXLNumberFormat NumberFormat { get; set; } + IXLNumberFormat DateFormat { get; } + IXLProtection Protection { get; set; } } } diff --git a/ClosedXML/Excel/Style/IXLStylized.cs b/ClosedXML/Excel/Style/IXLStylized.cs index 6a03319..c056e04 100644 --- a/ClosedXML/Excel/Style/IXLStylized.cs +++ b/ClosedXML/Excel/Style/IXLStylized.cs @@ -6,11 +6,18 @@ internal interface IXLStylized { IXLStyle Style { get; set; } + IEnumerable Styles { get; } - Boolean UpdatingStyle { get; set; } + IXLStyle InnerStyle { get; set; } + IXLRanges RangesUsed { get; } - Boolean StyleChanged { get; set; } - //Boolean IsDefault { get; set; } + + /// + /// Immutable style + /// + XLStyleValue StyleValue { get; } + + void ModifyStyle(Func modification); } } diff --git a/ClosedXML/Excel/Style/XLAlignment.cs b/ClosedXML/Excel/Style/XLAlignment.cs index 5f0a399..0082b49 100644 --- a/ClosedXML/Excel/Style/XLAlignment.cs +++ b/ClosedXML/Excel/Style/XLAlignment.cs @@ -9,325 +9,274 @@ { internal class XLAlignment : IXLAlignment { - private readonly IXLStylized _container; - private XLAlignmentHorizontalValues _horizontal; - private Int32 _indent; - private Boolean _justifyLastLine; - private XLAlignmentReadingOrderValues _readingOrder; - private Int32 _relativeIndent; - private Boolean _shrinkToFit; - private Int32 _textRotation; - private XLAlignmentVerticalValues _vertical; - private Boolean _wrapText; + #region Static members - public XLAlignment() : this(null, XLWorkbook.DefaultStyle.Alignment) + internal static XLAlignmentKey GenerateKey(IXLAlignment d) + { + XLAlignmentKey key; + if (d == null) + { + key = XLAlignmentValue.Default.Key; + } + else if (d is XLAlignment) + { + key = (d as XLAlignment).Key; + } + else + { + key = new XLAlignmentKey + { + Horizontal = d.Horizontal, + Vertical = d.Vertical, + Indent = d.Indent, + JustifyLastLine = d.JustifyLastLine, + ReadingOrder = d.ReadingOrder, + RelativeIndent = d.RelativeIndent, + ShrinkToFit = d.ShrinkToFit, + TextRotation = d.TextRotation, + WrapText = d.WrapText + }; + } + return key; + } + + #endregion Static members + + #region Properties + private readonly XLStyle _style; + + private XLAlignmentValue _value; + + internal XLAlignmentKey Key + { + get { return _value.Key; } + private set { _value = XLAlignmentValue.FromKey(value); } + } + + #endregion Properties + + #region Constructors + + /// + /// Create an instance of XLAlignment initializing it with the specified value. + /// + /// Style to attach the new instance to. + /// Style value to use. + public XLAlignment(XLStyle style, XLAlignmentValue value) + { + _style = style ?? XLStyle.CreateEmptyStyle(); + _value = value; + } + + public XLAlignment(XLStyle style, XLAlignmentKey key) : this(style, XLAlignmentValue.FromKey(key)) { } - public XLAlignment(IXLStylized container, IXLAlignment d = null) + public XLAlignment(XLStyle style = null, IXLAlignment d = null) : this(style, GenerateKey(d)) { - _container = container; - if (d == null) return; - - _horizontal = d.Horizontal; - _vertical = d.Vertical; - _indent = d.Indent; - _justifyLastLine = d.JustifyLastLine; - _readingOrder = d.ReadingOrder; - _relativeIndent = d.RelativeIndent; - _shrinkToFit = d.ShrinkToFit; - _textRotation = d.TextRotation; - _wrapText = d.WrapText; } + #endregion Constructors + #region IXLAlignment Members public XLAlignmentHorizontalValues Horizontal { - get { return _horizontal; } + get { return Key.Horizontal; } set { - SetStyleChanged(); Boolean updateIndent = !( - value == XLAlignmentHorizontalValues.Left + value == XLAlignmentHorizontalValues.Left || value == XLAlignmentHorizontalValues.Right || value == XLAlignmentHorizontalValues.Distributed ); - if (_container != null && !_container.UpdatingStyle) - { - _container.Styles.ForEach(s => - { - s.Alignment.Horizontal = value; - if (updateIndent) s.Alignment.Indent = 0; - }); - } - else - { - _horizontal = value; - if (updateIndent) - _indent = 0; - } + Modify(k => { k.Horizontal = value; return k; }); + if (updateIndent) + Indent = 0; } } public XLAlignmentVerticalValues Vertical { - get { return _vertical; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.Vertical = value); - else - _vertical = value; - } + get { return Key.Vertical; } + set { Modify(k => { k.Vertical = value; return k; }); } } public Int32 Indent { - get { return _indent; } + get { return Key.Indent; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.Indent = value); - else + if (Indent != value) { - if (_indent != value) + if (Horizontal == XLAlignmentHorizontalValues.General) + Horizontal = XLAlignmentHorizontalValues.Left; + + if (value > 0 && !( + Horizontal == XLAlignmentHorizontalValues.Left + || Horizontal == XLAlignmentHorizontalValues.Right + || Horizontal == XLAlignmentHorizontalValues.Distributed + )) { - if (_horizontal == XLAlignmentHorizontalValues.General) - _horizontal = XLAlignmentHorizontalValues.Left; - - if (value > 0 && !( - _horizontal == XLAlignmentHorizontalValues.Left - || _horizontal == XLAlignmentHorizontalValues.Right - || _horizontal == XLAlignmentHorizontalValues.Distributed - )) - { - throw new ArgumentException( - "For indents, only left, right, and distributed horizontal alignments are supported."); - } - - _indent = value; + throw new ArgumentException( + "For indents, only left, right, and distributed horizontal alignments are supported."); } } + Modify(k => { k.Indent = value; return k; }); } } public Boolean JustifyLastLine { - get { return _justifyLastLine; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.JustifyLastLine = value); - else - _justifyLastLine = value; - } + get { return Key.JustifyLastLine; } + set { Modify(k => { k.JustifyLastLine = value; return k; }); } } public XLAlignmentReadingOrderValues ReadingOrder { - get { return _readingOrder; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.ReadingOrder = value); - else - _readingOrder = value; - } + get { return Key.ReadingOrder; } + set { Modify(k => { k.ReadingOrder = value; return k; }); } } public Int32 RelativeIndent { - get { return _relativeIndent; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.RelativeIndent = value); - else - _relativeIndent = value; - } + get { return Key.RelativeIndent; } + set { Modify(k => { k.RelativeIndent = value; return k; }); } } public Boolean ShrinkToFit { - get { return _shrinkToFit; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.ShrinkToFit = value); - else - _shrinkToFit = value; - } + get { return Key.ShrinkToFit; } + set { Modify(k => { k.ShrinkToFit = value; return k; }); } } public Int32 TextRotation { - get { return _textRotation; } + get { return Key.TextRotation; } set { - SetStyleChanged(); Int32 rotation = value; if (rotation != 255 && (rotation < -90 || rotation > 180)) throw new ArgumentException("TextRotation must be between -90 and 180 degrees, or 255."); - if (rotation < 0) - rotation = 90 + (rotation * -1); - - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.TextRotation = rotation); - else - _textRotation = rotation; + Modify(k => { k.TextRotation = rotation; return k; }); } } public Boolean WrapText { - get { return _wrapText; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.WrapText = value); - else - _wrapText = value; - } + get { return Key.WrapText; } + set { Modify(k => { k.WrapText = value; return k; }); } } public Boolean TopToBottom { - get { return _textRotation == 255; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.TextRotation = value ? 255 : 0); - else - _textRotation = value ? 255 : 0; - } - } - - - public bool Equals(IXLAlignment other) - { - if (other == null) - return false; - - var otherA = other as XLAlignment; - if (otherA == null) - return false; - - return - _horizontal == otherA._horizontal - && _vertical == otherA._vertical - && _indent == otherA._indent - && _justifyLastLine == otherA._justifyLastLine - && _readingOrder == otherA._readingOrder - && _relativeIndent == otherA._relativeIndent - && _shrinkToFit == otherA._shrinkToFit - && _textRotation == otherA._textRotation - && _wrapText == otherA._wrapText - ; + get { return TextRotation == 255; } + set { TextRotation = value ? 255 : 0; } } public IXLStyle SetHorizontal(XLAlignmentHorizontalValues value) { Horizontal = value; - return _container.Style; + return _style; } public IXLStyle SetVertical(XLAlignmentVerticalValues value) { Vertical = value; - return _container.Style; + return _style; } public IXLStyle SetIndent(Int32 value) { Indent = value; - return _container.Style; + return _style; } public IXLStyle SetJustifyLastLine() { JustifyLastLine = true; - return _container.Style; + return _style; } public IXLStyle SetJustifyLastLine(Boolean value) { JustifyLastLine = value; - return _container.Style; + return _style; } public IXLStyle SetReadingOrder(XLAlignmentReadingOrderValues value) { ReadingOrder = value; - return _container.Style; + return _style; } public IXLStyle SetRelativeIndent(Int32 value) { RelativeIndent = value; - return _container.Style; + return _style; } public IXLStyle SetShrinkToFit() { ShrinkToFit = true; - return _container.Style; + return _style; } public IXLStyle SetShrinkToFit(Boolean value) { ShrinkToFit = value; - return _container.Style; + return _style; } public IXLStyle SetTextRotation(Int32 value) { TextRotation = value; - return _container.Style; + return _style; } public IXLStyle SetWrapText() { WrapText = true; - return _container.Style; + return _style; } public IXLStyle SetWrapText(Boolean value) { WrapText = value; - return _container.Style; + return _style; } public IXLStyle SetTopToBottom() { TopToBottom = true; - return _container.Style; + return _style; } public IXLStyle SetTopToBottom(Boolean value) { TopToBottom = value; - return _container.Style; + return _style; } #endregion - private void SetStyleChanged() + private void Modify(Func modification) { - if (_container != null) _container.StyleChanged = true; + Key = modification(Key); + + _style.Modify(styleKey => + { + var align = styleKey.Alignment; + styleKey.Alignment = modification(align); + return styleKey; + }); } + #region Overridden + public override string ToString() { var sb = new StringBuilder(); @@ -354,20 +303,25 @@ public override bool Equals(object obj) { - return Equals((XLAlignment)obj); + return Equals(obj as XLAlignment); + } + + public bool Equals(IXLAlignment other) + { + var otherA = other as XLAlignment; + if (otherA == null) + return false; + + return Key == otherA.Key; } public override int GetHashCode() { - return (Int32)Horizontal - ^ (Int32)Vertical - ^ Indent - ^ JustifyLastLine.GetHashCode() - ^ (Int32)ReadingOrder - ^ RelativeIndent - ^ ShrinkToFit.GetHashCode() - ^ TextRotation - ^ WrapText.GetHashCode(); + var hashCode = 1214962009; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; } + + #endregion Overridden } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/Style/XLAlignmentKey.cs b/ClosedXML/Excel/Style/XLAlignmentKey.cs new file mode 100644 index 0000000..5367ec6 --- /dev/null +++ b/ClosedXML/Excel/Style/XLAlignmentKey.cs @@ -0,0 +1,78 @@ +using System; + +namespace ClosedXML.Excel +{ + public struct XLAlignmentKey : IEquatable + { + public XLAlignmentHorizontalValues Horizontal { get; set; } + + public XLAlignmentVerticalValues Vertical { get; set; } + + public int Indent { get; set; } + + public bool JustifyLastLine { get; set; } + + public XLAlignmentReadingOrderValues ReadingOrder { get; set; } + + public int RelativeIndent { get; set; } + + public bool ShrinkToFit { get; set; } + + public int TextRotation { get; set; } + + public bool WrapText { get; set; } + + public bool TopToBottom { get; set; } + + public bool Equals(XLAlignmentKey other) + { + return + Horizontal == other.Horizontal + && Vertical == other.Vertical + && Indent == other.Indent + && JustifyLastLine == other.JustifyLastLine + && ReadingOrder == other.ReadingOrder + && RelativeIndent == other.RelativeIndent + && ShrinkToFit == other.ShrinkToFit + && TextRotation == other.TextRotation + && WrapText == other.WrapText + && TopToBottom == other.TopToBottom; + } + + public override bool Equals(object obj) + { + if (obj is XLAlignment) + return Equals((XLAlignment)obj); + return base.Equals(obj); + } + + public override int GetHashCode() + { + var hashCode = -596887160; + hashCode = hashCode * -1521134295 + Horizontal.GetHashCode(); + hashCode = hashCode * -1521134295 + Vertical.GetHashCode(); + hashCode = hashCode * -1521134295 + Indent.GetHashCode(); + hashCode = hashCode * -1521134295 + JustifyLastLine.GetHashCode(); + hashCode = hashCode * -1521134295 + ReadingOrder.GetHashCode(); + hashCode = hashCode * -1521134295 + RelativeIndent.GetHashCode(); + hashCode = hashCode * -1521134295 + ShrinkToFit.GetHashCode(); + hashCode = hashCode * -1521134295 + TextRotation.GetHashCode(); + hashCode = hashCode * -1521134295 + WrapText.GetHashCode(); + hashCode = hashCode * -1521134295 + TopToBottom.GetHashCode(); + return hashCode; + } + + public override string ToString() + { + return + $"{Horizontal} {Vertical} {ReadingOrder} Indent: {Indent} RelativeIndent: {RelativeIndent} TextRotation: {TextRotation} " + + (WrapText ? "WrapText" : "") + + (JustifyLastLine ? "JustifyLastLine" : "") + + (TopToBottom ? "TopToBottom" : ""); + } + + public static bool operator ==(XLAlignmentKey left, XLAlignmentKey right) => left.Equals(right); + + public static bool operator !=(XLAlignmentKey left, XLAlignmentKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLAlignmentValue.cs b/ClosedXML/Excel/Style/XLAlignmentValue.cs new file mode 100644 index 0000000..0d8655d --- /dev/null +++ b/ClosedXML/Excel/Style/XLAlignmentValue.cs @@ -0,0 +1,66 @@ +using ClosedXML.Excel.Caching; + +namespace ClosedXML.Excel +{ + public class XLAlignmentValue + { + private static readonly XLAlignmentRepository Repository = new XLAlignmentRepository(key => new XLAlignmentValue(key)); + + public static XLAlignmentValue FromKey(XLAlignmentKey key) + { + return Repository.GetOrCreate(key); + } + + internal static readonly XLAlignmentValue Default = FromKey(new XLAlignmentKey + { + Indent = 0, + Horizontal = XLAlignmentHorizontalValues.General, + JustifyLastLine = false, + ReadingOrder = XLAlignmentReadingOrderValues.ContextDependent, + RelativeIndent = 0, + ShrinkToFit = false, + TextRotation = 0, + Vertical = XLAlignmentVerticalValues.Bottom, + WrapText = false + }); + + public XLAlignmentKey Key { get; private set; } + + public XLAlignmentHorizontalValues Horizontal { get { return Key.Horizontal; } } + + public XLAlignmentVerticalValues Vertical { get { return Key.Vertical; } } + + public int Indent { get { return Key.Indent; } } + + public bool JustifyLastLine { get { return Key.JustifyLastLine; } } + + public XLAlignmentReadingOrderValues ReadingOrder { get { return Key.ReadingOrder; } } + + public int RelativeIndent { get { return Key.RelativeIndent; } } + + public bool ShrinkToFit { get { return Key.ShrinkToFit; } } + + public int TextRotation { get { return Key.TextRotation; } } + + public bool WrapText { get { return Key.WrapText; } } + + public bool TopToBottom { get { return Key.TopToBottom; } } + + private XLAlignmentValue(XLAlignmentKey key) + { + Key = key; + } + + public override bool Equals(object obj) + { + var cached = obj as XLAlignmentValue; + return cached != null && + Key.Equals(cached.Key); + } + + public override int GetHashCode() + { + return 990326508 + Key.GetHashCode(); + } + } +} diff --git a/ClosedXML/Excel/Style/XLBorder.cs b/ClosedXML/Excel/Style/XLBorder.cs index afc1ccb..051b049 100644 --- a/ClosedXML/Excel/Style/XLBorder.cs +++ b/ClosedXML/Excel/Style/XLBorder.cs @@ -1,80 +1,102 @@ using System; +using System.Collections.Generic; using System.Text; namespace ClosedXML.Excel { - using System.Collections.Generic; - internal class XLBorder : IXLBorder { - private readonly IXLStylized _container; - private XLBorderStyleValues _bottomBorder; - private XLColor _bottomBorderColor; - private XLBorderStyleValues _diagonalBorder; - private XLColor _diagonalBorderColor; - private Boolean _diagonalDown; - private Boolean _diagonalUp; - private XLBorderStyleValues _leftBorder; - private XLColor _leftBorderColor; - private XLBorderStyleValues _rightBorder; - private XLColor _rightBorderColor; - private XLBorderStyleValues _topBorder; - private XLColor _topBorderColor; + #region Static members - public XLBorder() : this(null, XLWorkbook.DefaultStyle.Border) + internal static XLBorderKey GenerateKey(IXLBorder defaultBorder) { + XLBorderKey key; + if (defaultBorder == null) + { + key = XLBorderValue.Default.Key; + } + else if (defaultBorder is XLBorder) + { + key = (defaultBorder as XLBorder).Key; + } + else + { + key = new XLBorderKey + { + LeftBorder = defaultBorder.LeftBorder, + LeftBorderColor = defaultBorder.LeftBorderColor.Key, + RightBorder = defaultBorder.RightBorder, + RightBorderColor = defaultBorder.RightBorderColor.Key, + TopBorder = defaultBorder.TopBorder, + TopBorderColor = defaultBorder.TopBorderColor.Key, + BottomBorder = defaultBorder.BottomBorder, + BottomBorderColor = defaultBorder.BottomBorderColor.Key, + DiagonalBorder = defaultBorder.DiagonalBorder, + DiagonalBorderColor = defaultBorder.DiagonalBorderColor.Key, + DiagonalUp = defaultBorder.DiagonalUp, + DiagonalDown = defaultBorder.DiagonalDown, + }; + } + return key; } - public XLBorder(IXLStylized container, IXLBorder defaultBorder, Boolean useDefaultModify = true) + #endregion Static members + + private readonly XLStyle _style; + + private readonly IXLStylized _container; + + private XLBorderValue _value; + + internal XLBorderKey Key + { + get { return _value.Key; } + private set { _value = XLBorderValue.FromKey(value); } + } + + #region Constructors + + /// + /// Create an instance of XLBorder initializing it with the specified value. + /// + /// Container the border is applied to. + /// Style to attach the new instance to. + /// Style value to use. + public XLBorder(IXLStylized container, XLStyle style, XLBorderValue value) { _container = container; - if (defaultBorder == null) return; - - _leftBorder = defaultBorder.LeftBorder; - _leftBorderColor = defaultBorder.LeftBorderColor; - _rightBorder = defaultBorder.RightBorder; - _rightBorderColor = defaultBorder.RightBorderColor; - _topBorder = defaultBorder.TopBorder; - _topBorderColor = defaultBorder.TopBorderColor; - _bottomBorder = defaultBorder.BottomBorder; - _bottomBorderColor = defaultBorder.BottomBorderColor; - _diagonalBorder = defaultBorder.DiagonalBorder; - _diagonalBorderColor = defaultBorder.DiagonalBorderColor; - _diagonalUp = defaultBorder.DiagonalUp; - _diagonalDown = defaultBorder.DiagonalDown; - - if (useDefaultModify) - { - var d = defaultBorder as XLBorder; - BottomBorderColorModified = d.BottomBorderColorModified; - BottomBorderModified = d.BottomBorderModified; - DiagonalBorderColorModified = d.DiagonalBorderColorModified; - DiagonalBorderModified = d.DiagonalBorderModified; - DiagonalDownModified = d.DiagonalDownModified; - DiagonalUpModified = d.DiagonalUpModified; - LeftBorderColorModified = d.LeftBorderColorModified; - LeftBorderModified = d.LeftBorderModified; - RightBorderColorModified = d.RightBorderColorModified; - RightBorderModified = d.RightBorderModified; - TopBorderColorModified = d.TopBorderColorModified; - TopBorderModified = d.TopBorderModified; - } + _style = style ?? _container.Style as XLStyle ?? XLStyle.CreateEmptyStyle(); + _value = value; } + public XLBorder(IXLStylized container, XLStyle style, XLBorderKey key) : this(container, style, XLBorderValue.FromKey(key)) + { + } + + public XLBorder(IXLStylized container, XLStyle style = null, IXLBorder d = null) : this(container, style, GenerateKey(d)) + { + } + + #endregion Constructors + #region IXLBorder Members public XLBorderStyleValues OutsideBorder { set { - if (_container == null || _container.UpdatingStyle) return; + if (_container == null) return; if (_container is XLWorksheet || _container is XLConditionalFormat) { - _container.Style.Border.SetTopBorder(value); - _container.Style.Border.SetBottomBorder(value); - _container.Style.Border.SetLeftBorder(value); - _container.Style.Border.SetRightBorder(value); + Modify(k => + { + k.TopBorder = value; + k.BottomBorder = value; + k.LeftBorder = value; + k.RightBorder = value; + return k; + }); } else { @@ -89,19 +111,22 @@ } } - public XLColor OutsideBorderColor { set { - if (_container == null || _container.UpdatingStyle) return; + if (_container == null) return; if (_container is XLWorksheet || _container is XLConditionalFormat) { - _container.Style.Border.SetTopBorderColor(value); - _container.Style.Border.SetBottomBorderColor(value); - _container.Style.Border.SetLeftBorderColor(value); - _container.Style.Border.SetRightBorderColor(value); + Modify(k => + { + k.TopBorderColor = value.Key; + k.BottomBorderColor = value.Key; + k.LeftBorderColor = value.Key; + k.RightBorderColor = value.Key; + return k; + }); } else { @@ -120,18 +145,19 @@ { set { - if (_container == null || _container.UpdatingStyle) return; + if (_container == null) return; var wsContainer = _container as XLWorksheet; if (wsContainer != null) { - //wsContainer.CellsUsed().Style.Border.SetOutsideBorder(value); - //wsContainer.UpdatingStyle = true; - wsContainer.Style.Border.SetTopBorder(value); - wsContainer.Style.Border.SetBottomBorder(value); - wsContainer.Style.Border.SetLeftBorder(value); - wsContainer.Style.Border.SetRightBorder(value); - //wsContainer.UpdatingStyle = false; + Modify(k => + { + k.TopBorder = value; + k.BottomBorder = value; + k.LeftBorder = value; + k.RightBorder = value; + return k; + }); } else { @@ -177,18 +203,19 @@ { set { - if (_container == null || _container.UpdatingStyle) return; + if (_container == null) return; var wsContainer = _container as XLWorksheet; if (wsContainer != null) { - //wsContainer.CellsUsed().Style.Border.SetOutsideBorderColor(value); - //wsContainer.UpdatingStyle = true; - wsContainer.Style.Border.SetTopBorderColor(value); - wsContainer.Style.Border.SetBottomBorderColor(value); - wsContainer.Style.Border.SetLeftBorderColor(value); - wsContainer.Style.Border.SetRightBorderColor(value); - //wsContainer.UpdatingStyle = false; + Modify(k => + { + k.TopBorderColor = value.Key; + k.BottomBorderColor = value.Key; + k.LeftBorderColor = value.Key; + k.RightBorderColor = value.Key; + return k; + }); } else { @@ -237,227 +264,106 @@ } } - public Boolean LeftBorderModified; public XLBorderStyleValues LeftBorder { - get { return _leftBorder; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.LeftBorder = value); - else - { - _leftBorder = value; - LeftBorderModified = true; - } - } + get { return Key.LeftBorder; } + set { Modify(k => { k.LeftBorder = value; return k; }); } } - public Boolean LeftBorderColorModified; public XLColor LeftBorderColor { - get { return _leftBorderColor; } + get { return XLColor.FromKey(Key.LeftBorderColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.LeftBorderColor = value); - else - { - _leftBorderColor = value; - LeftBorderColorModified = true; - } + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + + Modify(k => { k.LeftBorderColor = value.Key; return k; }); } } - public Boolean RightBorderModified; public XLBorderStyleValues RightBorder { - get { return _rightBorder; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.RightBorder = value); - else - { - _rightBorder = value; - RightBorderModified = true; - } - } + get { return Key.RightBorder; } + set { Modify(k => { k.RightBorder = value; return k; }); } } - public Boolean RightBorderColorModified; public XLColor RightBorderColor { - get { return _rightBorderColor; } + get { return XLColor.FromKey(Key.RightBorderColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.RightBorderColor = value); - else - { - _rightBorderColor = value; - RightBorderColorModified = true; - } + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + + Modify(k => { k.RightBorderColor = value.Key; return k; }); } } - public Boolean TopBorderModified; public XLBorderStyleValues TopBorder { - get { return _topBorder; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.TopBorder = value); - else - { - _topBorder = value; - TopBorderModified = true; - } - } + get { return Key.TopBorder; } + set { Modify(k => { k.TopBorder = value; return k; }); } } - public Boolean TopBorderColorModified; public XLColor TopBorderColor { - get { return _topBorderColor; } + get { return XLColor.FromKey(Key.TopBorderColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.TopBorderColor = value); - else - { - _topBorderColor = value; - TopBorderColorModified = true; - } + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + + Modify(k => { k.TopBorderColor = value.Key; return k; }); } } - public Boolean BottomBorderModified; public XLBorderStyleValues BottomBorder { - get { return _bottomBorder; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.BottomBorder = value); - else - { - _bottomBorder = value; - BottomBorderModified = true; - } - } + get { return Key.BottomBorder; } + set { Modify(k => { k.BottomBorder = value; return k; }); } } - public Boolean BottomBorderColorModified; public XLColor BottomBorderColor { - get { return _bottomBorderColor; } + get { return XLColor.FromKey(Key.BottomBorderColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.BottomBorderColor = value); - else - { - _bottomBorderColor = value; - BottomBorderColorModified = true; - } + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + + Modify(k => { k.BottomBorderColor = value.Key; return k; }); } } - public Boolean DiagonalBorderModified; public XLBorderStyleValues DiagonalBorder { - get { return _diagonalBorder; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.DiagonalBorder = value); - else - { - _diagonalBorder = value; - DiagonalBorderModified = true; - } - } + get { return Key.DiagonalBorder; } + set { Modify(k => { k.DiagonalBorder = value; return k; }); } } - public Boolean DiagonalBorderColorModified; public XLColor DiagonalBorderColor { - get { return _diagonalBorderColor; } + get { return XLColor.FromKey(Key.DiagonalBorderColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.DiagonalBorderColor = value); - else - { - _diagonalBorderColor = value; - DiagonalBorderColorModified = true; - } + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + + Modify(k => { k.DiagonalBorderColor = value.Key; return k; }); } } - public Boolean DiagonalUpModified; public Boolean DiagonalUp { - get { return _diagonalUp; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.DiagonalUp = value); - else - { - _diagonalUp = value; - DiagonalUpModified = true; - } - } + get { return Key.DiagonalUp; } + set { Modify(k => { k.DiagonalUp = value; return k; }); } } - public Boolean DiagonalDownModified; public Boolean DiagonalDown { - get { return _diagonalDown; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Border.DiagonalDown = value); - else - { - _diagonalDown = value; - DiagonalDownModified = true; - } - } - } - - public bool Equals(IXLBorder other) - { - var otherB = other as XLBorder; - return - _leftBorder == otherB._leftBorder - && _leftBorderColor.Equals(otherB._leftBorderColor) - && _rightBorder == otherB._rightBorder - && _rightBorderColor.Equals(otherB._rightBorderColor) - && _topBorder == otherB._topBorder - && _topBorderColor.Equals(otherB._topBorderColor) - && _bottomBorder == otherB._bottomBorder - && _bottomBorderColor.Equals(otherB._bottomBorderColor) - && _diagonalBorder == otherB._diagonalBorder - && _diagonalBorderColor.Equals(otherB._diagonalBorderColor) - && _diagonalUp == otherB._diagonalUp - && _diagonalDown == otherB._diagonalDown - ; + get { return Key.DiagonalDown; } + set { Modify(k => { k.DiagonalDown = value; return k; }); } } public IXLStyle SetOutsideBorder(XLBorderStyleValues value) @@ -568,13 +474,22 @@ return _container.Style; } - #endregion + #endregion IXLBorder Members - private void SetStyleChanged() + private void Modify(Func modification) { - if (_container != null) _container.StyleChanged = true; + Key = modification(Key); + + _style.Modify(styleKey => + { + var border = styleKey.Border; + styleKey.Border = modification(border); + return styleKey; + }); } + #region Overridden + public override string ToString() { var sb = new StringBuilder(); @@ -606,23 +521,25 @@ public override bool Equals(object obj) { - return Equals((XLBorder)obj); + return Equals(obj as XLBorder); + } + + public bool Equals(IXLBorder other) + { + var otherB = other as XLBorder; + if (otherB == null) + return false; + + return Key == otherB.Key; } public override int GetHashCode() { - return (Int32)LeftBorder - ^ LeftBorderColor.GetHashCode() - ^ (Int32)RightBorder - ^ RightBorderColor.GetHashCode() - ^ (Int32)TopBorder - ^ TopBorderColor.GetHashCode() - ^ (Int32)BottomBorder - ^ BottomBorderColor.GetHashCode() - ^ (Int32)DiagonalBorder - ^ DiagonalBorderColor.GetHashCode() - ^ DiagonalUp.GetHashCode() - ^ DiagonalDown.GetHashCode(); + var hashCode = 416600561; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; } + + #endregion Overridden } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/Style/XLBorderKey.cs b/ClosedXML/Excel/Style/XLBorderKey.cs new file mode 100644 index 0000000..0251dfa --- /dev/null +++ b/ClosedXML/Excel/Style/XLBorderKey.cs @@ -0,0 +1,97 @@ +using System; + +namespace ClosedXML.Excel +{ + internal struct XLBorderKey : IEquatable + { + public XLBorderStyleValues LeftBorder { get; set; } + + public XLColorKey LeftBorderColor { get; set; } + + public XLBorderStyleValues RightBorder { get; set; } + + public XLColorKey RightBorderColor { get; set; } + + public XLBorderStyleValues TopBorder { get; set; } + + public XLColorKey TopBorderColor { get; set; } + + public XLBorderStyleValues BottomBorder { get; set; } + + public XLColorKey BottomBorderColor { get; set; } + + public XLBorderStyleValues DiagonalBorder { get; set; } + + public XLColorKey DiagonalBorderColor { get; set; } + + public bool DiagonalUp { get; set; } + + public bool DiagonalDown { get; set; } + + public override int GetHashCode() + { + var hashCode = -198124310; + hashCode = hashCode * -1521134295 + LeftBorder.GetHashCode(); + hashCode = hashCode * -1521134295 + RightBorder.GetHashCode(); + hashCode = hashCode * -1521134295 + TopBorder.GetHashCode(); + hashCode = hashCode * -1521134295 + BottomBorder.GetHashCode(); + hashCode = hashCode * -1521134295 + DiagonalBorder.GetHashCode(); + hashCode = hashCode * -1521134295 + DiagonalUp.GetHashCode(); + hashCode = hashCode * -1521134295 + DiagonalDown.GetHashCode(); + + if (LeftBorder != XLBorderStyleValues.None) + hashCode = hashCode * -1521134295 + LeftBorderColor.GetHashCode(); + if (RightBorder != XLBorderStyleValues.None) + hashCode = hashCode * -1521134295 + RightBorderColor.GetHashCode(); + if (TopBorder != XLBorderStyleValues.None) + hashCode = hashCode * -1521134295 + TopBorderColor.GetHashCode(); + if (BottomBorder != XLBorderStyleValues.None) + hashCode = hashCode * -1521134295 + BottomBorderColor.GetHashCode(); + if (DiagonalBorder != XLBorderStyleValues.None) + hashCode = hashCode * -1521134295 + DiagonalBorderColor.GetHashCode(); + + return hashCode; + } + + public bool Equals(XLBorderKey other) + { + return + AreEquivalent(LeftBorder, LeftBorderColor, other.LeftBorder, other.LeftBorderColor) + && AreEquivalent(RightBorder, RightBorderColor, other.RightBorder, other.RightBorderColor) + && AreEquivalent(TopBorder, TopBorderColor, other.TopBorder, other.TopBorderColor) + && AreEquivalent(BottomBorder, BottomBorderColor, other.BottomBorder, other.BottomBorderColor) + && AreEquivalent(DiagonalBorder, DiagonalBorderColor, other.DiagonalBorder, other.DiagonalBorderColor) + && DiagonalUp == other.DiagonalUp + && DiagonalDown == other.DiagonalDown; + } + + private bool AreEquivalent( + XLBorderStyleValues borderStyle1, XLColorKey color1, + XLBorderStyleValues borderStyle2, XLColorKey color2) + { + return (borderStyle1 == XLBorderStyleValues.None && + borderStyle2 == XLBorderStyleValues.None) || + borderStyle1 == borderStyle2 && + color1 == color2; + } + + public override bool Equals(object obj) + { + if (obj is XLBorderKey) + return Equals((XLBorderKey)obj); + return base.Equals(obj); + } + + public override string ToString() + { + return $"{LeftBorder} {LeftBorderColor} {RightBorder} {RightBorderColor} {TopBorder} {TopBorderColor} " + + $"{BottomBorder} {BottomBorderColor} {DiagonalBorder} {DiagonalBorderColor} " + + (DiagonalUp ? "DiagonalUp" : "") + + (DiagonalDown ? "DiagonalDown" : ""); + } + + public static bool operator ==(XLBorderKey left, XLBorderKey right) => left.Equals(right); + + public static bool operator !=(XLBorderKey left, XLBorderKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLBorderValue.cs b/ClosedXML/Excel/Style/XLBorderValue.cs new file mode 100644 index 0000000..7c1f8da --- /dev/null +++ b/ClosedXML/Excel/Style/XLBorderValue.cs @@ -0,0 +1,79 @@ +using ClosedXML.Excel.Caching; + +namespace ClosedXML.Excel +{ + internal class XLBorderValue + { + private static readonly XLBorderRepository Repository = new XLBorderRepository(key => new XLBorderValue(key)); + + public static XLBorderValue FromKey(XLBorderKey key) + { + return Repository.GetOrCreate(key); + } + + internal static readonly XLBorderValue Default = FromKey(new XLBorderKey + { + BottomBorder = XLBorderStyleValues.None, + DiagonalBorder = XLBorderStyleValues.None, + DiagonalDown = false, + DiagonalUp = false, + LeftBorder = XLBorderStyleValues.None, + RightBorder = XLBorderStyleValues.None, + TopBorder = XLBorderStyleValues.None, + BottomBorderColor = XLColor.Black.Key, + DiagonalBorderColor = XLColor.Black.Key, + LeftBorderColor = XLColor.Black.Key, + RightBorderColor = XLColor.Black.Key, + TopBorderColor = XLColor.Black.Key + }); + + public XLBorderKey Key { get; private set; } + + public XLBorderStyleValues LeftBorder { get { return Key.LeftBorder; } } + + public XLColor LeftBorderColor { get; private set; } + + public XLBorderStyleValues RightBorder { get { return Key.RightBorder; } } + + public XLColor RightBorderColor { get; private set; } + + public XLBorderStyleValues TopBorder { get { return Key.TopBorder; } } + + public XLColor TopBorderColor { get; private set; } + + public XLBorderStyleValues BottomBorder { get { return Key.BottomBorder; } } + + public XLColor BottomBorderColor { get; private set; } + + public XLBorderStyleValues DiagonalBorder { get { return Key.DiagonalBorder; } } + + public XLColor DiagonalBorderColor { get; private set; } + + public bool DiagonalUp { get { return Key.DiagonalUp; } } + + public bool DiagonalDown { get { return Key.DiagonalDown; } } + + private XLBorderValue(XLBorderKey key) + { + Key = key; + + LeftBorderColor = XLColor.FromKey(Key.LeftBorderColor); + RightBorderColor = XLColor.FromKey(Key.RightBorderColor); + TopBorderColor = XLColor.FromKey(Key.TopBorderColor); + BottomBorderColor = XLColor.FromKey(Key.BottomBorderColor); + DiagonalBorderColor = XLColor.FromKey(Key.DiagonalBorderColor); + } + + public override bool Equals(object obj) + { + var cached = obj as XLBorderValue; + return cached != null && + Key.Equals(cached.Key); + } + + public override int GetHashCode() + { + return -280332839 + Key.GetHashCode(); + } + } +} diff --git a/ClosedXML/Excel/Style/XLColorKey.cs b/ClosedXML/Excel/Style/XLColorKey.cs new file mode 100644 index 0000000..2484ecf --- /dev/null +++ b/ClosedXML/Excel/Style/XLColorKey.cs @@ -0,0 +1,76 @@ +using System; + +namespace ClosedXML.Excel +{ + internal struct XLColorKey : IEquatable + { + public XLColorType ColorType { get; set; } + + public System.Drawing.Color Color { get; set; } + + public int Indexed { get; set; } + + public XLThemeColor ThemeColor { get; set; } + + public double ThemeTint { get; set; } + + public override int GetHashCode() + { + var hashCode = -331517974; + hashCode = hashCode * -1521134295 + ColorType.GetHashCode(); + hashCode = hashCode * -1521134295 + (ColorType == XLColorType.Indexed ? Indexed.GetHashCode() : 0); + hashCode = hashCode * -1521134295 + (ColorType == XLColorType.Theme ? ThemeColor.GetHashCode() : 0); + hashCode = hashCode * -1521134295 + (ColorType == XLColorType.Theme ? ThemeTint.GetHashCode() : 0); + hashCode = hashCode * -1521134295 + (ColorType == XLColorType.Color ? Color.ToArgb().GetHashCode() : 0); + return hashCode; + } + + public bool Equals(XLColorKey other) + { + if (ColorType == other.ColorType) + { + if (ColorType == XLColorType.Color) + { + // .NET Color.Equals() will return false for Color.FromArgb(255, 255, 255, 255) == Color.White + // Therefore we compare the ToArgb() values + return Color.ToArgb() == other.Color.ToArgb(); + } + if (ColorType == XLColorType.Theme) + { + return + ThemeColor == other.ThemeColor + && Math.Abs(ThemeTint - other.ThemeTint) < XLHelper.Epsilon; + } + return Indexed == other.Indexed; + } + + return false; + } + + public override bool Equals(object obj) + { + if (obj is XLColorKey) + return Equals((XLColorKey)obj); + return base.Equals(obj); + } + + public override string ToString() + { + switch (ColorType) + { + case XLColorType.Color: + return Color.ToString(); + case XLColorType.Theme: + return $"{ThemeColor} ({ThemeTint})"; + case XLColorType.Indexed: + return $"Indexed: {Indexed}"; + default: + return base.ToString(); + } + } + + public static bool operator ==(XLColorKey left, XLColorKey right) => left.Equals(right); + + public static bool operator !=(XLColorKey left, XLColorKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLFill.cs b/ClosedXML/Excel/Style/XLFill.cs index d7155af..12f39f7 100644 --- a/ClosedXML/Excel/Style/XLFill.cs +++ b/ClosedXML/Excel/Style/XLFill.cs @@ -5,142 +5,163 @@ { internal class XLFill : IXLFill { - #region IXLFill Members + #region static members - public bool Equals(IXLFill other) + internal static XLFillKey GenerateKey(IXLFill defaultFill) { - return - _patternType == other.PatternType - && _backgroundColor.Equals(other.BackgroundColor) - && _patternColor.Equals(other.PatternColor) - ; + XLFillKey key; + if (defaultFill == null) + { + key = XLFillValue.Default.Key; + } + else if (defaultFill is XLFill) + { + key = (defaultFill as XLFill).Key; + } + else + { + key = new XLFillKey + { + PatternType = defaultFill.PatternType, + BackgroundColor = defaultFill.BackgroundColor.Key, + PatternColor = defaultFill.PatternColor.Key + }; + } + return key; } - #endregion IXLFill Members - - private void SetStyleChanged() - { - if (_container != null) _container.StyleChanged = true; - } - - public override bool Equals(object obj) - { - return Equals((XLFill)obj); - } - - public override int GetHashCode() - { - return BackgroundColor.GetHashCode() - ^ (Int32)PatternType - ^ PatternColor.GetHashCode(); - } + #endregion static members #region Properties - private XLColor _backgroundColor; - private XLColor _patternColor; - private XLFillPatternValues _patternType; + private readonly XLStyle _style; - public XLColor BackgroundColor - { - get { return _backgroundColor; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Fill.BackgroundColor = value); - else - { - // 4 ways of determining an "empty" color - if (new XLFillPatternValues[] { XLFillPatternValues.None, XLFillPatternValues.Solid }.Contains(_patternType) - && (_backgroundColor == null - || !_backgroundColor.HasValue - || _backgroundColor == XLColor.NoColor - || _backgroundColor.ColorType == XLColorType.Indexed && _backgroundColor.Indexed == 64)) - { - _patternType = value.HasValue ? XLFillPatternValues.Solid : XLFillPatternValues.None; - } - _backgroundColor = value; - } - } - } + private XLFillValue _value; - public XLColor PatternColor + internal XLFillKey Key { - get { return _patternColor; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Fill.PatternColor = value); - else - { - _patternColor = value; - } - } - } - - public XLFillPatternValues PatternType - { - get { return _patternType; } - set - { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Fill.PatternType = value); - else - { - _patternType = value; - } - } - } - - public IXLStyle SetBackgroundColor(XLColor value) - { - BackgroundColor = value; - return _container.Style; - } - - public IXLStyle SetPatternColor(XLColor value) - { - PatternColor = value; - return _container.Style; - } - - public IXLStyle SetPatternType(XLFillPatternValues value) - { - PatternType = value; - return _container.Style; + get { return _value.Key; } + private set { _value = XLFillValue.FromKey(value); } } #endregion Properties #region Constructors - private readonly IXLStylized _container; + /// + /// Create an instance of XLFill initializing it with the specified value. + /// + /// Style to attach the new instance to. + /// Style value to use. + public XLFill(XLStyle style, XLFillValue value) + { + _style = style ?? XLStyle.CreateEmptyStyle(); + _value = value; + } - public XLFill() : this(null, XLWorkbook.DefaultStyle.Fill) + public XLFill(XLStyle style, XLFillKey key) : this(style, XLFillValue.FromKey(key)) { } - public XLFill(IXLStylized container, IXLFill defaultFill = null, Boolean useDefaultModify = true) + public XLFill(XLStyle style = null, IXLFill d = null) : this(style, GenerateKey(d)) { - _container = container; - if (defaultFill == null) return; - _patternType = defaultFill.PatternType; - _backgroundColor = defaultFill.BackgroundColor; - _patternColor = defaultFill.PatternColor; - - if (useDefaultModify) - { - var d = defaultFill as XLFill; - } } #endregion Constructors + private void Modify(Func modification) + { + Key = modification(Key); + + _style.Modify(styleKey => + { + var fill = styleKey.Fill; + styleKey.Fill = modification(fill); + return styleKey; + }); + } + + #region IXLFill Members + + public XLColor BackgroundColor + { + get { return XLColor.FromKey(Key.BackgroundColor); } + set + { + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + + // 4 ways of determining an "empty" color + if (new XLFillPatternValues[] { XLFillPatternValues.None, XLFillPatternValues.Solid }.Contains(PatternType) + && (BackgroundColor == null + || !BackgroundColor.HasValue + || BackgroundColor == XLColor.NoColor + || BackgroundColor.ColorType == XLColorType.Indexed && BackgroundColor.Indexed == 64)) + { + PatternType = value.HasValue ? XLFillPatternValues.Solid : XLFillPatternValues.None; + } + + Modify(k => { k.BackgroundColor = value.Key; return k; }); + } + } + + public XLColor PatternColor + { + get { return XLColor.FromKey(Key.PatternColor); } + set + { + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + + Modify(k => { k.PatternColor = value.Key; return k; }); + } + } + + public XLFillPatternValues PatternType + { + get { return Key.PatternType; } + set + { + Modify(k => { k.PatternType = value; return k; }); + } + } + + public IXLStyle SetBackgroundColor(XLColor value) + { + BackgroundColor = value; + return _style; + } + + public IXLStyle SetPatternColor(XLColor value) + { + PatternColor = value; + return _style; + } + + public IXLStyle SetPatternType(XLFillPatternValues value) + { + PatternType = value; + return _style; + } + + #endregion IXLFill Members + #region Overridden + public override bool Equals(object obj) + { + return Equals(obj as XLFill); + } + + public bool Equals(IXLFill other) + { + var otherF = other as XLFill; + if (otherF == null) + return false; + + return Key == otherF.Key; + } + public override string ToString() { switch (PatternType) @@ -156,6 +177,13 @@ } } + public override int GetHashCode() + { + var hashCode = -1938644919; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; + } + #endregion Overridden } } diff --git a/ClosedXML/Excel/Style/XLFillKey.cs b/ClosedXML/Excel/Style/XLFillKey.cs new file mode 100644 index 0000000..c2f2495 --- /dev/null +++ b/ClosedXML/Excel/Style/XLFillKey.cs @@ -0,0 +1,47 @@ +using System; + +namespace ClosedXML.Excel +{ + internal struct XLFillKey : IEquatable + { + public XLColorKey BackgroundColor { get; set; } + + public XLColorKey PatternColor { get; set; } + + public XLFillPatternValues PatternType { get; set; } + + public override int GetHashCode() + { + var hashCode = 2043579837; + hashCode = hashCode * -1521134295 + BackgroundColor.GetHashCode(); + hashCode = hashCode * -1521134295 + PatternColor.GetHashCode(); + hashCode = hashCode * -1521134295 + PatternType.GetHashCode(); + return hashCode; + } + + public bool Equals(XLFillKey other) + { + return + (PatternType == XLFillPatternValues.None && other.PatternType == XLFillPatternValues.None) || + BackgroundColor == other.BackgroundColor + && PatternColor == other.PatternColor + && PatternType == other.PatternType; + } + + public override bool Equals(object obj) + { + if (obj is XLFillKey) + return Equals((XLFillKey)obj); + return base.Equals(obj); + } + + public override string ToString() + { + return $"{PatternType} {BackgroundColor}/{PatternColor}"; + } + + public static bool operator ==(XLFillKey left, XLFillKey right) => left.Equals(right); + + public static bool operator !=(XLFillKey left, XLFillKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLFillValue.cs b/ClosedXML/Excel/Style/XLFillValue.cs new file mode 100644 index 0000000..d12d8fd --- /dev/null +++ b/ClosedXML/Excel/Style/XLFillValue.cs @@ -0,0 +1,48 @@ +using ClosedXML.Excel.Caching; + +namespace ClosedXML.Excel +{ + internal sealed class XLFillValue + { + private static readonly XLFillRepository Repository = new XLFillRepository(key => new XLFillValue(key)); + + public static XLFillValue FromKey(XLFillKey key) + { + return Repository.GetOrCreate(key); + } + + internal static readonly XLFillValue Default = FromKey(new XLFillKey + { + BackgroundColor = XLColor.FromIndex(64).Key, + PatternType = XLFillPatternValues.None, + PatternColor = XLColor.FromIndex(64).Key + }); + + public XLFillKey Key { get; private set; } + + public XLColor BackgroundColor { get; private set; } + + public XLColor PatternColor { get; private set; } + + public XLFillPatternValues PatternType { get { return Key.PatternType; } } + + private XLFillValue(XLFillKey key) + { + Key = key; + BackgroundColor = XLColor.FromKey(Key.BackgroundColor); + PatternColor = XLColor.FromKey(Key.PatternColor); + } + + public override bool Equals(object obj) + { + var cached = obj as XLFillValue; + return cached != null && + Key.Equals(cached.Key); + } + + public override int GetHashCode() + { + return -280332839 + Key.GetHashCode(); + } + } +} diff --git a/ClosedXML/Excel/Style/XLFont.cs b/ClosedXML/Excel/Style/XLFont.cs index 87915b4..0b3e572 100644 --- a/ClosedXML/Excel/Style/XLFont.cs +++ b/ClosedXML/Excel/Style/XLFont.cs @@ -5,379 +5,286 @@ { internal class XLFont : IXLFont { - private readonly IXLStylized _container; - private Boolean _bold; - private XLColor _fontColor; - private XLFontFamilyNumberingValues _fontFamilyNumbering; - private XLFontCharSet _fontCharSet; - private String _fontName; - private Double _fontSize; - private Boolean _italic; - private Boolean _shadow; - private Boolean _strikethrough; - private XLFontUnderlineValues _underline; - private XLFontVerticalTextAlignmentValues _verticalAlignment; + #region Static members - public XLFont() - : this(null, XLWorkbook.DefaultStyle.Font) + internal static XLFontKey GenerateKey(IXLFontBase defaultFont) + { + if (defaultFont == null) + { + return XLFontValue.Default.Key; + } + else if (defaultFont is XLFont) + { + return (defaultFont as XLFont).Key; + } + else + { + return new XLFontKey + { + Bold = defaultFont.Bold, + Italic = defaultFont.Italic, + Underline = defaultFont.Underline, + Strikethrough = defaultFont.Strikethrough, + VerticalAlignment = defaultFont.VerticalAlignment, + Shadow = defaultFont.Shadow, + FontSize = defaultFont.FontSize, + FontColor = defaultFont.FontColor.Key, + FontName = defaultFont.FontName, + FontFamilyNumbering = defaultFont.FontFamilyNumbering, + FontCharSet = defaultFont.FontCharSet + }; + } + } + + #endregion Static members + + private readonly XLStyle _style; + + private XLFontValue _value; + + internal XLFontKey Key + { + get { return _value.Key; } + private set { _value = XLFontValue.FromKey(value); } + } + + #region Constructors + + /// + /// Create an instance of XLFont initializing it with the specified value. + /// + /// Style to attach the new instance to. + /// Style value to use. + public XLFont(XLStyle style, XLFontValue value) + { + _style = style ?? XLStyle.CreateEmptyStyle(); + _value = value; + } + + public XLFont(XLStyle style, XLFontKey key) : this(style, XLFontValue.FromKey(key)) { } - public XLFont(IXLStylized container, IXLFontBase defaultFont, Boolean useDefaultModify = true) + public XLFont(XLStyle style = null, IXLFont d = null) : this(style, GenerateKey(d)) { - _container = container; - if (defaultFont == null) return; + } - _bold = defaultFont.Bold; - _italic = defaultFont.Italic; - _underline = defaultFont.Underline; - _strikethrough = defaultFont.Strikethrough; - _verticalAlignment = defaultFont.VerticalAlignment; - _shadow = defaultFont.Shadow; - _fontSize = defaultFont.FontSize; - _fontColor = defaultFont.FontColor; - _fontName = defaultFont.FontName; - _fontFamilyNumbering = defaultFont.FontFamilyNumbering; - _fontCharSet = defaultFont.FontCharSet; + #endregion Constructors - if (useDefaultModify) + private void Modify(Func modification) + { + Key = modification(Key); + + _style.Modify(styleKey => { - var d = defaultFont as XLFont; - if (d == null) return; - BoldModified = d.BoldModified; - ItalicModified = d.ItalicModified; - UnderlineModified = d.UnderlineModified; - StrikethroughModified = d.StrikethroughModified; - VerticalAlignmentModified = d.VerticalAlignmentModified; - ShadowModified = d.ShadowModified; - FontSizeModified = d.FontSizeModified; - FontColorModified = d.FontColorModified; - FontNameModified = d.FontNameModified; - FontFamilyNumberingModified = d.FontFamilyNumberingModified; - FontCharSetModified = d.FontCharSetModified; - } + var font = styleKey.Font; + styleKey.Font = modification(font); + return styleKey; + }); } #region IXLFont Members - public Boolean BoldModified { get; set; } public Boolean Bold { - get { return _bold; } + get { return Key.Bold; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.Bold = value); - else - { - _bold = value; - BoldModified = true; - } + Modify(k => { k.Bold = value; return k; }); } } - public Boolean ItalicModified { get; set; } public Boolean Italic { - get { return _italic; } + get { return Key.Italic; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.Italic = value); - else - { - _italic = value; - ItalicModified = true; - } + Modify(k => { k.Italic = value; return k; }); } } - public Boolean UnderlineModified { get; set; } public XLFontUnderlineValues Underline { - get { return _underline; } + get { return Key.Underline; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.Underline = value); - else - { - _underline = value; - UnderlineModified = true; - } - + Modify(k => { k.Underline = value; return k; }); } } - public Boolean StrikethroughModified { get; set; } public Boolean Strikethrough { - get { return _strikethrough; } + get { return Key.Strikethrough; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.Strikethrough = value); - else - { - _strikethrough = value; - StrikethroughModified = true; - } + Modify(k => { k.Strikethrough = value; return k; }); } } - public Boolean VerticalAlignmentModified { get; set; } public XLFontVerticalTextAlignmentValues VerticalAlignment { - get { return _verticalAlignment; } + get { return Key.VerticalAlignment; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.VerticalAlignment = value); - else - { - _verticalAlignment = value; - VerticalAlignmentModified = true; - } + Modify(k => { k.VerticalAlignment = value; return k; }); } } - public Boolean ShadowModified { get; set; } public Boolean Shadow { - get { return _shadow; } + get { return Key.Shadow; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.Shadow = value); - else - { - _shadow = value; - ShadowModified = true; - } + Modify(k => { k.Shadow = value; return k; }); } } - public Boolean FontSizeModified { get; set; } public Double FontSize { - get { return _fontSize; } + get { return Key.FontSize; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.FontSize = value); - else - { - _fontSize = value; - FontSizeModified = true; - } + Modify(k => { k.FontSize = value; return k; }); } } - private Boolean _fontColorModified; - public Boolean FontColorModified - { - get { return _fontColorModified; } - set - { - _fontColorModified = value; - } - } public XLColor FontColor { - get { return _fontColor; } + get { return XLColor.FromKey(Key.FontColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.FontColor = value); - else - { - _fontColor = value; - FontColorModified = true; - } + if (value == null) + throw new ArgumentNullException(nameof(value), "Color cannot be null"); + Modify(k => { k.FontColor = value.Key; return k; }); } } - public Boolean FontNameModified { get; set; } public String FontName { - get { return _fontName; } + get { return Key.FontName; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.FontName = value); - else - { - _fontName = value; - FontNameModified = true; - } + Modify(k => { k.FontName = value; return k; }); } } - public Boolean FontFamilyNumberingModified { get; set; } public XLFontFamilyNumberingValues FontFamilyNumbering { - get { return _fontFamilyNumbering; } + get { return Key.FontFamilyNumbering; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.FontFamilyNumbering = value); - else - { - _fontFamilyNumbering = value; - FontFamilyNumberingModified = true; - } + Modify(k => { k.FontFamilyNumbering = value; return k; }); } } - public Boolean FontCharSetModified { get; set; } public XLFontCharSet FontCharSet { - get { return _fontCharSet; } + get { return Key.FontCharSet; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Font.FontCharSet = value); - else - { - _fontCharSet = value; - FontCharSetModified = true; - } + Modify(k => { k.FontCharSet = value; return k; }); } } public IXLStyle SetBold() { Bold = true; - return _container.Style; + return _style; } public IXLStyle SetBold(Boolean value) { Bold = value; - return _container.Style; + return _style; } public IXLStyle SetItalic() { Italic = true; - return _container.Style; + return _style; } public IXLStyle SetItalic(Boolean value) { Italic = value; - return _container.Style; + return _style; } public IXLStyle SetUnderline() { Underline = XLFontUnderlineValues.Single; - return _container.Style; + return _style; } public IXLStyle SetUnderline(XLFontUnderlineValues value) { Underline = value; - return _container.Style; + return _style; } public IXLStyle SetStrikethrough() { Strikethrough = true; - return _container.Style; + return _style; } public IXLStyle SetStrikethrough(Boolean value) { Strikethrough = value; - return _container.Style; + return _style; } public IXLStyle SetVerticalAlignment(XLFontVerticalTextAlignmentValues value) { VerticalAlignment = value; - return _container.Style; + return _style; } public IXLStyle SetShadow() { Shadow = true; - return _container.Style; + return _style; } public IXLStyle SetShadow(Boolean value) { Shadow = value; - return _container.Style; + return _style; } public IXLStyle SetFontSize(Double value) { FontSize = value; - return _container.Style; + return _style; } public IXLStyle SetFontColor(XLColor value) { FontColor = value; - return _container.Style; + return _style; } public IXLStyle SetFontName(String value) { FontName = value; - return _container.Style; + return _style; } public IXLStyle SetFontFamilyNumbering(XLFontFamilyNumberingValues value) { FontFamilyNumbering = value; - return _container.Style; + return _style; } public IXLStyle SetFontCharSet(XLFontCharSet value) { FontCharSet = value; - return _container.Style; + return _style; } - public Boolean Equals(IXLFont other) - { - var otherF = other as XLFont; - if (otherF == null) - return false; + #endregion IXLFont Members - return - _bold == otherF._bold - && _italic == otherF._italic - && _underline == otherF._underline - && _strikethrough == otherF._strikethrough - && _verticalAlignment == otherF._verticalAlignment - && _shadow == otherF._shadow - && _fontSize == otherF._fontSize - && _fontColor.Equals(otherF._fontColor) - && _fontName == otherF._fontName - && _fontFamilyNumbering == otherF._fontFamilyNumbering - ; - } - - #endregion - - private void SetStyleChanged() - { - if (_container != null) _container.StyleChanged = true; - } + #region Overridden public override string ToString() { @@ -406,21 +313,25 @@ public override bool Equals(object obj) { - return Equals((XLFont)obj); + return Equals(obj as XLFont); + } + + public Boolean Equals(IXLFont other) + { + var otherF = other as XLFont; + if (otherF == null) + return false; + + return Key == otherF.Key; } public override int GetHashCode() { - return Bold.GetHashCode() - ^ Italic.GetHashCode() - ^ (Int32)Underline - ^ Strikethrough.GetHashCode() - ^ (Int32)VerticalAlignment - ^ Shadow.GetHashCode() - ^ FontSize.GetHashCode() - ^ FontColor.GetHashCode() - ^ FontName.GetHashCode() - ^ (Int32)FontFamilyNumbering; + var hashCode = 416600561; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; } + + #endregion Overridden } } diff --git a/ClosedXML/Excel/Style/XLFontKey.cs b/ClosedXML/Excel/Style/XLFontKey.cs new file mode 100644 index 0000000..37ee4a0 --- /dev/null +++ b/ClosedXML/Excel/Style/XLFontKey.cs @@ -0,0 +1,81 @@ +using System; + +namespace ClosedXML.Excel +{ + internal struct XLFontKey : IEquatable + { + public bool Bold { get; set; } + + public bool Italic { get; set; } + + public XLFontUnderlineValues Underline { get; set; } + + public bool Strikethrough { get; set; } + + public XLFontVerticalTextAlignmentValues VerticalAlignment { get; set; } + + public bool Shadow { get; set; } + + public double FontSize { get; set; } + + public XLColorKey FontColor { get; set; } + + public string FontName { get; set; } + + public XLFontFamilyNumberingValues FontFamilyNumbering { get; set; } + + public XLFontCharSet FontCharSet { get; set; } + + public bool Equals(XLFontKey other) + { + return + Bold == other.Bold + && Italic == other.Italic + && Underline == other.Underline + && Strikethrough == other.Strikethrough + && VerticalAlignment == other.VerticalAlignment + && Shadow == other.Shadow + && FontSize == other.FontSize + && FontColor == other.FontColor + && FontFamilyNumbering == other.FontFamilyNumbering + && FontCharSet == other.FontCharSet + && string.Equals(FontName, other.FontName, StringComparison.InvariantCultureIgnoreCase); + } + + public override bool Equals(object obj) + { + if (obj is XLFontKey) + return Equals((XLFontKey)obj); + return base.Equals(obj); + } + + public override int GetHashCode() + { + var hashCode = 1158783753; + hashCode = hashCode * -1521134295 + Bold.GetHashCode(); + hashCode = hashCode * -1521134295 + Italic.GetHashCode(); + hashCode = hashCode * -1521134295 + Underline.GetHashCode(); + hashCode = hashCode * -1521134295 + Strikethrough.GetHashCode(); + hashCode = hashCode * -1521134295 + VerticalAlignment.GetHashCode(); + hashCode = hashCode * -1521134295 + Shadow.GetHashCode(); + hashCode = hashCode * -1521134295 + FontSize.GetHashCode(); + hashCode = hashCode * -1521134295 + FontColor.GetHashCode(); + hashCode = hashCode * -1521134295 + FontName.ToUpperInvariant().GetHashCode(); + hashCode = hashCode * -1521134295 + FontFamilyNumbering.GetHashCode(); + hashCode = hashCode * -1521134295 + FontCharSet.GetHashCode(); + return hashCode; + } + + public override string ToString() + { + return $"{FontName} {FontSize}pt {FontColor} " + + (Bold ? "Bold" : "") + (Italic ? "Italic" : "") + (Strikethrough ? "Strikethrough" : "") + + (Underline == XLFontUnderlineValues.None ? "" : Underline.ToString()) + + $"{FontFamilyNumbering} {FontCharSet}"; + } + + public static bool operator ==(XLFontKey left, XLFontKey right) => left.Equals(right); + + public static bool operator !=(XLFontKey left, XLFontKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLFontValue.cs b/ClosedXML/Excel/Style/XLFontValue.cs new file mode 100644 index 0000000..088ca07 --- /dev/null +++ b/ClosedXML/Excel/Style/XLFontValue.cs @@ -0,0 +1,72 @@ +using ClosedXML.Excel.Caching; +using System.Collections.Generic; + +namespace ClosedXML.Excel +{ + internal sealed class XLFontValue + { + private static readonly XLFontRepository Repository = new XLFontRepository(key => new XLFontValue(key)); + + public static XLFontValue FromKey(XLFontKey key) + { + return Repository.GetOrCreate(key); + } + + internal static readonly XLFontValue Default = FromKey(new XLFontKey + { + Bold = false, + Italic = false, + Underline = XLFontUnderlineValues.None, + Strikethrough = false, + VerticalAlignment = XLFontVerticalTextAlignmentValues.Baseline, + FontSize = 11, + FontColor = XLColor.FromArgb(0, 0, 0).Key, + FontName = "Calibri", + FontFamilyNumbering = XLFontFamilyNumberingValues.Swiss, + FontCharSet = XLFontCharSet.Default + }); + + public XLFontKey Key { get; private set; } + + public bool Bold { get { return Key.Bold; } } + + public bool Italic { get { return Key.Italic; } } + + public XLFontUnderlineValues Underline { get { return Key.Underline; } } + + public bool Strikethrough { get { return Key.Strikethrough; } } + + public XLFontVerticalTextAlignmentValues VerticalAlignment { get { return Key.VerticalAlignment; } } + + public bool Shadow { get { return Key.Shadow; } } + + public double FontSize { get { return Key.FontSize; } } + + public XLColor FontColor { get; private set; } + + public string FontName { get { return Key.FontName; } } + + public XLFontFamilyNumberingValues FontFamilyNumbering { get { return Key.FontFamilyNumbering; } } + + public XLFontCharSet FontCharSet { get { return Key.FontCharSet; } } + + private XLFontValue(XLFontKey key) + { + Key = key; + + FontColor = XLColor.FromKey(Key.FontColor); + } + + public override bool Equals(object obj) + { + var cached = obj as XLFontValue; + return cached != null && + Key.Equals(cached.Key); + } + + public override int GetHashCode() + { + return -280332839 + EqualityComparer.Default.GetHashCode(Key); + } + } +} diff --git a/ClosedXML/Excel/Style/XLNumberFormat.cs b/ClosedXML/Excel/Style/XLNumberFormat.cs index 0fc2f4a..1f1a45f 100644 --- a/ClosedXML/Excel/Style/XLNumberFormat.cs +++ b/ClosedXML/Excel/Style/XLNumberFormat.cs @@ -4,112 +4,149 @@ { internal class XLNumberFormat : IXLNumberFormat { - #region IXLNumberFormat Members + #region Static members - public bool Equals(IXLNumberFormatBase other) + internal static XLNumberFormatKey GenerateKey(IXLNumberFormat defaultNumberFormat) { - return - _numberFormatId == other.NumberFormatId - && _format == other.Format - ; + if (defaultNumberFormat == null) + return XLNumberFormatValue.Default.Key; + + if (defaultNumberFormat is XLNumberFormat) + return (defaultNumberFormat as XLNumberFormat).Key; + + return new XLNumberFormatKey + { + NumberFormatId = defaultNumberFormat.NumberFormatId, + Format = defaultNumberFormat.Format + }; } - #endregion - - private void SetStyleChanged() - { - if (_container != null) _container.StyleChanged = true; - } - - public override bool Equals(object obj) - { - return Equals((IXLNumberFormatBase)obj); - } - - public override int GetHashCode() - { - return NumberFormatId - ^ Format.GetHashCode(); - } + #endregion Static members #region Properties - private readonly IXLStylized _container; - private String _format = String.Empty; + private readonly XLStyle _style; - private Int32 _numberFormatId; + private XLNumberFormatValue _value; + + internal XLNumberFormatKey Key + { + get { return _value.Key; } + private set { _value = XLNumberFormatValue.FromKey(value); } + } + + #endregion Properties + + #region Constructors + + /// + /// Create an instance of XLNumberFormat initializing it with the specified value. + /// + /// Style to attach the new instance to. + /// Style value to use. + public XLNumberFormat(XLStyle style, XLNumberFormatValue value) + { + _style = style ?? XLStyle.CreateEmptyStyle(); + _value = value; + } + + public XLNumberFormat(XLStyle style, XLNumberFormatKey key) : this(style, XLNumberFormatValue.FromKey(key)) + { + } + + public XLNumberFormat(XLStyle style = null, IXLNumberFormat d = null) : this(style, GenerateKey(d)) + { + } + + #endregion Constructors + + #region IXLNumberFormat Members public Int32 NumberFormatId { - get { return _numberFormatId; } + get { return Key.NumberFormatId; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.NumberFormat.NumberFormatId = value); - else + Modify(k => { - _numberFormatId = value; - _format = String.Empty; - } + k.Format = XLNumberFormatValue.Default.Format; + k.NumberFormatId = value; + return k; + }); } } public String Format { - get { return _format; } + get { return Key.Format; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.NumberFormat.Format = value); - else + Modify(k => { - _format = value; - _numberFormatId = -1; - } + k.Format = value; + if (string.IsNullOrWhiteSpace(k.Format)) + k.NumberFormatId = XLNumberFormatValue.Default.NumberFormatId; + else + k.NumberFormatId = -1; + return k; + }); } } public IXLStyle SetNumberFormatId(Int32 value) { NumberFormatId = value; - return _container.Style; + return _style; } public IXLStyle SetFormat(String value) { Format = value; - return _container.Style; + return _style; } - #endregion + #endregion IXLNumberFormat Members - #region Constructors - - public XLNumberFormat() - : this(null, XLWorkbook.DefaultStyle.NumberFormat) + private void Modify(Func modification) { + Key = modification(Key); + + _style.Modify(styleKey => + { + var numberFormat = styleKey.NumberFormat; + styleKey.NumberFormat = modification(numberFormat); + return styleKey; + }); } - - public XLNumberFormat(IXLStylized container, IXLNumberFormat defaultNumberFormat) - { - _container = container; - if (defaultNumberFormat == null) return; - _numberFormatId = defaultNumberFormat.NumberFormatId; - _format = defaultNumberFormat.Format; - } - - #endregion - #region Overridden public override string ToString() { - return _numberFormatId + "-" + _format; + return NumberFormatId + "-" + Format; } - #endregion + public override bool Equals(object obj) + { + return Equals(obj as IXLNumberFormatBase); + } + + public bool Equals(IXLNumberFormatBase other) + { + var otherN = other as XLNumberFormat; + if (otherN == null) + return false; + + return Key == otherN.Key; + } + + public override int GetHashCode() + { + var hashCode = 416600561; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; + } + + #endregion Overridden } } diff --git a/ClosedXML/Excel/Style/XLNumberFormatKey.cs b/ClosedXML/Excel/Style/XLNumberFormatKey.cs new file mode 100644 index 0000000..7a14dc5 --- /dev/null +++ b/ClosedXML/Excel/Style/XLNumberFormatKey.cs @@ -0,0 +1,42 @@ +using System; + +namespace ClosedXML.Excel +{ + internal struct XLNumberFormatKey : IEquatable + { + public int NumberFormatId { get; set; } + + public string Format { get; set; } + + public override int GetHashCode() + { + var hashCode = -759193072; + hashCode = hashCode * -1521134295 + NumberFormatId.GetHashCode(); + hashCode = hashCode * -1521134295 + (Format == null ? 0 : Format.ToUpperInvariant().GetHashCode()); + return hashCode; + } + + public bool Equals(XLNumberFormatKey other) + { + return + NumberFormatId == other.NumberFormatId + && string.Equals(Format, other.Format, StringComparison.InvariantCultureIgnoreCase); + } + + public override bool Equals(object obj) + { + if (obj is XLNumberFormatKey) + return Equals((XLNumberFormatKey)obj); + return base.Equals(obj); + } + + public override string ToString() + { + return $"{Format}/{NumberFormatId}"; + } + + public static bool operator ==(XLNumberFormatKey left, XLNumberFormatKey right) => left.Equals(right); + + public static bool operator !=(XLNumberFormatKey left, XLNumberFormatKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLNumberFormatValue.cs b/ClosedXML/Excel/Style/XLNumberFormatValue.cs new file mode 100644 index 0000000..dab2ee1 --- /dev/null +++ b/ClosedXML/Excel/Style/XLNumberFormatValue.cs @@ -0,0 +1,43 @@ +using ClosedXML.Excel.Caching; + +namespace ClosedXML.Excel +{ + internal sealed class XLNumberFormatValue + { + private static readonly XLNumberFormatRepository Repository = new XLNumberFormatRepository(key => new XLNumberFormatValue(key)); + + public static XLNumberFormatValue FromKey(XLNumberFormatKey key) + { + return Repository.GetOrCreate(key); + } + + internal static readonly XLNumberFormatValue Default = FromKey(new XLNumberFormatKey + { + NumberFormatId = 0, + Format = string.Empty + }); + + public XLNumberFormatKey Key { get; private set; } + + public int NumberFormatId { get { return Key.NumberFormatId; } } + + public string Format { get { return Key.Format; } } + + private XLNumberFormatValue(XLNumberFormatKey key) + { + Key = key; + } + + public override bool Equals(object obj) + { + var cached = obj as XLNumberFormatValue; + return cached != null && + Key.Equals(cached.Key); + } + + public override int GetHashCode() + { + return 1507230172 + Key.GetHashCode(); + } + } +} diff --git a/ClosedXML/Excel/Style/XLPredefinedFormat.cs b/ClosedXML/Excel/Style/XLPredefinedFormat.cs index 461cf73..e256a30 100644 --- a/ClosedXML/Excel/Style/XLPredefinedFormat.cs +++ b/ClosedXML/Excel/Style/XLPredefinedFormat.cs @@ -170,6 +170,7 @@ } private static IDictionary _formatCodes; + internal static IDictionary FormatCodes { get diff --git a/ClosedXML/Excel/Style/XLProtection.cs b/ClosedXML/Excel/Style/XLProtection.cs index 51ba453..9a36f59 100644 --- a/ClosedXML/Excel/Style/XLProtection.cs +++ b/ClosedXML/Excel/Style/XLProtection.cs @@ -4,109 +4,133 @@ { internal class XLProtection : IXLProtection { - private readonly IXLStylized _container; - private Boolean _hidden; + #region Static members - private Boolean _locked; + internal static XLProtectionKey GenerateKey(IXLProtection defaultProtection) + { + if (defaultProtection == null) + return XLProtectionValue.Default.Key; + if (defaultProtection is XLProtection) + return (defaultProtection as XLProtection).Key; + + return new XLProtectionKey + { + Locked = defaultProtection.Locked, + Hidden = defaultProtection.Hidden + }; + } + + #endregion Static members + + #region Properties + + private readonly XLStyle _style; + + private XLProtectionValue _value; + + internal XLProtectionKey Key + { + get { return _value.Key; } + private set { _value = XLProtectionValue.FromKey(value); } + } + + #endregion Properties + + #region Constructors + + /// + /// Create an instance of XLProtection initializing it with the specified value. + /// + /// Style to attach the new instance to. + /// Style value to use. + public XLProtection(XLStyle style, XLProtectionValue value) + { + _style = style ?? XLStyle.CreateEmptyStyle(); + _value = value; + } + + public XLProtection(XLStyle style, XLProtectionKey key) : this(style, XLProtectionValue.FromKey(key)) + { + } + + public XLProtection(XLStyle style = null, IXLProtection d = null) : this(style, GenerateKey(d)) + { + } + + #endregion Constructors #region IXLProtection Members public Boolean Locked { - get { return _locked; } + get { return Key.Locked; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Protection.Locked = value); - else - _locked = value; + Modify(k => { k.Locked = value; return k; }); } } public Boolean Hidden { - get { return _hidden; } + get { return Key.Hidden; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Protection.Hidden = value); - else - _hidden = value; + Modify(k => { k.Hidden = value; return k; }); } } + public IXLStyle SetLocked() + { + Locked = true; + return _style; + } + + public IXLStyle SetLocked(Boolean value) + { + Locked = value; + return _style; + } + + public IXLStyle SetHidden() + { + Hidden = true; + return _style; + } + + public IXLStyle SetHidden(Boolean value) + { + Hidden = value; + return _style; + } + + #endregion IXLProtection Members + + private void Modify(Func modification) + { + Key = modification(Key); + + _style.Modify(styleKey => + { + var protection = styleKey.Protection; + styleKey.Protection = modification(protection); + return styleKey; + }); + } + + #region Overridden + + public override bool Equals(object obj) + { + return Equals((IXLProtection)obj); + } + public bool Equals(IXLProtection other) { var otherP = other as XLProtection; if (otherP == null) return false; - return _locked == otherP._locked - && _hidden == otherP._hidden; - } - - public IXLStyle SetLocked() - { - Locked = true; - return _container.Style; - } - - public IXLStyle SetLocked(Boolean value) - { - Locked = value; - return _container.Style; - } - - public IXLStyle SetHidden() - { - Hidden = true; - return _container.Style; - } - - public IXLStyle SetHidden(Boolean value) - { - Hidden = value; - return _container.Style; - } - - #endregion - - #region Constructors - - public XLProtection() - : this(null, XLWorkbook.DefaultStyle.Protection) - { - } - - public XLProtection(IXLStylized container, IXLProtection defaultProtection = null) - { - _container = container; - if (defaultProtection == null) return; - - _locked = defaultProtection.Locked; - _hidden = defaultProtection.Hidden; - } - - #endregion - - private void SetStyleChanged() - { - if (_container != null) _container.StyleChanged = true; - } - - public override bool Equals(object obj) - { - return Equals((IXLProtection)obj); - } - - public override int GetHashCode() - { - if (Locked) - return Hidden ? 11 : 10; - - return Hidden ? 1 : 0; + return Key == otherP.Key; } public override string ToString() @@ -116,5 +140,14 @@ return Hidden ? "Hidden" : "None"; } + + public override int GetHashCode() + { + var hashCode = 416600561; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; + } + + #endregion Overridden } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/Style/XLProtectionKey.cs b/ClosedXML/Excel/Style/XLProtectionKey.cs new file mode 100644 index 0000000..ba4f013 --- /dev/null +++ b/ClosedXML/Excel/Style/XLProtectionKey.cs @@ -0,0 +1,42 @@ +using System; + +namespace ClosedXML.Excel +{ + internal struct XLProtectionKey : IEquatable + { + public bool Locked { get; set; } + + public bool Hidden { get; set; } + + public override int GetHashCode() + { + var hashCode = -1357408252; + hashCode = hashCode * -1521134295 + Locked.GetHashCode(); + hashCode = hashCode * -1521134295 + Hidden.GetHashCode(); + return hashCode; + } + + public bool Equals(XLProtectionKey other) + { + return + Locked == other.Locked + && Hidden == other.Hidden; + } + + public override bool Equals(object obj) + { + if (obj is XLProtectionKey) + return Equals((XLProtectionKey)obj); + return base.Equals(obj); + } + + public override string ToString() + { + return (Locked ? "Locked" : "") + (Hidden ? "Hidden" : ""); + } + + public static bool operator ==(XLProtectionKey left, XLProtectionKey right) => left.Equals(right); + + public static bool operator !=(XLProtectionKey left, XLProtectionKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLProtectionValue.cs b/ClosedXML/Excel/Style/XLProtectionValue.cs new file mode 100644 index 0000000..c5520e9 --- /dev/null +++ b/ClosedXML/Excel/Style/XLProtectionValue.cs @@ -0,0 +1,43 @@ +using ClosedXML.Excel.Caching; + +namespace ClosedXML.Excel +{ + internal sealed class XLProtectionValue + { + private static readonly XLProtectionRepository Repository = new XLProtectionRepository(key => new XLProtectionValue(key)); + + public static XLProtectionValue FromKey(XLProtectionKey key) + { + return Repository.GetOrCreate(key); + } + + internal static readonly XLProtectionValue Default = FromKey(new XLProtectionKey + { + Locked = true, + Hidden = false + }); + + public XLProtectionKey Key { get; private set; } + + public bool Locked { get { return Key.Locked; } } + + public bool Hidden { get { return Key.Hidden; } } + + private XLProtectionValue(XLProtectionKey key) + { + Key = key; + } + + public override bool Equals(object obj) + { + var cached = obj as XLProtectionValue; + return cached != null && + Key.Equals(cached.Key); + } + + public override int GetHashCode() + { + return 909014992 + Key.GetHashCode(); + } + } +} diff --git a/ClosedXML/Excel/Style/XLStyle.cs b/ClosedXML/Excel/Style/XLStyle.cs index 939aa96..95e63f2 100644 --- a/ClosedXML/Excel/Style/XLStyle.cs +++ b/ClosedXML/Excel/Style/XLStyle.cs @@ -5,55 +5,153 @@ { internal class XLStyle : IXLStyle { - public XLStyle(IXLStylized container, IXLStyle initialStyle = null, Boolean useDefaultModify = true) - { - if (initialStyle != null) - { - Font = new XLFont(container, initialStyle.Font, useDefaultModify); - Alignment = new XLAlignment(container, initialStyle.Alignment); - Border = new XLBorder(container, initialStyle.Border, useDefaultModify); - Fill = new XLFill(container, initialStyle.Fill, useDefaultModify); - NumberFormat = new XLNumberFormat(container, initialStyle.NumberFormat); - Protection = new XLProtection(container, initialStyle.Protection); - } - else - { - Font = new XLFont(container, null); - Alignment = new XLAlignment(container); - Border = new XLBorder(container, null); - Fill = new XLFill(container); - NumberFormat = new XLNumberFormat(container, null); - Protection = new XLProtection(container); - } + #region Static members - DateFormat = NumberFormat; + public static XLStyle Default { get { return new XLStyle(XLStyleValue.Default); } } + + internal static XLStyleKey GenerateKey(IXLStyle initialStyle) + { + if (initialStyle == null) + return Default.Key; + if (initialStyle is XLStyle) + return (initialStyle as XLStyle).Key; + + return new XLStyleKey + { + Font = XLFont.GenerateKey(initialStyle.Font), + Alignment = XLAlignment.GenerateKey(initialStyle.Alignment), + Border = XLBorder.GenerateKey(initialStyle.Border), + Fill = XLFill.GenerateKey(initialStyle.Fill), + NumberFormat = XLNumberFormat.GenerateKey(initialStyle.NumberFormat), + Protection = XLProtection.GenerateKey(initialStyle.Protection) + }; } - public IXLFont Font { get; set; } - - public IXLAlignment Alignment { get; set; } - - public IXLBorder Border { get; set; } - - public IXLFill Fill { get; set; } - - private IXLNumberFormat numberFormat; - public IXLNumberFormat NumberFormat + internal static XLStyle CreateEmptyStyle() { - get + return new XLStyle(new XLStylizedEmpty(null)); + } + + #endregion Static members + + #region properties + + private readonly IXLStylized _container; + + internal XLStyleValue Value { get; private set; } + + internal XLStyleKey Key + { + get { return Value.Key; } + private set { - return numberFormat; + Value = XLStyleValue.FromKey(value); } + } + + #endregion properties + + #region constructors + + public XLStyle(IXLStylized container, IXLStyle initialStyle = null, Boolean useDefaultModify = true) : this(container, GenerateKey(initialStyle)) + { + } + + public XLStyle(IXLStylized container, XLStyleKey key) : this(container, XLStyleValue.FromKey(key)) + { + } + + internal XLStyle(IXLStylized container, XLStyleValue value) + { + _container = container ?? new XLStylizedEmpty(XLStyle.Default); + Value = value; + } + + /// + /// To initialize XLStyle.Default only + /// + private XLStyle(XLStyleValue value) + { + _container = null; + Value = value; + } + + #endregion constructors + + internal void Modify(Func modification) + { + Key = modification(Key); + + if (_container != null) + { + _container.ModifyStyle(modification); + } + } + + #region IXLStyle members + + public IXLFont Font + { + get { return new XLFont(this, Value.Font); } set { - numberFormat = value; - DateFormat = numberFormat; + Modify(k => { k.Font = XLFont.GenerateKey(value); return k; }); } } - public IXLProtection Protection { get; set; } + public IXLAlignment Alignment + { + get { return new XLAlignment(this, Value.Alignment); } + set + { + Modify(k => { k.Alignment = XLAlignment.GenerateKey(value); return k; }); + } + } - public IXLNumberFormat DateFormat { get; private set; } + public IXLBorder Border + { + get { return new XLBorder(_container, this, Value.Border); } + set + { + Modify(k => { k.Border = XLBorder.GenerateKey(value); return k; }); + } + } + + public IXLFill Fill + { + get { return new XLFill(this, Value.Fill); } + set + { + Modify(k => { k.Fill = XLFill.GenerateKey(value); return k; }); + } + } + + public IXLNumberFormat NumberFormat + { + get { return new XLNumberFormat(this, Value.NumberFormat); } + set + { + Modify(k => { k.NumberFormat = XLNumberFormat.GenerateKey(value); return k; }); + } + } + + public IXLProtection Protection + { + get { return new XLProtection(this, Value.Protection); } + set + { + Modify(k => { k.Protection = XLProtection.GenerateKey(value); return k; }); + } + } + + public IXLNumberFormat DateFormat + { + get { return NumberFormat; } + } + + #endregion IXLStyle members + + #region Overridden public override string ToString() { @@ -75,29 +173,27 @@ public bool Equals(IXLStyle other) { - return - Font.Equals(other.Font) - && Fill.Equals(other.Fill) - && Border.Equals(other.Border) - && NumberFormat.Equals(other.NumberFormat) - && Alignment.Equals(other.Alignment) - && Protection.Equals(other.Protection) - ; + var otherS = other as XLStyle; + + if (otherS == null) + return false; + + return Key == otherS.Key && + _container == otherS._container; } public override bool Equals(object obj) { - return Equals((XLStyle)obj); + return Equals(obj as XLStyle); } public override int GetHashCode() { - return Font.GetHashCode() - ^ Fill.GetHashCode() - ^ Border.GetHashCode() - ^ NumberFormat.GetHashCode() - ^ Alignment.GetHashCode() - ^ Protection.GetHashCode(); + var hashCode = 416600561; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; } + + #endregion Overridden } } diff --git a/ClosedXML/Excel/Style/XLStyleKey.cs b/ClosedXML/Excel/Style/XLStyleKey.cs new file mode 100644 index 0000000..46eea98 --- /dev/null +++ b/ClosedXML/Excel/Style/XLStyleKey.cs @@ -0,0 +1,65 @@ +using System; + +namespace ClosedXML.Excel +{ + internal struct XLStyleKey : IEquatable + { + public XLAlignmentKey Alignment { get; set; } + + public XLBorderKey Border { get; set; } + + public XLFillKey Fill { get; set; } + + public XLFontKey Font { get; set; } + + public XLNumberFormatKey NumberFormat { get; set; } + + public XLProtectionKey Protection { get; set; } + + public override int GetHashCode() + { + var hashCode = -476701294; + hashCode = hashCode * -1521134295 + Alignment.GetHashCode(); + hashCode = hashCode * -1521134295 + Border.GetHashCode(); + hashCode = hashCode * -1521134295 + Fill.GetHashCode(); + hashCode = hashCode * -1521134295 + Font.GetHashCode(); + hashCode = hashCode * -1521134295 + NumberFormat.GetHashCode(); + hashCode = hashCode * -1521134295 + Protection.GetHashCode(); + return hashCode; + } + + public bool Equals(XLStyleKey other) + { + return Alignment == other.Alignment && + Border == other.Border && + Fill == other.Fill && + Font == other.Font && + NumberFormat == other.NumberFormat && + Protection == other.Protection; + } + + public override string ToString() + { + return + this == XLStyle.Default.Key ? "Default" : + string.Format("Alignment: {0} Border: {1} Fill: {2} Font: {3} NumberFormat: {4} Protection: {5}", + Alignment == XLStyle.Default.Key.Alignment ? "Default" : Alignment.ToString(), + Border == XLStyle.Default.Key.Border ? "Default" : Border.ToString(), + Fill == XLStyle.Default.Key.Fill ? "Default" : Fill.ToString(), + Font == XLStyle.Default.Key.Font ? "Default" : Font.ToString(), + NumberFormat == XLStyle.Default.Key.NumberFormat ? "Default" : NumberFormat.ToString(), + Protection == XLStyle.Default.Key.Protection ? "Default" : Protection.ToString()); + } + + public override bool Equals(object obj) + { + if (obj is XLStyleKey) + return Equals((XLStyleKey)obj); + return base.Equals(obj); + } + + public static bool operator ==(XLStyleKey left, XLStyleKey right) => left.Equals(right); + + public static bool operator !=(XLStyleKey left, XLStyleKey right) => !(left.Equals(right)); + } +} diff --git a/ClosedXML/Excel/Style/XLStyleValue.cs b/ClosedXML/Excel/Style/XLStyleValue.cs new file mode 100644 index 0000000..a2745bf --- /dev/null +++ b/ClosedXML/Excel/Style/XLStyleValue.cs @@ -0,0 +1,80 @@ +using ClosedXML.Excel.Caching; + +namespace ClosedXML.Excel +{ + internal class XLStyleValue + { + private static readonly XLStyleRepository Repository = new XLStyleRepository(key => new XLStyleValue(key)); + + public static XLStyleValue FromKey(XLStyleKey key) + { + return Repository.GetOrCreate(key); + } + + internal static readonly XLStyleValue Default = FromKey(new XLStyleKey + { + Alignment = XLAlignmentValue.Default.Key, + Border = XLBorderValue.Default.Key, + Fill = XLFillValue.Default.Key, + Font = XLFontValue.Default.Key, + NumberFormat = XLNumberFormatValue.Default.Key, + Protection = XLProtectionValue.Default.Key + }); + + public XLStyleKey Key { get; private set; } + + public XLAlignmentValue Alignment { get; private set; } + + public XLBorderValue Border { get; private set; } + + public XLFillValue Fill { get; private set; } + + public XLFontValue Font { get; private set; } + + public XLNumberFormatValue NumberFormat { get; private set; } + + public XLProtectionValue Protection { get; private set; } + + internal XLStyleValue(XLStyleKey key) + { + Key = key; + Alignment = XLAlignmentValue.FromKey(Key.Alignment); + Border = XLBorderValue.FromKey(Key.Border); + Fill = XLFillValue.FromKey(Key.Fill); + Font = XLFontValue.FromKey(Key.Font); + NumberFormat = XLNumberFormatValue.FromKey(Key.NumberFormat); + Protection = XLProtectionValue.FromKey(Key.Protection); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(this, obj)) + return true; + + var cached = obj as XLStyleValue; + return cached != null && + Key.Equals(cached.Key); + } + + public override int GetHashCode() + { + return -280332839 + Key.GetHashCode(); + } + + public static bool operator ==(XLStyleValue left, XLStyleValue right) + { + if (ReferenceEquals(left, right)) + return true; + if (ReferenceEquals(left, null) && ReferenceEquals(right, null)) + return true; + if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) + return false; + return left.Key.Equals(right.Key); + } + + public static bool operator !=(XLStyleValue left, XLStyleValue right) + { + return !(left == right); + } + } +} diff --git a/ClosedXML/Excel/Style/XLStylizedBase.cs b/ClosedXML/Excel/Style/XLStylizedBase.cs new file mode 100644 index 0000000..307bcf7 --- /dev/null +++ b/ClosedXML/Excel/Style/XLStylizedBase.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace ClosedXML.Excel +{ + /// + /// Base class for any workbook element that has or may have a style. + /// + internal abstract class XLStylizedBase : IXLStylized + { + #region Properties + + /// + /// Read-only style property. + /// + internal XLStyleValue StyleValue { get; private set; } + XLStyleValue IXLStylized.StyleValue + { + get { return StyleValue; } + } + + /// + /// Editable style of the workbook element. Modification of this property DOES affect styles of child objects as well - they will + /// be changed accordingly. Accessing this property causes a new instance generated so use this property + /// with caution. If you need only _read_ the style consider using property instead. + /// + public IXLStyle Style + { + get { return InnerStyle; } + set { SetStyle(value, true); } + } + + /// + /// Editable style of the workbook element. Modification of this property DOES NOT affect styles of child objects. + /// Accessing this property causes a new instance generated so use this property with caution. If you need + /// only _read_ the style consider using property instead. + /// + public IXLStyle InnerStyle + { + get { return new XLStyle(this, StyleValue.Key); } + set { SetStyle(value, false); } + } + + /// + /// Get a collection of stylized entities which current entity's style changes should be propagated to. + /// + protected abstract IEnumerable Children { get; } + + public abstract IXLRanges RangesUsed { get; } + + public abstract IEnumerable Styles { get; } + + #endregion Properties + + protected XLStylizedBase(XLStyleValue styleValue) + { + StyleValue = styleValue; + } + + #region Private methods + + private void SetStyle(IXLStyle value, bool propagate = false) + { + SetStyle(XLStyleValue.FromKey(XLStyle.GenerateKey(value)), propagate); + } + + /// + /// Apply specified style to the container. + /// + /// Style to apply. + /// Whether or not propagate the style to inner ranges. + private void SetStyle(XLStyleValue value, bool propagate = false) + { + StyleValue = value; + if (propagate) + { + Children.ForEach(child => child.SetStyle(StyleValue, true)); + } + } + + private static ReferenceEqualityComparer _comparer = new ReferenceEqualityComparer(); + + void IXLStylized.ModifyStyle(Func modification) + { + var children = GetChildrenRecursively(this) + .GroupBy(child => child.StyleValue, _comparer); + + foreach (var group in children) + { + var styleKey = modification(group.Key.Key); + var styleValue = XLStyleValue.FromKey(styleKey); + foreach (var child in group) + { + child.StyleValue = styleValue; + } + } + } + + private IEnumerable GetChildrenRecursively(XLStylizedBase parent) + { + return new List { parent } + .Union(parent.Children.Where(child => child != parent).SelectMany(child => GetChildrenRecursively(child))); + } + + #endregion Private methods + + #region Nested classes + + public sealed class ReferenceEqualityComparer : IEqualityComparer where T : class + { + public bool Equals(T x, T y) => ReferenceEquals(x, y); + + public int GetHashCode(T obj) => RuntimeHelpers.GetHashCode(obj); + } + + #endregion Nested classes + } +} diff --git a/ClosedXML/Excel/Style/XLStylizedContainer.cs b/ClosedXML/Excel/Style/XLStylizedContainer.cs index e9177a3..458bcd3 100644 --- a/ClosedXML/Excel/Style/XLStylizedContainer.cs +++ b/ClosedXML/Excel/Style/XLStylizedContainer.cs @@ -2,36 +2,38 @@ namespace ClosedXML.Excel { - using System; - - internal class XLStylizedContainer: IXLStylized + internal class XLStylizedContainer : XLStylizedBase, IXLStylized { - public Boolean StyleChanged { get; set; } - readonly IXLStylized _container; + protected readonly IXLStylized _container; + public XLStylizedContainer(IXLStyle style, IXLStylized container) + : base((style as XLStyle).Value) { - Style = style; _container = container; - RangesUsed = container.RangesUsed; } - public IXLStyle Style { get; set; } - - public IEnumerable Styles + public override IEnumerable Styles { get { - var _backupUpdatingStyle = _container.UpdatingStyle; - _container.UpdatingStyle = true; yield return Style; - _container.UpdatingStyle = _backupUpdatingStyle; } } - public bool UpdatingStyle { get; set; } + public override IXLRanges RangesUsed + { + get { return _container.RangesUsed; } + } - public IXLStyle InnerStyle { get; set; } + protected override IEnumerable Children + { + get + { + if (_container is XLStylizedBase) + yield return _container as XLStylizedBase; - public IXLRanges RangesUsed { get; set; } + yield break; + } + } } } diff --git a/ClosedXML/Excel/Style/XLStylizedEmpty.cs b/ClosedXML/Excel/Style/XLStylizedEmpty.cs index 161f15f..d22ce36 100644 --- a/ClosedXML/Excel/Style/XLStylizedEmpty.cs +++ b/ClosedXML/Excel/Style/XLStylizedEmpty.cs @@ -1,37 +1,30 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ClosedXML.Excel { - internal class XLStylizedEmpty: IXLStylized + internal class XLStylizedEmpty : XLStylizedBase, IXLStylized { public XLStylizedEmpty(IXLStyle defaultStyle) + : base((defaultStyle as XLStyle)?.Value ?? XLStyle.Default.Value) { - Style = new XLStyle(this, defaultStyle); } - public IXLStyle Style { get; set; } - - public IEnumerable Styles + + public override IEnumerable Styles { get { - UpdatingStyle = true; yield return Style; - UpdatingStyle = false; } } - public bool UpdatingStyle { get; set; } - - public IXLStyle InnerStyle { get; set; } - - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { return new XLRanges(); } } - public bool StyleChanged { get; set; } + protected override IEnumerable Children + { + get { yield break; } + } } } diff --git a/ClosedXML/Excel/Tables/XLTableField.cs b/ClosedXML/Excel/Tables/XLTableField.cs index c7b2bbf..32c5c17 100644 --- a/ClosedXML/Excel/Tables/XLTableField.cs +++ b/ClosedXML/Excel/Tables/XLTableField.cs @@ -162,14 +162,14 @@ var styles = this.Column .Cells() .Skip(this.table.ShowHeaderRow ? 1 : 0) - .Select(c => c.Style); + .OfType() + .Select(c => c.StyleValue); if (this.table.ShowTotalsRow) styles = styles.Take(styles.Count() - 1); var distinctStyles = styles - .GroupBy(f => f) - .Select(g => new { Key = g.Key, Count = g.Count() }); + .Distinct(); return distinctStyles.Count() == 1; } diff --git a/ClosedXML/Excel/Tables/XLTableRows.cs b/ClosedXML/Excel/Tables/XLTableRows.cs index bb17b88..f02dffa 100644 --- a/ClosedXML/Excel/Tables/XLTableRows.cs +++ b/ClosedXML/Excel/Tables/XLTableRows.cs @@ -5,25 +5,20 @@ { using System.Collections; - internal class XLTableRows : IXLTableRows, IXLStylized + internal class XLTableRows : XLStylizedBase, IXLTableRows, IXLStylized { - public Boolean StyleChanged { get; set; } private readonly List _ranges = new List(); - private IXLStyle _style; - - public XLTableRows(IXLStyle defaultStyle) + + public XLTableRows(IXLStyle defaultStyle) : base((defaultStyle as XLStyle).Value) { - _style = new XLStyle(this, defaultStyle); } #region IXLStylized Members - - public IEnumerable Styles + public override IEnumerable Styles { get { - UpdatingStyle = true; - yield return _style; + yield return Style; foreach (XLTableRow rng in _ranges) { yield return rng.Style; @@ -34,19 +29,21 @@ rng.RangeAddress.LastAddress.ColumnNumber)) yield return r.Style; } - UpdatingStyle = false; } } - public Boolean UpdatingStyle { get; set; } - - public IXLStyle InnerStyle + protected override IEnumerable Children { - get { return _style; } - set { _style = new XLStyle(this, value); } + get + { + foreach (var range in _ranges) + { + yield return range; + } + } } - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { @@ -83,16 +80,6 @@ return GetEnumerator(); } - public IXLStyle Style - { - get { return _style; } - set - { - _style = new XLStyle(this, value); - _ranges.ForEach(r => r.Style = value); - } - } - public IXLCells Cells() { var cells = new XLCells(false, false); diff --git a/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/Excel/XLWorkbook.cs index 3a22085..c9716be 100644 --- a/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/Excel/XLWorkbook.cs @@ -44,69 +44,19 @@ public partial class XLWorkbook : IXLWorkbook { #region Static - - private static IXLStyle _defaultStyle; - public static IXLStyle DefaultStyle { get { - return _defaultStyle - ?? (_defaultStyle = new XLStyle(null) - { - Font = new XLFont(null, null) - { - Bold = false, - Italic = false, - Underline = XLFontUnderlineValues.None, - Strikethrough = false, - VerticalAlignment = XLFontVerticalTextAlignmentValues.Baseline, - FontSize = 11, - FontColor = XLColor.FromArgb(0, 0, 0), - FontName = "Calibri", - FontFamilyNumbering = XLFontFamilyNumberingValues.Swiss, - FontCharSet = XLFontCharSet.Default - }, - Fill = new XLFill(null) - { - BackgroundColor = XLColor.FromIndex(64), - PatternType = XLFillPatternValues.None, - PatternColor = XLColor.FromIndex(64) - }, - Border = new XLBorder(null, null) - { - BottomBorder = XLBorderStyleValues.None, - DiagonalBorder = XLBorderStyleValues.None, - DiagonalDown = false, - DiagonalUp = false, - LeftBorder = XLBorderStyleValues.None, - RightBorder = XLBorderStyleValues.None, - TopBorder = XLBorderStyleValues.None, - BottomBorderColor = XLColor.Black, - DiagonalBorderColor = XLColor.Black, - LeftBorderColor = XLColor.Black, - RightBorderColor = XLColor.Black, - TopBorderColor = XLColor.Black - }, - NumberFormat = new XLNumberFormat(null, null) { NumberFormatId = 0 }, - Alignment = new XLAlignment(null) - { - Indent = 0, - Horizontal = XLAlignmentHorizontalValues.General, - JustifyLastLine = false, - ReadingOrder = XLAlignmentReadingOrderValues.ContextDependent, - RelativeIndent = 0, - ShrinkToFit = false, - TextRotation = 0, - Vertical = XLAlignmentVerticalValues.Bottom, - WrapText = false - }, - Protection = new XLProtection(null) - { - Locked = true, - Hidden = false - } - }); + return XLStyle.Default; + } + } + + internal static XLStyleValue DefaultStyleValue + { + get + { + return XLStyleValue.Default; } } @@ -167,29 +117,8 @@ internal readonly List UnsupportedSheets = new List(); - private readonly Dictionary _stylesById = new Dictionary(); - private readonly Dictionary _stylesByStyle = new Dictionary(); - public XLEventTracking EventTracking { get; set; } - internal Int32 GetStyleId(IXLStyle style) - { - Int32 cached; - if (_stylesByStyle.TryGetValue(style, out cached)) - return cached; - - var count = _stylesByStyle.Count; - var styleToUse = new XLStyle(null, style); - _stylesByStyle.Add(styleToUse, count); - _stylesById.Add(count, styleToUse); - return count; - } - - internal IXLStyle GetStyleById(Int32 id) - { - return _stylesById[id]; - } - #region Nested Type: XLLoadSource private enum XLLoadSource diff --git a/ClosedXML/Excel/XLWorkbook_Load.cs b/ClosedXML/Excel/XLWorkbook_Load.cs index fa2079c..85b6eec 100644 --- a/ClosedXML/Excel/XLWorkbook_Load.cs +++ b/ClosedXML/Excel/XLWorkbook_Load.cs @@ -1350,7 +1350,6 @@ else { ApplyStyle(xlCell, styleIndex, s, fills, borders, fonts, numberingFormats); - styleList.Add(styleIndex, xlCell.Style); } if (cell.CellFormula != null && cell.CellFormula.SharedIndex != null && cell.CellFormula.Reference != null) @@ -1487,6 +1486,9 @@ // so if a workbook is in 1904-format, we do that adjustment here and when saving. xlCell.SetValue(xlCell.GetDateTime().AddDays(1462)); } + + if (!styleList.ContainsKey(styleIndex)) + styleList.Add(styleIndex, xlCell.Style); } /// @@ -2553,18 +2555,23 @@ var cellFormat = (CellFormat)s.CellFormats.ElementAt(styleIndex); + var xlStyle = XLStyle.Default.Key; + if (cellFormat.ApplyProtection != null) { var protection = cellFormat.Protection; if (protection == null) - xlStylized.InnerStyle.Protection = new XLProtection(null, DefaultStyle.Protection); + xlStyle.Protection = XLProtectionValue.Default.Key; else { - xlStylized.InnerStyle.Protection.Hidden = protection.Hidden != null && protection.Hidden.HasValue && - protection.Hidden.Value; - xlStylized.InnerStyle.Protection.Locked = protection.Locked == null || - (protection.Locked.HasValue && protection.Locked.Value); + xlStyle.Protection = new XLProtectionKey + { + Hidden = protection.Hidden != null && protection.Hidden.HasValue && + protection.Hidden.Value, + Locked = protection.Locked == null || + (protection.Locked.HasValue && protection.Locked.Value) + }; } } @@ -2575,90 +2582,97 @@ { LoadFill(fill, xlStylized.InnerStyle.Fill, differentialFillFormat: false); } + xlStyle.Fill = (xlStylized.InnerStyle as XLStyle).Value.Key.Fill; } var alignment = cellFormat.Alignment; if (alignment != null) { + var xlAlignment = xlStyle.Alignment; if (alignment.Horizontal != null) - xlStylized.InnerStyle.Alignment.Horizontal = alignment.Horizontal.Value.ToClosedXml(); + xlAlignment.Horizontal = alignment.Horizontal.Value.ToClosedXml(); if (alignment.Indent != null && alignment.Indent != 0) - xlStylized.InnerStyle.Alignment.Indent = Int32.Parse(alignment.Indent.ToString()); + xlAlignment.Indent = Int32.Parse(alignment.Indent.ToString()); if (alignment.JustifyLastLine != null) - xlStylized.InnerStyle.Alignment.JustifyLastLine = alignment.JustifyLastLine; + xlAlignment.JustifyLastLine = alignment.JustifyLastLine; if (alignment.ReadingOrder != null) { - xlStylized.InnerStyle.Alignment.ReadingOrder = + xlAlignment.ReadingOrder = (XLAlignmentReadingOrderValues)Int32.Parse(alignment.ReadingOrder.ToString()); } if (alignment.RelativeIndent != null) - xlStylized.InnerStyle.Alignment.RelativeIndent = alignment.RelativeIndent; + xlAlignment.RelativeIndent = alignment.RelativeIndent; if (alignment.ShrinkToFit != null) - xlStylized.InnerStyle.Alignment.ShrinkToFit = alignment.ShrinkToFit; + xlAlignment.ShrinkToFit = alignment.ShrinkToFit; if (alignment.TextRotation != null) - xlStylized.InnerStyle.Alignment.TextRotation = (Int32)alignment.TextRotation.Value; + xlAlignment.TextRotation = (Int32)alignment.TextRotation.Value; if (alignment.Vertical != null) - xlStylized.InnerStyle.Alignment.Vertical = alignment.Vertical.Value.ToClosedXml(); + xlAlignment.Vertical = alignment.Vertical.Value.ToClosedXml(); if (alignment.WrapText != null) - xlStylized.InnerStyle.Alignment.WrapText = alignment.WrapText; + xlAlignment.WrapText = alignment.WrapText; + + xlStyle.Alignment = xlAlignment; } if (UInt32HasValue(cellFormat.BorderId)) { uint borderId = cellFormat.BorderId.Value; var border = (Border)borders.ElementAt((Int32)borderId); + var xlBorder = xlStyle.Border; if (border != null) { var bottomBorder = border.BottomBorder; if (bottomBorder != null) { if (bottomBorder.Style != null) - xlStylized.InnerStyle.Border.BottomBorder = bottomBorder.Style.Value.ToClosedXml(); + xlBorder.BottomBorder = bottomBorder.Style.Value.ToClosedXml(); var bottomBorderColor = GetColor(bottomBorder.Color); if (bottomBorderColor.HasValue) - xlStylized.InnerStyle.Border.BottomBorderColor = bottomBorderColor; + xlBorder.BottomBorderColor = bottomBorderColor.Key; } var topBorder = border.TopBorder; if (topBorder != null) { if (topBorder.Style != null) - xlStylized.InnerStyle.Border.TopBorder = topBorder.Style.Value.ToClosedXml(); + xlBorder.TopBorder = topBorder.Style.Value.ToClosedXml(); var topBorderColor = GetColor(topBorder.Color); if (topBorderColor.HasValue) - xlStylized.InnerStyle.Border.TopBorderColor = topBorderColor; + xlBorder.TopBorderColor = topBorderColor.Key; } var leftBorder = border.LeftBorder; if (leftBorder != null) { if (leftBorder.Style != null) - xlStylized.InnerStyle.Border.LeftBorder = leftBorder.Style.Value.ToClosedXml(); + xlBorder.LeftBorder = leftBorder.Style.Value.ToClosedXml(); var leftBorderColor = GetColor(leftBorder.Color); if (leftBorderColor.HasValue) - xlStylized.InnerStyle.Border.LeftBorderColor = leftBorderColor; + xlBorder.LeftBorderColor = leftBorderColor.Key; } var rightBorder = border.RightBorder; if (rightBorder != null) { if (rightBorder.Style != null) - xlStylized.InnerStyle.Border.RightBorder = rightBorder.Style.Value.ToClosedXml(); + xlBorder.RightBorder = rightBorder.Style.Value.ToClosedXml(); var rightBorderColor = GetColor(rightBorder.Color); if (rightBorderColor.HasValue) - xlStylized.InnerStyle.Border.RightBorderColor = rightBorderColor; + xlBorder.RightBorderColor = rightBorderColor.Key; } var diagonalBorder = border.DiagonalBorder; if (diagonalBorder != null) { if (diagonalBorder.Style != null) - xlStylized.InnerStyle.Border.DiagonalBorder = diagonalBorder.Style.Value.ToClosedXml(); + xlBorder.DiagonalBorder = diagonalBorder.Style.Value.ToClosedXml(); var diagonalBorderColor = GetColor(diagonalBorder.Color); if (diagonalBorderColor.HasValue) - xlStylized.InnerStyle.Border.DiagonalBorderColor = diagonalBorderColor; + xlBorder.DiagonalBorderColor = diagonalBorderColor.Key; if (border.DiagonalDown != null) - xlStylized.InnerStyle.Border.DiagonalDown = border.DiagonalDown; + xlBorder.DiagonalDown = border.DiagonalDown; if (border.DiagonalUp != null) - xlStylized.InnerStyle.Border.DiagonalUp = border.DiagonalUp; + xlBorder.DiagonalUp = border.DiagonalUp; } + + xlStyle.Border = xlBorder; } } @@ -2666,71 +2680,83 @@ { var fontId = cellFormat.FontId; var font = (DocumentFormat.OpenXml.Spreadsheet.Font)fonts.ElementAt((Int32)fontId.Value); + + var xlFont = xlStyle.Font; if (font != null) { - xlStylized.InnerStyle.Font.Bold = GetBoolean(font.Bold); + xlFont.Bold = GetBoolean(font.Bold); var fontColor = GetColor(font.Color); if (fontColor.HasValue) - xlStylized.InnerStyle.Font.FontColor = fontColor; + xlFont.FontColor = fontColor.Key; if (font.FontFamilyNumbering != null && (font.FontFamilyNumbering).Val != null) { - xlStylized.InnerStyle.Font.FontFamilyNumbering = + xlFont.FontFamilyNumbering = (XLFontFamilyNumberingValues)Int32.Parse((font.FontFamilyNumbering).Val.ToString()); } if (font.FontName != null) { if ((font.FontName).Val != null) - xlStylized.InnerStyle.Font.FontName = (font.FontName).Val; + xlFont.FontName = (font.FontName).Val; } if (font.FontSize != null) { if ((font.FontSize).Val != null) - xlStylized.InnerStyle.Font.FontSize = (font.FontSize).Val; + xlFont.FontSize = (font.FontSize).Val; } - xlStylized.InnerStyle.Font.Italic = GetBoolean(font.Italic); - xlStylized.InnerStyle.Font.Shadow = GetBoolean(font.Shadow); - xlStylized.InnerStyle.Font.Strikethrough = GetBoolean(font.Strike); + xlFont.Italic = GetBoolean(font.Italic); + xlFont.Shadow = GetBoolean(font.Shadow); + xlFont.Strikethrough = GetBoolean(font.Strike); if (font.Underline != null) { - xlStylized.InnerStyle.Font.Underline = font.Underline.Val != null - ? (font.Underline).Val.Value.ToClosedXml() - : XLFontUnderlineValues.Single; + xlFont.Underline = font.Underline.Val != null + ? (font.Underline).Val.Value.ToClosedXml() + : XLFontUnderlineValues.Single; } if (font.VerticalTextAlignment != null) { - xlStylized.InnerStyle.Font.VerticalAlignment = font.VerticalTextAlignment.Val != null - ? (font.VerticalTextAlignment).Val.Value. - ToClosedXml() - : XLFontVerticalTextAlignmentValues.Baseline; + xlFont.VerticalAlignment = font.VerticalTextAlignment.Val != null + ? (font.VerticalTextAlignment).Val.Value.ToClosedXml() + : XLFontVerticalTextAlignmentValues.Baseline; } + + xlStyle.Font = xlFont; } } - if (!UInt32HasValue(cellFormat.NumberFormatId)) return; - - var numberFormatId = cellFormat.NumberFormatId; - - string formatCode = String.Empty; - if (numberingFormats != null) + if (UInt32HasValue(cellFormat.NumberFormatId)) { - var numberingFormat = - numberingFormats.FirstOrDefault( - nf => - ((NumberingFormat)nf).NumberFormatId != null && - ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId) as NumberingFormat; + var numberFormatId = cellFormat.NumberFormatId; - if (numberingFormat != null && numberingFormat.FormatCode != null) - formatCode = numberingFormat.FormatCode.Value; + string formatCode = String.Empty; + if (numberingFormats != null) + { + var numberingFormat = + numberingFormats.FirstOrDefault( + nf => + ((NumberingFormat)nf).NumberFormatId != null && + ((NumberingFormat)nf).NumberFormatId.Value == numberFormatId) as NumberingFormat; + + if (numberingFormat != null && numberingFormat.FormatCode != null) + formatCode = numberingFormat.FormatCode.Value; + } + + var xlNumberFormat = xlStyle.NumberFormat; + if (formatCode.Length > 0) + { + xlNumberFormat.Format = formatCode; + xlNumberFormat.NumberFormatId = -1; + } + else + xlNumberFormat.NumberFormatId = (Int32)numberFormatId.Value; + xlStyle.NumberFormat = xlNumberFormat; } - if (formatCode.Length > 0) - xlStylized.InnerStyle.NumberFormat.Format = formatCode; - else - xlStylized.InnerStyle.NumberFormat.NumberFormatId = (Int32)numberFormatId.Value; + + xlStylized.InnerStyle = new XLStyle(xlStylized, xlStyle); } private static Boolean UInt32HasValue(UInt32Value value) diff --git a/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs b/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs index e861ae9..a0423df 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs @@ -12,22 +12,22 @@ { public SaveContext() { - DifferentialFormats = new Dictionary(); + DifferentialFormats = new Dictionary(); PivotTables = new Dictionary(); RelIdGenerator = new RelIdGenerator(); - SharedFonts = new Dictionary(); + SharedFonts = new Dictionary(); SharedNumberFormats = new Dictionary(); - SharedStyles = new Dictionary(); + SharedStyles = new Dictionary(); TableId = 0; TableNames = new HashSet(); } - public Dictionary DifferentialFormats { get; private set; } + public Dictionary DifferentialFormats { get; private set; } public IDictionary PivotTables { get; private set; } public RelIdGenerator RelIdGenerator { get; private set; } - public Dictionary SharedFonts { get; private set; } + public Dictionary SharedFonts { get; private set; } public Dictionary SharedNumberFormats { get; private set; } - public Dictionary SharedStyles { get; private set; } + public Dictionary SharedStyles { get; private set; } public uint TableId { get; set; } public HashSet TableNames { get; private set; } } @@ -96,7 +96,7 @@ internal struct FontInfo { - public XLFont Font; + public XLFontValue Font; public UInt32 FontId; }; @@ -106,7 +106,7 @@ internal struct FillInfo { - public XLFill Fill; + public XLFillValue Fill; public UInt32 FillId; } @@ -116,7 +116,7 @@ internal struct BorderInfo { - public XLBorder Border; + public XLBorderValue Border; public UInt32 BorderId; } @@ -126,7 +126,7 @@ internal struct NumberFormatInfo { - public IXLNumberFormatBase NumberFormat; + public XLNumberFormatValue NumberFormat; public Int32 NumberFormatId; } @@ -140,7 +140,7 @@ public UInt32 FillId; public UInt32 FontId; public Int32 NumberFormatId; - public IXLStyle Style; + public XLStyleValue Style; public UInt32 StyleId; } diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs index afc77bd..59619b7 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -945,16 +945,13 @@ phoneticRun.Append(text); sharedStringItem.Append(phoneticRun); } - var f = new XLFont(null, c.RichText.Phonetics); + var f = XLFontValue.FromKey(XLFont.GenerateKey(c.RichText.Phonetics)); if (!context.SharedFonts.ContainsKey(f)) context.SharedFonts.Add(f, new FontInfo { Font = f }); var phoneticProperties = new PhoneticProperties { - FontId = - context.SharedFonts[ - new XLFont(null, c.RichText.Phonetics)]. - FontId + FontId = context.SharedFonts[f].FontId }; if (c.RichText.Phonetics.Alignment != XLPhoneticAlignment.Left) phoneticProperties.Alignment = c.RichText.Phonetics.Alignment.ToOpenXml(); @@ -1886,13 +1883,13 @@ // https://github.com/ClosedXML/ClosedXML/issues/513 if (xlField.IsConsistentStyle()) { - var style = xlField.Column.Cells() + var style = (xlField.Column.Cells() .Skip(xlTable.ShowHeaderRow ? 1 : 0) .First() - .Style; + .Style as XLStyle).Value; - if (!DefaultStyle.Equals(style) && context.DifferentialFormats.ContainsKey(style)) - tableColumn.DataFormatId = UInt32Value.FromUInt32(Convert.ToUInt32(context.DifferentialFormats[style])); + if (!DefaultStyleValue.Equals(style) && context.DifferentialFormats.ContainsKey(style.Key)) + tableColumn.DataFormatId = UInt32Value.FromUInt32(Convert.ToUInt32(context.DifferentialFormats[style.Key])); } else tableColumn.DataFormatId = null; @@ -2140,8 +2137,8 @@ ptfi.DataType = XLDataType.DateTime; ptfi.MixedDataType = false; ptfi.DistinctValues = fieldValueCells - .Select(cell => cell.GetDateTime()) - .Distinct() + .Select(cell => cell.GetDateTime()) + .Distinct() .Cast() .ToArray(); @@ -2973,35 +2970,35 @@ { case Drawings.XLPicturePlacement.FreeFloating: var absoluteAnchor = new Xdr.AbsoluteAnchor( - new Xdr.Position - { - X = ConvertToEnglishMetricUnits(pic.Left, GraphicsUtils.Graphics.DpiX), - Y = ConvertToEnglishMetricUnits(pic.Top, GraphicsUtils.Graphics.DpiY) - }, - new Xdr.Extent - { - Cx = extentsCx, - Cy = extentsCy - }, - new Xdr.Picture( - new Xdr.NonVisualPictureProperties( - new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, - new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) - ), - new Xdr.BlipFill( - new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, - new Stretch(new FillRectangle()) - ), - new Xdr.ShapeProperties( - new Transform2D( - new Offset { X = 0, Y = 0 }, - new Extents { Cx = extentsCx, Cy = extentsCy } + new Xdr.Position + { + X = ConvertToEnglishMetricUnits(pic.Left, GraphicsUtils.Graphics.DpiX), + Y = ConvertToEnglishMetricUnits(pic.Top, GraphicsUtils.Graphics.DpiY) + }, + new Xdr.Extent + { + Cx = extentsCx, + Cy = extentsCy + }, + new Xdr.Picture( + new Xdr.NonVisualPictureProperties( + new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = pic.Name }, + new Xdr.NonVisualPictureDrawingProperties(new PictureLocks { NoChangeAspect = true }) ), - new PresetGeometry { Preset = ShapeTypeValues.Rectangle } - ) - ), - new Xdr.ClientData() - ); + new Xdr.BlipFill( + new Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = BlipCompressionValues.Print }, + new Stretch(new FillRectangle()) + ), + new Xdr.ShapeProperties( + new Transform2D( + new Offset { X = 0, Y = 0 }, + new Extents { Cx = extentsCx, Cy = extentsCy } + ), + new PresetGeometry { Preset = ShapeTypeValues.Rectangle } + ) + ), + new Xdr.ClientData() + ); worksheetDrawing.Append(absoluteAnchor); break; @@ -3214,28 +3211,10 @@ private void GenerateWorkbookStylesPartContent(WorkbookStylesPart workbookStylesPart, SaveContext context) { - var defaultStyle = new XLStyle(null, DefaultStyle); - var defaultStyleId = GetStyleId(defaultStyle); + var defaultStyle = DefaultStyleValue; + if (!context.SharedFonts.ContainsKey(defaultStyle.Font)) - context.SharedFonts.Add(defaultStyle.Font, new FontInfo { FontId = 0, Font = defaultStyle.Font as XLFont }); - - var sharedFills = new Dictionary - {{defaultStyle.Fill, new FillInfo {FillId = 2, Fill = defaultStyle.Fill as XLFill}}}; - - var sharedBorders = new Dictionary - {{defaultStyle.Border, new BorderInfo {BorderId = 0, Border = defaultStyle.Border as XLBorder}}}; - - var sharedNumberFormats = new Dictionary - { - { - defaultStyle.NumberFormat, - new NumberFormatInfo - {NumberFormatId = 0, NumberFormat = defaultStyle.NumberFormat} - } - }; - - //Dictionary sharedAlignments = new Dictionary(); - //sharedAlignments.Add(defaultStyle.Alignment.ToString(), new AlignmentInfo() { AlignmentId = 0, Alignment = defaultStyle.Alignment }); + context.SharedFonts.Add(defaultStyle.Font, new FontInfo { FontId = 0, Font = defaultStyle.Font }); if (workbookStylesPart.Stylesheet == null) workbookStylesPart.Stylesheet = new Stylesheet(); @@ -3261,7 +3240,7 @@ else defaultFormatId = 0; - context.SharedStyles.Add(defaultStyleId, + context.SharedStyles.Add(defaultStyle.Key, new StyleInfo { StyleId = defaultFormatId, @@ -3278,70 +3257,76 @@ UInt32 fillCount = 3; UInt32 borderCount = 1; var numberFormatCount = 0; // 0-based - var xlStyles = new HashSet(); var pivotTableNumberFormats = new HashSet(); + var xlStyles = new HashSet(); foreach (var worksheet in WorksheetsInternal) { - foreach (var s in worksheet.GetStyleIds().Where(s => !xlStyles.Contains(s))) + xlStyles.Add(worksheet.StyleValue); + foreach (var s in worksheet.Internals.ColumnsCollection.Select(c => c.Value.StyleValue)) + { xlStyles.Add(s); + } + foreach (var s in worksheet.Internals.RowsCollection.Select(r => r.Value.StyleValue)) + { + xlStyles.Add(s); + } - foreach ( - var s in - worksheet.Internals.ColumnsCollection.Select(kp => kp.Value.GetStyleId()).Where( - s => !xlStyles.Contains(s))) + foreach (var s in worksheet.Internals.CellsCollection.GetCells().Select(c => c.StyleValue)) + { xlStyles.Add(s); - - foreach ( - var s in - worksheet.Internals.RowsCollection.Select(kp => kp.Value.GetStyleId()).Where( - s => !xlStyles.Contains(s)) - ) - xlStyles.Add(s); + } foreach (var ptnf in worksheet.PivotTables.SelectMany(pt => pt.Values.Select(ptv => ptv.NumberFormat)).Distinct().Where(nf => !pivotTableNumberFormats.Contains(nf))) pivotTableNumberFormats.Add(ptnf); } - foreach (var numberFormat in pivotTableNumberFormats) + var alignments = xlStyles.Select(s => s.Alignment).Distinct().ToList(); + var borders = xlStyles.Select(s => s.Border).Distinct().ToList(); + var fonts = xlStyles.Select(s => s.Font).Distinct().ToList(); + var fills = xlStyles.Select(s => s.Fill).Distinct().ToList(); + var numberFormats = xlStyles.Select(s => s.NumberFormat).Distinct().ToList(); + var protections = xlStyles.Select(s => s.Protection).Distinct().ToList(); + + for (int i = 0; i < fonts.Count; i++) { - if (numberFormat.NumberFormatId != -1 - || sharedNumberFormats.ContainsKey(numberFormat)) + if (!context.SharedFonts.ContainsKey(fonts[i])) + { + context.SharedFonts.Add(fonts[i], new FontInfo { FontId = (uint)fontCount++, Font = fonts[i] }); + } + } + + var sharedFills = fills.ToDictionary( + f => f, f => new FillInfo { FillId = fillCount++, Fill = f }); + + var sharedBorders = borders.ToDictionary( + b => b, b => new BorderInfo { BorderId = borderCount++, Border = b }); + + var sharedNumberFormats = numberFormats + .Where(nf => nf.NumberFormatId == -1) + .ToDictionary(nf => nf, nf => new NumberFormatInfo + { + NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount++, + NumberFormat = nf + }); + + foreach (var pivotNumberFormat in pivotTableNumberFormats.Where(nf => nf.NumberFormatId == -1)) + { + var numberFormat = XLNumberFormatValue.FromKey(new XLNumberFormatKey + { + NumberFormatId = -1, + Format = pivotNumberFormat.Format + }); + + if (sharedNumberFormats.ContainsKey(numberFormat)) continue; sharedNumberFormats.Add(numberFormat, new NumberFormatInfo { - NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount, + NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount++, NumberFormat = numberFormat }); - numberFormatCount++; - } - - foreach (var xlStyle in xlStyles.Select(GetStyleById)) - { - if (!context.SharedFonts.ContainsKey(xlStyle.Font)) - context.SharedFonts.Add(xlStyle.Font, - new FontInfo { FontId = fontCount++, Font = xlStyle.Font as XLFont }); - - if (!sharedFills.ContainsKey(xlStyle.Fill)) - sharedFills.Add(xlStyle.Fill, new FillInfo { FillId = fillCount++, Fill = xlStyle.Fill as XLFill }); - - if (!sharedBorders.ContainsKey(xlStyle.Border)) - sharedBorders.Add(xlStyle.Border, - new BorderInfo { BorderId = borderCount++, Border = xlStyle.Border as XLBorder }); - - if (xlStyle.NumberFormat.NumberFormatId != -1 - || sharedNumberFormats.ContainsKey(xlStyle.NumberFormat)) - continue; - - sharedNumberFormats.Add(xlStyle.NumberFormat, - new NumberFormatInfo - { - NumberFormatId = XLConstants.NumberOfBuiltInStyles + numberFormatCount, - NumberFormat = xlStyle.NumberFormat - }); - numberFormatCount++; } var allSharedNumberFormats = ResolveNumberFormats(workbookStylesPart, sharedNumberFormats, defaultFormatId); @@ -3354,25 +3339,23 @@ var allSharedFills = ResolveFills(workbookStylesPart, sharedFills); var allSharedBorders = ResolveBorders(workbookStylesPart, sharedBorders); - foreach (var id in xlStyles) + foreach (var xlStyle in xlStyles) { - var xlStyle = GetStyleById(id); - if (context.SharedStyles.ContainsKey(id)) continue; - var numberFormatId = xlStyle.NumberFormat.NumberFormatId >= 0 ? xlStyle.NumberFormat.NumberFormatId : allSharedNumberFormats[xlStyle.NumberFormat].NumberFormatId; - context.SharedStyles.Add(id, - new StyleInfo - { - StyleId = styleCount++, - Style = xlStyle, - FontId = context.SharedFonts[xlStyle.Font].FontId, - FillId = allSharedFills[xlStyle.Fill].FillId, - BorderId = allSharedBorders[xlStyle.Border].BorderId, - NumberFormatId = numberFormatId - }); + if (!context.SharedStyles.ContainsKey(xlStyle.Key)) + context.SharedStyles.Add(xlStyle.Key, + new StyleInfo + { + StyleId = styleCount++, + Style = xlStyle, + FontId = context.SharedFonts[xlStyle.Font].FontId, + FillId = allSharedFills[xlStyle.Fill].FillId, + BorderId = allSharedBorders[xlStyle.Border].BorderId, + NumberFormatId = numberFormatId + }); } ResolveCellStyleFormats(workbookStylesPart, context); @@ -3383,7 +3366,7 @@ workbookStylesPart.Stylesheet.CellStyles.Count = (UInt32)workbookStylesPart.Stylesheet.CellStyles.Count(); - var newSharedStyles = new Dictionary(); + var newSharedStyles = new Dictionary(); foreach (var ss in context.SharedStyles) { var styleId = -1; @@ -3416,14 +3399,15 @@ workbookStylesPart.Stylesheet.DifferentialFormats = new DifferentialFormats(); var differentialFormats = workbookStylesPart.Stylesheet.DifferentialFormats; - + differentialFormats.RemoveAllChildren(); FillDifferentialFormatsCollection(differentialFormats, context.DifferentialFormats); foreach (var ws in Worksheets) { foreach (var cf in ws.ConditionalFormats) { - if (!cf.Style.Equals(DefaultStyle) && !context.DifferentialFormats.ContainsKey(cf.Style)) + var styleValue = (cf.Style as XLStyle).Value; + if (!styleValue.Equals(DefaultStyleValue) && !context.DifferentialFormats.ContainsKey(styleValue.Key)) AddConditionalDifferentialFormat(workbookStylesPart.Stylesheet.DifferentialFormats, cf, context); } @@ -3431,12 +3415,12 @@ { if (tf.IsConsistentStyle()) { - var style = tf.Column.Cells() + var style = (tf.Column.Cells() .Skip(tf.Table.ShowHeaderRow ? 1 : 0) .First() - .Style; + .Style as XLStyle).Value; - if (!style.Equals(DefaultStyle) && !context.DifferentialFormats.ContainsKey(style)) + if (!style.Equals(DefaultStyleValue) && !context.DifferentialFormats.ContainsKey(style.Key)) AddStyleAsDifferentialFormat(workbookStylesPart.Stylesheet.DifferentialFormats, style, context); } } @@ -3448,7 +3432,7 @@ } private void FillDifferentialFormatsCollection(DifferentialFormats differentialFormats, - Dictionary dictionary) + Dictionary dictionary) { dictionary.Clear(); var id = 0; @@ -3456,18 +3440,15 @@ foreach (var df in differentialFormats.Elements()) { var emptyContainer = new XLStylizedEmpty(DefaultStyle); - emptyContainer.UpdatingStyle = true; var style = new XLStyle(emptyContainer, DefaultStyle); - LoadFont(df.Font, style.Font); - LoadBorder(df.Border, style.Border); - LoadNumberFormat(df.NumberingFormat, style.NumberFormat); - LoadFill(df.Fill, style.Fill, differentialFillFormat: true); + LoadFont(df.Font, emptyContainer.Style.Font); + LoadBorder(df.Border, emptyContainer.Style.Border); + LoadNumberFormat(df.NumberingFormat, emptyContainer.Style.NumberFormat); + LoadFill(df.Fill, emptyContainer.Style.Fill, differentialFillFormat: true); - emptyContainer.UpdatingStyle = false; - - if (!dictionary.ContainsKey(style)) - dictionary.Add(style, id++); + if (!dictionary.ContainsKey(emptyContainer.StyleValue.Key)) + dictionary.Add(emptyContainer.StyleValue.Key, id++); } } @@ -3475,8 +3456,9 @@ SaveContext context) { var differentialFormat = new DifferentialFormat(); + var styleValue = (cf.Style as XLStyle).Value; - var diffFont = GetNewFont(new FontInfo { Font = cf.Style.Font as XLFont }, false); + var diffFont = GetNewFont(new FontInfo { Font = styleValue.Font }, false); if (diffFont?.HasChildren ?? false) differentialFormat.Append(diffFont); @@ -3490,25 +3472,25 @@ differentialFormat.Append(numberFormat); } - var diffFill = GetNewFill(new FillInfo { Fill = cf.Style.Fill as XLFill }, differentialFillFormat: true, ignoreMod: false); + var diffFill = GetNewFill(new FillInfo { Fill = styleValue.Fill }, differentialFillFormat: true, ignoreMod: false); if (diffFill?.HasChildren ?? false) differentialFormat.Append(diffFill); - var diffBorder = GetNewBorder(new BorderInfo { Border = cf.Style.Border as XLBorder }, false); + var diffBorder = GetNewBorder(new BorderInfo { Border = styleValue.Border }, false); if (diffBorder?.HasChildren ?? false) differentialFormat.Append(diffBorder); differentialFormats.Append(differentialFormat); - context.DifferentialFormats.Add(cf.Style, differentialFormats.Count() - 1); + context.DifferentialFormats.Add(styleValue.Key, differentialFormats.Count() - 1); } - private static void AddStyleAsDifferentialFormat(DifferentialFormats differentialFormats, IXLStyle style, + private static void AddStyleAsDifferentialFormat(DifferentialFormats differentialFormats, XLStyleValue style, SaveContext context) { var differentialFormat = new DifferentialFormat(); - var diffFont = GetNewFont(new FontInfo { Font = style.Font as XLFont }, false); + var diffFont = GetNewFont(new FontInfo { Font = style.Font }, false); if (diffFont?.HasChildren ?? false) differentialFormat.Append(diffFont); @@ -3536,17 +3518,17 @@ differentialFormat.Append(numberFormat); } - var diffFill = GetNewFill(new FillInfo { Fill = style.Fill as XLFill }, differentialFillFormat: true, ignoreMod: false); + var diffFill = GetNewFill(new FillInfo { Fill = style.Fill }, differentialFillFormat: true, ignoreMod: false); if (diffFill?.HasChildren ?? false) differentialFormat.Append(diffFill); - var diffBorder = GetNewBorder(new BorderInfo { Border = style.Border as XLBorder }, false); + var diffBorder = GetNewBorder(new BorderInfo { Border = style.Border }, false); if (diffBorder?.HasChildren ?? false) differentialFormat.Append(diffBorder); differentialFormats.Append(differentialFormat); - context.DifferentialFormats.Add(style, differentialFormats.Count() - 1); + context.DifferentialFormats.Add(style.Key, differentialFormats.Count() - 1); } private static void ResolveRest(WorkbookStylesPart workbookStylesPart, SaveContext context) @@ -3665,16 +3647,18 @@ && f.FillId != null && styleInfo.FillId == f.FillId && f.FontId != null && styleInfo.FontId == f.FontId && f.NumberFormatId != null && styleInfo.NumberFormatId == f.NumberFormatId - && f.ApplyFill != null && f.ApplyFill == ApplyFill(styleInfo) - && f.ApplyBorder != null && f.ApplyBorder == ApplyBorder(styleInfo) + && (f.ApplyFill == null && styleInfo.Style.Fill == XLFillValue.Default || + f.ApplyFill != null && f.ApplyFill == ApplyFill(styleInfo)) + && (f.ApplyBorder == null && styleInfo.Style.Border == XLBorderValue.Default || + f.ApplyBorder != null && f.ApplyBorder == ApplyBorder(styleInfo)) && (f.Alignment == null || AlignmentsAreEqual(f.Alignment, styleInfo.Style.Alignment)) && ProtectionsAreEqual(f.Protection, styleInfo.Style.Protection) ; } - private static bool ProtectionsAreEqual(Protection protection, IXLProtection xlProtection) + private static bool ProtectionsAreEqual(Protection protection, XLProtectionValue xlProtection) { - var p = new XLProtection(); + var p = XLProtectionValue.Default.Key; if (protection != null) { if (protection.Locked != null) @@ -3682,14 +3666,14 @@ if (protection.Hidden != null) p.Hidden = protection.Hidden.Value; } - return p.Equals(xlProtection); + return p.Equals(xlProtection.Key); } - private static bool AlignmentsAreEqual(Alignment alignment, IXLAlignment xlAlignment) + private static bool AlignmentsAreEqual(Alignment alignment, XLAlignmentValue xlAlignment) { - var a = new XLAlignment(); if (alignment != null) { + var a = XLAlignmentValue.Default.Key; if (alignment.Indent != null) a.Indent = (Int32)alignment.Indent.Value; @@ -3710,17 +3694,21 @@ a.RelativeIndent = alignment.RelativeIndent.Value; if (alignment.JustifyLastLine != null) a.JustifyLastLine = alignment.JustifyLastLine.Value; + return a.Equals(xlAlignment.Key); } - return a.Equals(xlAlignment); + else + { + return XLStyle.Default.Value.Alignment.Equals(xlAlignment); + } } - private Dictionary ResolveBorders(WorkbookStylesPart workbookStylesPart, - Dictionary sharedBorders) + private Dictionary ResolveBorders(WorkbookStylesPart workbookStylesPart, + Dictionary sharedBorders) { if (workbookStylesPart.Stylesheet.Borders == null) workbookStylesPart.Stylesheet.Borders = new Borders(); - var allSharedBorders = new Dictionary(); + var allSharedBorders = new Dictionary(); foreach (var borderInfo in sharedBorders.Values) { var borderId = 0; @@ -3749,16 +3737,16 @@ private static Border GetNewBorder(BorderInfo borderInfo, Boolean ignoreMod = true) { var border = new Border(); - if (borderInfo.Border.DiagonalUpModified || ignoreMod) + if (borderInfo.Border.DiagonalUp != XLBorderValue.Default.DiagonalUp || ignoreMod) border.DiagonalUp = borderInfo.Border.DiagonalUp; - if (borderInfo.Border.DiagonalDownModified || ignoreMod) + if (borderInfo.Border.DiagonalDown != XLBorderValue.Default.DiagonalDown || ignoreMod) border.DiagonalDown = borderInfo.Border.DiagonalDown; - if (borderInfo.Border.LeftBorderModified || borderInfo.Border.LeftBorderColorModified || ignoreMod) + if (borderInfo.Border.LeftBorder != XLBorderValue.Default.LeftBorder || ignoreMod) { var leftBorder = new LeftBorder { Style = borderInfo.Border.LeftBorder.ToOpenXml() }; - if (borderInfo.Border.LeftBorderColorModified || ignoreMod) + if (borderInfo.Border.LeftBorderColor != XLBorderValue.Default.LeftBorderColor || ignoreMod) { var leftBorderColor = GetNewColor(borderInfo.Border.LeftBorderColor); leftBorder.AppendChild(leftBorderColor); @@ -3766,10 +3754,10 @@ border.AppendChild(leftBorder); } - if (borderInfo.Border.RightBorderModified || borderInfo.Border.RightBorderColorModified || ignoreMod) + if (borderInfo.Border.RightBorder != XLBorderValue.Default.RightBorder || ignoreMod) { var rightBorder = new RightBorder { Style = borderInfo.Border.RightBorder.ToOpenXml() }; - if (borderInfo.Border.RightBorderColorModified || ignoreMod) + if (borderInfo.Border.RightBorderColor != XLBorderValue.Default.RightBorderColor || ignoreMod) { var rightBorderColor = GetNewColor(borderInfo.Border.RightBorderColor); rightBorder.AppendChild(rightBorderColor); @@ -3777,10 +3765,10 @@ border.AppendChild(rightBorder); } - if (borderInfo.Border.TopBorderModified || borderInfo.Border.TopBorderColorModified || ignoreMod) + if (borderInfo.Border.TopBorder != XLBorderValue.Default.TopBorder || ignoreMod) { var topBorder = new TopBorder { Style = borderInfo.Border.TopBorder.ToOpenXml() }; - if (borderInfo.Border.TopBorderColorModified || ignoreMod) + if (borderInfo.Border.TopBorderColor != XLBorderValue.Default.TopBorderColor || ignoreMod) { var topBorderColor = GetNewColor(borderInfo.Border.TopBorderColor); topBorder.AppendChild(topBorderColor); @@ -3788,10 +3776,10 @@ border.AppendChild(topBorder); } - if (borderInfo.Border.BottomBorderModified || borderInfo.Border.BottomBorderColorModified || ignoreMod) + if (borderInfo.Border.BottomBorder != XLBorderValue.Default.BottomBorder || ignoreMod) { var bottomBorder = new BottomBorder { Style = borderInfo.Border.BottomBorder.ToOpenXml() }; - if (borderInfo.Border.BottomBorderColorModified || ignoreMod) + if (borderInfo.Border.BottomBorderColor != XLBorderValue.Default.BottomBorderColor || ignoreMod) { var bottomBorderColor = GetNewColor(borderInfo.Border.BottomBorderColor); bottomBorder.AppendChild(bottomBorderColor); @@ -3799,23 +3787,24 @@ border.AppendChild(bottomBorder); } - if (borderInfo.Border.DiagonalBorderModified || borderInfo.Border.DiagonalBorderColorModified || ignoreMod) + if (borderInfo.Border.DiagonalBorder != XLBorderValue.Default.DiagonalBorder || ignoreMod) { var DiagonalBorder = new DiagonalBorder { Style = borderInfo.Border.DiagonalBorder.ToOpenXml() }; - if (borderInfo.Border.DiagonalBorderColorModified || ignoreMod) - { - var DiagonalBorderColor = GetNewColor(borderInfo.Border.DiagonalBorderColor); - DiagonalBorder.AppendChild(DiagonalBorderColor); - } + if (borderInfo.Border.DiagonalBorderColor != XLBorderValue.Default.DiagonalBorderColor || ignoreMod) + if (borderInfo.Border.DiagonalBorderColor != null) + { + var DiagonalBorderColor = GetNewColor(borderInfo.Border.DiagonalBorderColor); + DiagonalBorder.AppendChild(DiagonalBorderColor); + } border.AppendChild(DiagonalBorder); } return border; } - private bool BordersAreEqual(Border b, IXLBorder xlBorder) + private bool BordersAreEqual(Border b, XLBorderValue xlBorder) { - var nb = new XLBorder(); + var nb = XLBorderValue.Default.Key; if (b.DiagonalUp != null) nb.DiagonalUp = b.DiagonalUp.Value; @@ -3828,7 +3817,7 @@ nb.DiagonalBorder = b.DiagonalBorder.Style.Value.ToClosedXml(); var bColor = GetColor(b.DiagonalBorder.Color); if (bColor.HasValue) - nb.DiagonalBorderColor = bColor; + nb.DiagonalBorderColor = bColor.Key; } if (b.LeftBorder != null) @@ -3837,7 +3826,7 @@ nb.LeftBorder = b.LeftBorder.Style.Value.ToClosedXml(); var bColor = GetColor(b.LeftBorder.Color); if (bColor.HasValue) - nb.LeftBorderColor = bColor; + nb.LeftBorderColor = bColor.Key; } if (b.RightBorder != null) @@ -3846,7 +3835,7 @@ nb.RightBorder = b.RightBorder.Style.Value.ToClosedXml(); var bColor = GetColor(b.RightBorder.Color); if (bColor.HasValue) - nb.RightBorderColor = bColor; + nb.RightBorderColor = bColor.Key; } if (b.TopBorder != null) @@ -3855,7 +3844,7 @@ nb.TopBorder = b.TopBorder.Style.Value.ToClosedXml(); var bColor = GetColor(b.TopBorder.Color); if (bColor.HasValue) - nb.TopBorderColor = bColor; + nb.TopBorderColor = bColor.Key; } if (b.BottomBorder != null) @@ -3864,14 +3853,14 @@ nb.BottomBorder = b.BottomBorder.Style.Value.ToClosedXml(); var bColor = GetColor(b.BottomBorder.Color); if (bColor.HasValue) - nb.BottomBorderColor = bColor; + nb.BottomBorderColor = bColor.Key; } - return nb.Equals(xlBorder); + return nb.Equals(xlBorder.Key); } - private Dictionary ResolveFills(WorkbookStylesPart workbookStylesPart, - Dictionary sharedFills) + private Dictionary ResolveFills(WorkbookStylesPart workbookStylesPart, + Dictionary sharedFills) { if (workbookStylesPart.Stylesheet.Fills == null) workbookStylesPart.Stylesheet.Fills = new Fills(); @@ -3879,7 +3868,7 @@ ResolveFillWithPattern(workbookStylesPart.Stylesheet.Fills, PatternValues.None); ResolveFillWithPattern(workbookStylesPart.Stylesheet.Fills, PatternValues.Gray125); - var allSharedFills = new Dictionary(); + var allSharedFills = new Dictionary(); foreach (var fillInfo in sharedFills.Values) { var fillId = 0; @@ -4044,13 +4033,13 @@ return fill; } - private bool FillsAreEqual(Fill f, IXLFill xlFill, Boolean fromDifferentialFormat) + private bool FillsAreEqual(Fill f, XLFillValue xlFill, Boolean fromDifferentialFormat) { - var nF = new XLFill(); + var nF = new XLFill(null); LoadFill(f, nF, fromDifferentialFormat); - return nF.Equals(xlFill); + return nF.Key.Equals(xlFill.Key); } private void ResolveFonts(WorkbookStylesPart workbookStylesPart, SaveContext context) @@ -4058,7 +4047,7 @@ if (workbookStylesPart.Stylesheet.Fonts == null) workbookStylesPart.Stylesheet.Fonts = new Fonts(); - var newFonts = new Dictionary(); + var newFonts = new Dictionary(); foreach (var fontInfo in context.SharedFonts.Values) { var fontId = 0; @@ -4089,32 +4078,33 @@ private static Font GetNewFont(FontInfo fontInfo, Boolean ignoreMod = true) { var font = new Font(); - var bold = (fontInfo.Font.BoldModified || ignoreMod) && fontInfo.Font.Bold ? new Bold() : null; - var italic = (fontInfo.Font.ItalicModified || ignoreMod) && fontInfo.Font.Italic ? new Italic() : null; - var underline = (fontInfo.Font.UnderlineModified || ignoreMod) && + var bold = (fontInfo.Font.Bold != XLFontValue.Default.Bold || ignoreMod) && fontInfo.Font.Bold ? new Bold() : null; + var italic = (fontInfo.Font.Italic != XLFontValue.Default.Italic || ignoreMod) && fontInfo.Font.Italic ? new Italic() : null; + var underline = (fontInfo.Font.Underline != XLFontValue.Default.Underline || ignoreMod) && fontInfo.Font.Underline != XLFontUnderlineValues.None ? new Underline { Val = fontInfo.Font.Underline.ToOpenXml() } : null; - var strike = (fontInfo.Font.StrikethroughModified || ignoreMod) && fontInfo.Font.Strikethrough + var strike = (fontInfo.Font.Strikethrough != XLFontValue.Default.Strikethrough || ignoreMod) && fontInfo.Font.Strikethrough ? new Strike() : null; - var verticalAlignment = fontInfo.Font.VerticalAlignmentModified || ignoreMod + var verticalAlignment = fontInfo.Font.VerticalAlignment != XLFontValue.Default.VerticalAlignment || ignoreMod ? new VerticalTextAlignment { Val = fontInfo.Font.VerticalAlignment.ToOpenXml() } : null; - var shadow = (fontInfo.Font.ShadowModified || ignoreMod) && fontInfo.Font.Shadow ? new Shadow() : null; - var fontSize = fontInfo.Font.FontSizeModified || ignoreMod + + var shadow = (fontInfo.Font.Shadow != XLFontValue.Default.Shadow || ignoreMod) && fontInfo.Font.Shadow ? new Shadow() : null; + var fontSize = fontInfo.Font.FontSize != XLFontValue.Default.FontSize || ignoreMod ? new FontSize { Val = fontInfo.Font.FontSize } : null; - var color = fontInfo.Font.FontColorModified || ignoreMod ? GetNewColor(fontInfo.Font.FontColor) : null; + var color = fontInfo.Font.FontColor != XLFontValue.Default.FontColor || ignoreMod ? GetNewColor(fontInfo.Font.FontColor) : null; - var fontName = fontInfo.Font.FontNameModified || ignoreMod + var fontName = fontInfo.Font.FontName != XLFontValue.Default.FontName || ignoreMod ? new FontName { Val = fontInfo.Font.FontName } : null; - var fontFamilyNumbering = fontInfo.Font.FontFamilyNumberingModified || ignoreMod + var fontFamilyNumbering = fontInfo.Font.FontFamilyNumbering != XLFontValue.Default.FontFamilyNumbering || ignoreMod ? new FontFamilyNumbering { Val = (Int32)fontInfo.Font.FontFamilyNumbering } : null; - var fontCharSet = (fontInfo.Font.FontCharSetModified || ignoreMod) && fontInfo.Font.FontCharSet != XLFontCharSet.Default + var fontCharSet = (fontInfo.Font.FontCharSet != XLFontValue.Default.FontCharSet || ignoreMod) && fontInfo.Font.FontCharSet != XLFontCharSet.Default ? new FontCharSet { Val = (Int32)fontInfo.Font.FontCharSet } : null; @@ -4176,9 +4166,12 @@ return color; } - private bool FontsAreEqual(Font f, IXLFont xlFont) + private bool FontsAreEqual(Font f, XLFontValue xlFont) { - var nf = new XLFont { Bold = f.Bold != null, Italic = f.Italic != null }; + var nf = XLFontValue.Default.Key; + nf.Bold = f.Bold != null; + nf.Italic = f.Italic != null; + if (f.Underline != null) { nf.Underline = f.Underline.Val != null @@ -4197,18 +4190,18 @@ nf.FontSize = f.FontSize.Val; var fColor = GetColor(f.Color); if (fColor.HasValue) - nf.FontColor = fColor; + nf.FontColor = fColor.Key; if (f.FontName != null) nf.FontName = f.FontName.Val; if (f.FontFamilyNumbering != null) nf.FontFamilyNumbering = (XLFontFamilyNumberingValues)f.FontFamilyNumbering.Val.Value; - return nf.Equals(xlFont); + return nf.Equals(xlFont.Key); } - private static Dictionary ResolveNumberFormats( + private static Dictionary ResolveNumberFormats( WorkbookStylesPart workbookStylesPart, - Dictionary sharedNumberFormats, + Dictionary sharedNumberFormats, UInt32 defaultFormatId) { if (workbookStylesPart.Stylesheet.NumberingFormats == null) @@ -4221,7 +4214,7 @@ }); } - var allSharedNumberFormats = new Dictionary(); + var allSharedNumberFormats = new Dictionary(); foreach (var numberFormatInfo in sharedNumberFormats.Values.Where(nf => nf.NumberFormatId != defaultFormatId)) { var numberingFormatId = XLConstants.NumberOfBuiltInStyles; // 0-based @@ -4257,16 +4250,13 @@ return allSharedNumberFormats; } - private static bool NumberFormatsAreEqual(NumberingFormat nf, IXLNumberFormatBase xlNumberFormat) + private static bool NumberFormatsAreEqual(NumberingFormat nf, XLNumberFormatValue xlNumberFormat) { - var newXLNumberFormat = new XLNumberFormat(); - if (nf.FormatCode != null && !String.IsNullOrWhiteSpace(nf.FormatCode.Value)) - newXLNumberFormat.Format = nf.FormatCode.Value; + return string.Equals(xlNumberFormat?.Format, nf.FormatCode.Value); else if (nf.NumberFormatId != null) - newXLNumberFormat.NumberFormatId = (Int32)nf.NumberFormatId.Value; - - return newXLNumberFormat.Equals(xlNumberFormat); + return xlNumberFormat?.NumberFormatId == (Int32)nf.NumberFormatId.Value; + return false; } #endregion GenerateWorkbookStylesPartContent @@ -4457,13 +4447,14 @@ var seqRef = new List { selection.ActiveCell.Value }; seqRef.AddRange(xlWorksheet.SelectedRanges - .Select(range => - { - if (range.RangeAddress.FirstAddress.Equals(range.RangeAddress.LastAddress)) - return range.RangeAddress.FirstAddress.ToStringRelative(false); - else - return range.RangeAddress.ToStringRelative(false); - })); + .Select(range => + { + if (range.RangeAddress.FirstAddress.Equals(range.RangeAddress.LastAddress)) + return range.RangeAddress.FirstAddress.ToStringRelative(false); + else + return range.RangeAddress.ToStringRelative(false); + }) + ); selection.SequenceOfReferences = new ListValue { InnerText = String.Join(" ", seqRef.Distinct().ToArray()) }; @@ -4577,7 +4568,7 @@ maxInColumnsCollection = 0; } - var worksheetStyleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; + var worksheetStyleId = context.SharedStyles[xlWorksheet.StyleValue.Key].StyleId; if (minInColumnsCollection > 1) { UInt32Value min = 1; @@ -4607,7 +4598,7 @@ var outlineLevel = 0; if (xlWorksheet.Internals.ColumnsCollection.ContainsKey(co)) { - styleId = context.SharedStyles[xlWorksheet.Internals.ColumnsCollection[co].GetStyleId()].StyleId; + styleId = context.SharedStyles[xlWorksheet.Internals.ColumnsCollection[co].StyleValue.Key].StyleId; columnWidth = GetColumnWidth(xlWorksheet.Internals.ColumnsCollection[co].Width).SaveRound(); isHidden = xlWorksheet.Internals.ColumnsCollection[co].IsHidden; collapsed = xlWorksheet.Internals.ColumnsCollection[co].Collapsed; @@ -4615,7 +4606,7 @@ } else { - styleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; + styleId = context.SharedStyles[xlWorksheet.StyleValue.Key].StyleId; columnWidth = worksheetColumnWidth; } @@ -4652,7 +4643,7 @@ maxInColumnsCollection = (Int32)col.Max.Value; } - if (maxInColumnsCollection < XLHelper.MaxColumnNumber && !xlWorksheet.Style.Equals(DefaultStyle)) + if (maxInColumnsCollection < XLHelper.MaxColumnNumber && !xlWorksheet.StyleValue.Equals(DefaultStyleValue)) { var column = new Column { @@ -4736,9 +4727,9 @@ row.CustomFormat = true; } - if (thisRow.GetStyleId() != xlWorksheet.GetStyleId()) + if (thisRow.StyleValue != xlWorksheet.StyleValue) { - row.StyleIndex = context.SharedStyles[thisRow.GetStyleId()].StyleId; + row.StyleIndex = context.SharedStyles[thisRow.StyleValue.Key].StyleId; row.CustomFormat = true; } @@ -4781,7 +4772,7 @@ { XLTableField field = null; - var styleId = context.SharedStyles[xlCell.GetStyleId()].StyleId; + var styleId = context.SharedStyles[xlCell.StyleValue.Key].StyleId; var cellReference = (xlCell.Address).GetTrimmedAddress(); // For saving cells to file, ignore conditional formatting. They just bloat the file diff --git a/ClosedXML/Excel/XLWorksheet.cs b/ClosedXML/Excel/XLWorksheet.cs index cdd2d65..b29631d 100644 --- a/ClosedXML/Excel/XLWorksheet.cs +++ b/ClosedXML/Excel/XLWorksheet.cs @@ -38,7 +38,8 @@ : base( new XLRangeAddress( new XLAddress(null, XLHelper.MinRowNumber, XLHelper.MinColumnNumber, false, false), - new XLAddress(null, XLHelper.MaxRowNumber, XLHelper.MaxColumnNumber, false, false))) + new XLAddress(null, XLHelper.MaxRowNumber, XLHelper.MaxColumnNumber, false, false)), + (workbook.Style as XLStyle).Value) { EventTrackingEnabled = workbook.EventTracking == XLEventTracking.Enabled; @@ -61,7 +62,6 @@ Protection = new XLSheetProtection(); AutoFilter = new XLAutoFilter(); ConditionalFormats = new XLConditionalFormats(); - SetStyle(workbook.Style); Internals = new XLWorksheetInternals(new XLCellsCollection(), new XLColumnsCollection(), new XLRowsCollection(), new XLRanges()); PageSetup = new XLPageSetup((XLPageSetup)workbook.PageOptions, this); @@ -101,20 +101,21 @@ { get { - UpdatingStyle = true; yield return GetStyle(); foreach (XLCell c in Internals.CellsCollection.GetCells()) yield return c.Style; - UpdatingStyle = false; } } - public override Boolean UpdatingStyle { get; set; } - - public override IXLStyle InnerStyle + protected override IEnumerable Children { - get { return GetStyle(); } - set { SetStyle(value); } + get + { + foreach (var col in ColumnsUsed(true).OfType()) + yield return col; + foreach (var row in RowsUsed(true).OfType()) + yield return row; + } } internal Boolean RowHeightChanged { get; set; } @@ -131,20 +132,6 @@ public XLWorkbook Workbook { get; private set; } - public override IXLStyle Style - { - get - { - return GetStyle(); - } - set - { - SetStyle(value); - foreach (XLCell cell in Internals.CellsCollection.GetCells()) - cell.Style = value; - } - } - public Double ColumnWidth { get { return _columnWidth; } @@ -576,7 +563,7 @@ targetSheet.ColumnWidthChanged = ColumnWidthChanged; targetSheet.RowHeight = RowHeight; targetSheet.RowHeightChanged = RowHeightChanged; - targetSheet.SetStyle(Style); + targetSheet.InnerStyle = InnerStyle; targetSheet.PageSetup = new XLPageSetup((XLPageSetup)PageSetup, targetSheet); (targetSheet.PageSetup.Header as XLHeaderFooter).Changed = true; (targetSheet.PageSetup.Footer as XLHeaderFooter).Changed = true; @@ -1051,11 +1038,6 @@ #endregion Outlines - public HashSet GetStyleIds() - { - return Internals.CellsCollection.GetStyleIds(GetStyleId()); - } - public XLRow FirstRowUsed() { return FirstRowUsed(false); @@ -1135,17 +1117,17 @@ throw new IndexOutOfRangeException(String.Format("Column number must be between 1 and {0}", XLHelper.MaxColumnNumber)); - Int32 thisStyleId = GetStyleId(); + var thisStyle = Style; if (!Internals.ColumnsCollection.ContainsKey(column)) { // This is a new row so we're going to reference all // cells in this row to preserve their formatting Internals.RowsCollection.Keys.ForEach(r => Cell(r, column)); Internals.ColumnsCollection.Add(column, - new XLColumn(column, new XLColumnParameters(this, thisStyleId, false))); + new XLColumn(column, new XLColumnParameters(this, thisStyle, false))); } - return new XLColumn(column, new XLColumnParameters(this, thisStyleId, true)); + return new XLColumn(column, new XLColumnParameters(this, thisStyle, true)); } public IXLColumn Column(String column) @@ -1365,10 +1347,10 @@ throw new IndexOutOfRangeException(String.Format("Row number must be between 1 and {0}", XLHelper.MaxRowNumber)); - Int32 styleId; + IXLStyle style; XLRow rowToUse; if (Internals.RowsCollection.TryGetValue(row, out rowToUse)) - styleId = rowToUse.GetStyleId(); + style = rowToUse.Style; else { if (pingCells) @@ -1384,11 +1366,11 @@ usedColumns.ForEach(c => Cell(row, c)); } - styleId = GetStyleId(); - Internals.RowsCollection.Add(row, new XLRow(row, new XLRowParameters(this, styleId, false))); + style = Style; + Internals.RowsCollection.Add(row, new XLRow(row, new XLRowParameters(this, style, false))); } - return new XLRow(row, new XLRowParameters(this, styleId)); + return new XLRow(row, new XLRowParameters(this, style)); } private IXLRange GetRangeForSort() diff --git a/ClosedXML/XLHelper.cs b/ClosedXML/XLHelper.cs index 76d2b7b..e505099 100644 --- a/ClosedXML/XLHelper.cs +++ b/ClosedXML/XLHelper.cs @@ -85,9 +85,9 @@ private static readonly string[] letters = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; /// - /// Gets the column letter of a given column number. + /// Gets the column letter of a given column number. /// - /// The column number to translate into a column letter. + /// The column number to translate into a column letter. /// if set to true the column letter will be restricted to the allowed range. /// public static string GetColumnLetterFromNumber(int columnNumber, bool trimToAllowed = false) diff --git a/ClosedXML_Examples/Creating/CreateFiles.cs b/ClosedXML_Examples/Creating/CreateFiles.cs index c61315c..8f1978f 100644 --- a/ClosedXML_Examples/Creating/CreateFiles.cs +++ b/ClosedXML_Examples/Creating/CreateFiles.cs @@ -88,7 +88,7 @@ new ShiftingFormulas().Create(Path.Combine(path, "ShiftingFormulas.xlsx")); new CopyingRowsAndColumns().Create(Path.Combine(path, "CopyingRowsAndColumns.xlsx")); new UsingRichText().Create(Path.Combine(path, "UsingRichText.xlsx")); - //new UsingPhonetics().Create(Path.Combine(path, "UsingPhonetics.xlsx")); + new UsingPhonetics().Create(Path.Combine(path, "UsingPhonetics.xlsx")); new WalkingRanges().Create(Path.Combine(path, "CellMoves.xlsx")); new AddingComments().Create(Path.Combine(path, "AddingComments.xlsx")); new PivotTables().Create(Path.Combine(path, "PivotTables.xlsx")); diff --git a/ClosedXML_Tests/Excel/Caching/SampleRepositoryTests.cs b/ClosedXML_Tests/Excel/Caching/SampleRepositoryTests.cs new file mode 100644 index 0000000..2cbbb5f --- /dev/null +++ b/ClosedXML_Tests/Excel/Caching/SampleRepositoryTests.cs @@ -0,0 +1,153 @@ +using ClosedXML.Excel.Caching; +using NUnit.Framework; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; + +namespace ClosedXML_Tests.Excel.Caching +{ + [TestFixture] + public class BaseRepositoryTests + { + [Test] + public void DifferentEntitiesWithSameKeyStoredOnce() + { + // Arrange + int key = 12345; + var entity1 = new SampleEntity(key); + var entity2 = new SampleEntity(key); + var sampleRepository = this.CreateSampleRepository(); + + // Act + var storedEntity1 = sampleRepository.Store(key, entity1); + var storedEntity2 = sampleRepository.Store(key, entity2); + + // Assert + Assert.AreSame(entity1, storedEntity1); + Assert.AreSame(entity1, storedEntity2); + Assert.AreNotSame(entity2, storedEntity2); + } + + + [Test] + public void NonUsedReferencesAreGCed() + { +#if !DEBUG + // Arrange + int key = 12345; + var sampleRepository = this.CreateSampleRepository(); + + // Act + var storedEntityRef1 = new WeakReference(sampleRepository.Store(key, new SampleEntity(key))); + + int count = 0; + do + { + Thread.Sleep(50); + GC.Collect(); + count++; + } while (storedEntityRef1.IsAlive && count < 10); + + // Assert + if (count == 10) + Assert.Fail("storedEntityRef1 was not GCed"); + + Assert.IsFalse(sampleRepository.Any()); +#else + Assert.Ignore("Can't run in DEBUG"); +#endif + } + + + [Test] + public void NonUsedReferencesAreGCed2() + { +#if !DEBUG + // Arrange + int countUnique = 30; + int repeatCount = 1000; + SampleEntity[] entities = new SampleEntity[countUnique * repeatCount]; + for (int i = 0; i < countUnique; i++) + { + for (int j = 0; j < repeatCount; j++) + { + entities[i * repeatCount + j] = new SampleEntity(i); + } + } + + var sampleRepository = this.CreateSampleRepository(); + + // Act + Parallel.ForEach(entities, new ParallelOptions { MaxDegreeOfParallelism = 8 }, + e => sampleRepository.Store(e.Key, e)); + + Thread.Sleep(50); + GC.Collect(); + var storedEntries = sampleRepository.ToList(); + + // Assert + Assert.AreEqual(0, storedEntries.Count); +#else + Assert.Ignore("Can't run in DEBUG"); +#endif + } + + [Test] + public void ConcurrentAddingCausesNoDuplication() + { + // Arrange + int countUnique = 30; + int repeatCount = 1000; + SampleEntity[] entities = new SampleEntity[countUnique * repeatCount]; + for (int i = 0; i < countUnique; i++) + { + for (int j = 0; j < repeatCount; j++) + { + entities[i * repeatCount + j] = new SampleEntity(i); + } + } + + var sampleRepository = this.CreateSampleRepository(); + + // Act + Parallel.ForEach(entities, new ParallelOptions { MaxDegreeOfParallelism = 8 }, + e => sampleRepository.Store(e.Key, e)); + var storedEntries = sampleRepository.ToList(); + + // Assert + Assert.AreEqual(countUnique, storedEntries.Count); + Assert.NotNull(entities); // To protect them from GC + } + + + private SampleRepository CreateSampleRepository() + { + return new SampleRepository(); + } + + + /// + /// Class under testing + /// + internal class SampleRepository : XLRepositoryBase + { + public SampleRepository() : base(key => new SampleEntity(key)) + { + } + } + + public class SampleEntity + { + public int Key { get; private set; } + + public SampleEntity(int key) + { + Key = key; + } + } + } + + +} diff --git a/ClosedXML_Tests/Excel/Columns/ColumnTests.cs b/ClosedXML_Tests/Excel/Columns/ColumnTests.cs index 1a34b9e..35dc053 100644 --- a/ClosedXML_Tests/Excel/Columns/ColumnTests.cs +++ b/ClosedXML_Tests/Excel/Columns/ColumnTests.cs @@ -241,7 +241,7 @@ { var ws = new XLWorkbook().AddWorksheet("Sheet1") as XLWorksheet; - var column = new XLColumn(-1, new XLColumnParameters(ws, 0, false)); + var column = new XLColumn(-1, new XLColumnParameters(ws, XLStyle.Default, false)); Assert.IsFalse(column.RangeAddress.IsValid); } diff --git a/ClosedXML_Tests/Excel/Rows/RowTests.cs b/ClosedXML_Tests/Excel/Rows/RowTests.cs index 6453623..5314b54 100644 --- a/ClosedXML_Tests/Excel/Rows/RowTests.cs +++ b/ClosedXML_Tests/Excel/Rows/RowTests.cs @@ -259,7 +259,7 @@ { var ws = new XLWorkbook().AddWorksheet("Sheet1") as XLWorksheet; - var row = new XLRow(-1, new XLRowParameters(ws, 0, false)); + var row = new XLRow(-1, new XLRowParameters(ws, XLStyle.Default, false)); Assert.IsFalse(row.RangeAddress.IsValid); } diff --git a/ClosedXML_Tests/Excel/Styles/StyleChangeTests.cs b/ClosedXML_Tests/Excel/Styles/StyleChangeTests.cs new file mode 100644 index 0000000..fcfc50d --- /dev/null +++ b/ClosedXML_Tests/Excel/Styles/StyleChangeTests.cs @@ -0,0 +1,136 @@ +using ClosedXML.Excel; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClosedXML_Tests.Excel.Styles +{ + [TestFixture] + public class StyleChangeTests + { + [Test] + public void ChangeFontColorDoesNotAffectOtherProperties() + { + using (var wb = new XLWorkbook()) + { + // Arrange + var ws = wb.AddWorksheet("Sheet1"); + var a1 = ws.Cell("A1"); + var a2 = ws.Cell("A2"); + var b1 = ws.Cell("B1"); + var b2 = ws.Cell("B2"); + + ws.Range("A1:B2").Value = "Test"; + + a1.Style.Fill.BackgroundColor = XLColor.Red; + a2.Style.Fill.BackgroundColor = XLColor.Green; + b1.Style.Fill.BackgroundColor = XLColor.Blue; + b2.Style.Fill.BackgroundColor = XLColor.Pink; + + a1.Style.Font.FontName = "Arial"; + a2.Style.Font.FontName = "Times New Roman"; + b1.Style.Font.FontName = "Calibri"; + b2.Style.Font.FontName = "Cambria"; + + // Act + ws.Range("A1:B2").Style.Font.FontColor = XLColor.PowderBlue; + + //Assert + Assert.AreEqual(XLColor.Red, ws.Cell("A1").Style.Fill.BackgroundColor); + Assert.AreEqual(XLColor.Green, ws.Cell("A2").Style.Fill.BackgroundColor); + Assert.AreEqual(XLColor.Blue, ws.Cell("B1").Style.Fill.BackgroundColor); + Assert.AreEqual(XLColor.Pink, ws.Cell("B2").Style.Fill.BackgroundColor); + + Assert.AreEqual("Arial", ws.Cell("A1").Style.Font.FontName); + Assert.AreEqual("Times New Roman", ws.Cell("A2").Style.Font.FontName); + Assert.AreEqual("Calibri", ws.Cell("B1").Style.Font.FontName); + Assert.AreEqual("Cambria", ws.Cell("B2").Style.Font.FontName); + + Assert.AreEqual(XLColor.PowderBlue, ws.Cell("A1").Style.Font.FontColor); + Assert.AreEqual(XLColor.PowderBlue, ws.Cell("A2").Style.Font.FontColor); + Assert.AreEqual(XLColor.PowderBlue, ws.Cell("B1").Style.Font.FontColor); + Assert.AreEqual(XLColor.PowderBlue, ws.Cell("B2").Style.Font.FontColor); + } + } + + + [Test] + public void ChangeDetachedStyleAlignment() + { + var style = XLStyle.Default; + + style.Alignment.Horizontal = XLAlignmentHorizontalValues.Justify; + + Assert.AreEqual(XLAlignmentHorizontalValues.Justify, style.Alignment.Horizontal); + } + + [Test] + public void ChangeDetachedStyleBorder() + { + var style = XLStyle.Default; + + style.Border.DiagonalBorder = XLBorderStyleValues.Double; + + Assert.AreEqual(XLBorderStyleValues.Double, style.Border.DiagonalBorder); + } + + [Test] + public void ChangeDetachedStyleFill() + { + var style = XLStyle.Default; + + style.Fill.BackgroundColor = XLColor.Red; + + Assert.AreEqual(XLColor.Red, style.Fill.BackgroundColor); + } + + + [Test] + public void ChangeDetachedStyleFont() + { + var style = XLStyle.Default; + + style.Font.FontSize = 50; + + Assert.AreEqual(50, style.Font.FontSize); + } + + + [Test] + public void ChangeDetachedStyleNumberFormat() + { + var style = XLStyle.Default; + + style.NumberFormat.Format = "YYYY"; + + Assert.AreEqual("YYYY", style.NumberFormat.Format); + } + + [Test] + public void ChangeDetachedStyleProtection() + { + var style = XLStyle.Default; + + style.Protection.Hidden = true; + + Assert.AreEqual(true, style.Protection.Hidden); + } + + [Test] + public void ChangeAttachedStyleAlignment() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.AddWorksheet("Sheet1"); + var a1 = ws.Cell("A1"); + + a1.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Justify; + + Assert.AreEqual(XLAlignmentHorizontalValues.Justify, a1.Style.Alignment.Horizontal); + } + } + } +} diff --git a/ClosedXML_Tests/Excel/Styles/XLFillTests.cs b/ClosedXML_Tests/Excel/Styles/XLFillTests.cs index 6a5af86..90c3e08 100644 --- a/ClosedXML_Tests/Excel/Styles/XLFillTests.cs +++ b/ClosedXML_Tests/Excel/Styles/XLFillTests.cs @@ -48,7 +48,7 @@ worksheet.Cell(2, 2).SetValue("Text"); var cf = worksheet.Cell(2, 2).AddConditionalFormat(); var style = cf.WhenNotBlank(); - style + style = style .Border.SetOutsideBorder(XLBorderStyleValues.Thick) .Border.SetOutsideBorderColor(XLColor.Blue); diff --git a/ClosedXML_Tests/Resource/Examples/AutoFilter/DateTimeGroupAutoFilter.xlsx b/ClosedXML_Tests/Resource/Examples/AutoFilter/DateTimeGroupAutoFilter.xlsx index 4e5ab05..592e67d 100644 --- a/ClosedXML_Tests/Resource/Examples/AutoFilter/DateTimeGroupAutoFilter.xlsx +++ b/ClosedXML_Tests/Resource/Examples/AutoFilter/DateTimeGroupAutoFilter.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Misc/AddingDataSet.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/AddingDataSet.xlsx index 12cb876..1683c27 100644 --- a/ClosedXML_Tests/Resource/Examples/Misc/AddingDataSet.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Misc/AddingDataSet.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Misc/AddingDataTableAsWorksheet.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/AddingDataTableAsWorksheet.xlsx index c3e6540..55388ef 100644 --- a/ClosedXML_Tests/Resource/Examples/Misc/AddingDataTableAsWorksheet.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Misc/AddingDataTableAsWorksheet.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Misc/CopyingWorksheets.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/CopyingWorksheets.xlsx index 40d3c0f..57cf75f 100644 --- a/ClosedXML_Tests/Resource/Examples/Misc/CopyingWorksheets.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Misc/CopyingWorksheets.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Misc/ShowCase.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/ShowCase.xlsx index 0d7a0b2..780a546 100644 --- a/ClosedXML_Tests/Resource/Examples/Misc/ShowCase.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Misc/ShowCase.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/AddingRowToTables.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/AddingRowToTables.xlsx index 2f0ed47..377c002 100644 --- a/ClosedXML_Tests/Resource/Examples/Ranges/AddingRowToTables.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Ranges/AddingRowToTables.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/CurrentRowColumn.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/CurrentRowColumn.xlsx index 594d975..44ebfb8 100644 --- a/ClosedXML_Tests/Resource/Examples/Ranges/CurrentRowColumn.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Ranges/CurrentRowColumn.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/DeletingRanges.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/DeletingRanges.xlsx index b34c7d8..05aeb97 100644 --- a/ClosedXML_Tests/Resource/Examples/Ranges/DeletingRanges.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Ranges/DeletingRanges.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/SortExample.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/SortExample.xlsx index a3db8ac..3e820aa 100644 --- a/ClosedXML_Tests/Resource/Examples/Ranges/SortExample.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Ranges/SortExample.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/Sorting.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/Sorting.xlsx index a38d9be..12e5656 100644 --- a/ClosedXML_Tests/Resource/Examples/Ranges/Sorting.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Ranges/Sorting.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/TransposeRanges.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/TransposeRanges.xlsx index d348c86..2696471 100644 --- a/ClosedXML_Tests/Resource/Examples/Ranges/TransposeRanges.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Ranges/TransposeRanges.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/WalkingRanges.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/WalkingRanges.xlsx index ee46beb..1b82a8f 100644 --- a/ClosedXML_Tests/Resource/Examples/Ranges/WalkingRanges.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Ranges/WalkingRanges.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Styles/StyleRowsColumns.xlsx b/ClosedXML_Tests/Resource/Examples/Styles/StyleRowsColumns.xlsx index f10a5f6..fdadbd3 100644 --- a/ClosedXML_Tests/Resource/Examples/Styles/StyleRowsColumns.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Styles/StyleRowsColumns.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Styles/StyleWorksheet.xlsx b/ClosedXML_Tests/Resource/Examples/Styles/StyleWorksheet.xlsx index 2201621..c7f0652 100644 --- a/ClosedXML_Tests/Resource/Examples/Styles/StyleWorksheet.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Styles/StyleWorksheet.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Tables/InsertingTables.xlsx b/ClosedXML_Tests/Resource/Examples/Tables/InsertingTables.xlsx index 97daf3b..a16417a 100644 --- a/ClosedXML_Tests/Resource/Examples/Tables/InsertingTables.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Tables/InsertingTables.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/Tables/UsingTables.xlsx b/ClosedXML_Tests/Resource/Examples/Tables/UsingTables.xlsx index e18c66c..3bbdb81 100644 --- a/ClosedXML_Tests/Resource/Examples/Tables/UsingTables.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Tables/UsingTables.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Other/Charts/PreserveCharts/outputfile.xlsx b/ClosedXML_Tests/Resource/Other/Charts/PreserveCharts/outputfile.xlsx index 5aa86b6..fe5db26 100644 --- a/ClosedXML_Tests/Resource/Other/Charts/PreserveCharts/outputfile.xlsx +++ b/ClosedXML_Tests/Resource/Other/Charts/PreserveCharts/outputfile.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/ConditionalFormattingOrder/ConditionalFormattingOrder.xlsx b/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/ConditionalFormattingOrder/ConditionalFormattingOrder.xlsx index ed07359..84c186d 100644 --- a/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/ConditionalFormattingOrder/ConditionalFormattingOrder.xlsx +++ b/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/ConditionalFormattingOrder/ConditionalFormattingOrder.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/TransparentBackgroundFill/TransparentBackgroundFill.xlsx b/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/TransparentBackgroundFill/TransparentBackgroundFill.xlsx index bccd5b2..ffd35b3 100644 --- a/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/TransparentBackgroundFill/TransparentBackgroundFill.xlsx +++ b/ClosedXML_Tests/Resource/Other/StyleReferenceFiles/TransparentBackgroundFill/TransparentBackgroundFill.xlsx Binary files differ