diff --git a/ClosedXML/ClosedXML.csproj b/ClosedXML/ClosedXML.csproj index 704523f..bf439af 100644 --- a/ClosedXML/ClosedXML.csproj +++ b/ClosedXML/ClosedXML.csproj @@ -129,6 +129,7 @@ + diff --git a/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/Excel/Cells/XLCell.cs index 5989dd5..46dd03c 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,28 @@ 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) + public XLCell(XLWorksheet worksheet, XLAddress address, IXLStyle style) + : base(style.Value) { Address = address; ShareString = true; _worksheet = worksheet; } + public XLCell(XLWorksheet worksheet, XLAddress address) + : this(worksheet, address, XLStyle.Default) + { + } + #endregion Constructor public XLWorksheet Worksheet @@ -240,7 +237,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) @@ -903,13 +900,6 @@ return InsertData(dataTable.Rows); } - public IXLStyle Style - { - get { return GetStyle(); } - - set { SetStyle(value); } - } - public IXLCell SetDataType(XLDataType dataType) { DataType = dataType; @@ -1197,8 +1187,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; @@ -1242,17 +1232,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; } } @@ -1530,27 +1520,21 @@ #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 { @@ -1664,52 +1648,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 @@ -2214,8 +2165,7 @@ { CopyValuesFrom(otherCell); - if (otherCell._styleCacheId.HasValue) - SetStyle(otherCell._style ?? otherCell.Worksheet.Workbook.GetStyleById(otherCell._styleCacheId.Value)); + Style = otherCell.Style; if (copyDataValidations) { diff --git a/ClosedXML/Excel/Cells/XLCells.cs b/ClosedXML/Excel/Cells/XLCells.cs index bde0c7f..48e52b4 100644 --- a/ClosedXML/Excel/Cells/XLCells.cs +++ b/ClosedXML/Excel/Cells/XLCells.cs @@ -7,23 +7,21 @@ { 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 #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; @@ -169,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); } @@ -219,28 +207,17 @@ #endregion #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 - { - get { return _style; } - set { _style = new XLStyle(this, value); } - } - - 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 fdf669d..b499b65 100644 --- a/ClosedXML/Excel/Columns/XLColumn.cs +++ b/ClosedXML/Excel/Columns/XLColumn.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Drawing; - namespace ClosedXML.Excel { internal class XLColumn : XLRangeBase, IXLColumn @@ -24,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.Value) { SetColumnNumber(column); @@ -33,7 +34,6 @@ SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted)); else { - SetStyle(xlColumnParameters.DefaultStyleId); _width = xlColumnParameters.Worksheet.ColumnWidth; } } @@ -42,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; @@ -51,7 +52,6 @@ _collapsed = column._collapsed; _isHidden = column._isHidden; _outlineLevel = column._outlineLevel; - SetStyle(column.GetStyleId()); } #endregion @@ -62,35 +62,52 @@ { 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); + { + Int32 minRow = 1; + Int32 maxRow = 0; + + 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++) + yield return Worksheet.Cell(ro, column); + } + } } } @@ -177,45 +194,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(); @@ -263,7 +241,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; @@ -781,7 +759,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 9f5b571..1325bef 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 d846ce3..1d29af9 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFCellIsConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFCellIsConverter.cs @@ -11,8 +11,8 @@ var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.Key]; conditionalFormattingRule.Operator = cf.Operator.ToOpenXml(); diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs index 5e33f41..0a83028 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFContainsConverter.cs @@ -10,8 +10,8 @@ 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]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..2238881 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFDatesOccuringConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFDatesOccuringConverter.cs @@ -24,8 +24,8 @@ { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.Key]; conditionalFormattingRule.TimePeriod = cf.TimePeriod.ToOpenXml(); diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs index 230f0f6..3b967d0 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFEndsWithConverter.cs @@ -10,8 +10,8 @@ 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]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..d4f09f3 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsBlankConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsBlankConverter.cs @@ -9,8 +9,8 @@ { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..265fb41 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsErrorConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFIsErrorConverter.cs @@ -9,8 +9,8 @@ { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..59ce073 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotBlankConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotBlankConverter.cs @@ -9,8 +9,8 @@ { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..5072e34 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotContainsConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotContainsConverter.cs @@ -10,8 +10,8 @@ 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]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..703ec43 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotErrorConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFNotErrorConverter.cs @@ -9,8 +9,8 @@ { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..0c5c79c 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFStartsWithConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFStartsWithConverter.cs @@ -10,8 +10,8 @@ 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]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..b8d7338 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFTopConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFTopConverter.cs @@ -10,8 +10,8 @@ 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]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.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..600e9bc 100644 --- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFUniqueConverter.cs +++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFUniqueConverter.cs @@ -9,8 +9,8 @@ { var conditionalFormattingRule = XLCFBaseConverter.Convert(cf, priority); - if (!cf.Style.Equals(XLWorkbook.DefaultStyle)) - conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style]; + if (!cf.Style.Value.Equals(XLWorkbook.DefaultStyle.Value)) + conditionalFormattingRule.FormatId = (UInt32)context.DifferentialFormats[cf.Style.Value.Key]; return conditionalFormattingRule; } diff --git a/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs b/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs index e55ec35..5e8b530 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.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); @@ -103,11 +101,10 @@ get { return NoRangeComparerInstance; } } - public XLConditionalFormat(XLRange range, Boolean copyDefaultModify = false) + 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(); @@ -116,11 +113,10 @@ } - public XLConditionalFormat(XLConditionalFormat conditionalFormat, IXLRange targetRange) + public XLConditionalFormat(XLConditionalFormat conditionalFormat, IXLRange targetRange) : base(XLStyle.Default.Value) { 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); @@ -143,45 +139,25 @@ public Guid Id { get; internal 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; } diff --git a/ClosedXML/Excel/Ranges/XLRange.cs b/ClosedXML/Excel/Ranges/XLRange.cs index 4a19fcc..1c78f4f 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.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.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.Style); 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 96cd2db..20d0b80 100644 --- a/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -8,45 +8,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 @@ -54,7 +27,8 @@ private static Int32 IdCounter = 0; private readonly Int32 Id; - protected XLRangeBase(XLRangeAddress rangeAddress) + protected XLRangeBase(XLRangeAddress rangeAddress, XLStyleValue styleValue) + : base(styleValue) { Id = ++IdCounter; @@ -261,7 +235,7 @@ #region IXLStylized Members - public IXLRanges RangesUsed + public override IXLRanges RangesUsed { get { @@ -270,6 +244,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 @@ -454,12 +445,6 @@ ); } - public virtual IXLStyle Style - { - get { return GetStyle(); } - set { Cells().ForEach(c => c.Style = value); } - } - IXLRange IXLRangeBase.AsRange() { return AsRange(); @@ -531,30 +516,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; @@ -824,19 +786,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, @@ -844,15 +805,11 @@ 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); + newCell = new XLCell(Worksheet, absoluteAddress, new XLStyle(this, styleValue.Key)); Worksheet.Internals.CellsCollection.Add(absRow, absColumn, newCell); return newCell; @@ -1136,7 +1093,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.Style); newCell.CopyValuesFrom(oldCell); newCell.FormulaA1 = oldCell.FormulaA1; cellsToInsert.Add(newKey, newCell); @@ -1159,7 +1116,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.Style); newCell.CopyValuesFrom(c); if (c.HasDataValidation) { @@ -1379,7 +1336,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.Style); newCell.CopyValuesFrom(oldCell); newCell.FormulaA1 = oldCell.FormulaA1; cellsToInsert.Add(newKey, newCell); @@ -1403,7 +1360,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.Style); newCell.CopyValuesFrom(c); if (c.HasDataValidation) { @@ -1563,7 +1520,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.Style); 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 ae85bf2..26048d6 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.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 f2481ed..525b13a 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.DefaultStyle.Value) { - _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 #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 aeb54e1..cdba803 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.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 bbd51f8..4544e08 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 { @@ -146,4 +133,4 @@ } } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/Ranges/XLRanges.cs b/ClosedXML/Excel/Ranges/XLRanges.cs index 7942134..e523a69 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.DefaultStyle.Value) { - _style = new XLStyle(this, XLWorkbook.DefaultStyle); } #region IXLRanges Members @@ -61,17 +59,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.IsInvalid && r.Contains(cell)); @@ -175,14 +162,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; @@ -193,19 +177,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; } } diff --git a/ClosedXML/Excel/Rows/XLRow.cs b/ClosedXML/Excel/Rows/XLRow.cs index cae1b8e..b8fe358 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.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,50 @@ { 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); + { + Int32 minColumn = 1; + Int32 maxColumn = 0; + 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++) + yield return Worksheet.Cell(row, co); + } + } } } @@ -183,7 +198,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; @@ -392,46 +407,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 { @@ -648,7 +623,7 @@ Worksheet.Internals.RowsCollection[RowNumber()].SetStyleNoColumns(value); else { - SetStyle(value); + Style = value; int row = RowNumber(); foreach (XLCell c in Worksheet.Internals.CellsCollection.GetCellsInRow(row)) @@ -716,7 +691,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 27583d1..97df87f 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.DefaultStyle.Value) { _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 @@ -212,13 +192,25 @@ #endregion #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 @@ -228,19 +220,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/IXLAlignment.cs b/ClosedXML/Excel/Style/IXLAlignment.cs index f516558..37b634e 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. diff --git a/ClosedXML/Excel/Style/IXLStyle.cs b/ClosedXML/Excel/Style/IXLStyle.cs index 0edd7a3..80f9685 100644 --- a/ClosedXML/Excel/Style/IXLStyle.cs +++ b/ClosedXML/Excel/Style/IXLStyle.cs @@ -2,7 +2,7 @@ namespace ClosedXML.Excel { - public interface IXLStyle: IEquatable + public interface IXLStyle : IEquatable { IXLAlignment Alignment { get; set; } IXLBorder Border { get; set; } @@ -11,5 +11,7 @@ IXLNumberFormat NumberFormat { get; set; } IXLNumberFormat DateFormat { get; } IXLProtection Protection { get; set; } + + XLStyleValue Value { get; } } } diff --git a/ClosedXML/Excel/Style/IXLStylized.cs b/ClosedXML/Excel/Style/IXLStylized.cs index 6a03319..43973aa 100644 --- a/ClosedXML/Excel/Style/IXLStylized.cs +++ b/ClosedXML/Excel/Style/IXLStylized.cs @@ -7,10 +7,12 @@ { 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; } } } diff --git a/ClosedXML/Excel/Style/XLAlignment.cs b/ClosedXML/Excel/Style/XLAlignment.cs index 5f0a399..f164409 100644 --- a/ClosedXML/Excel/Style/XLAlignment.cs +++ b/ClosedXML/Excel/Style/XLAlignment.cs @@ -9,325 +9,268 @@ { 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 + 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 - public XLAlignment() : this(null, XLWorkbook.DefaultStyle.Alignment) + #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; } - set - { - SetStyleChanged(); + get { return Key.Horizontal; } + set { 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; } - set - { - SetStyleChanged(); + get { return Key.TextRotation; } + set { 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); + Modify(k => { k.TextRotation = rotation; return k; }); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Alignment.TextRotation = rotation); - else - _textRotation = rotation; } } 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 +297,24 @@ 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/XLBorder.cs b/ClosedXML/Excel/Style/XLBorder.cs index afc1ccb..02db92a 100644 --- a/ClosedXML/Excel/Style/XLBorder.cs +++ b/ClosedXML/Excel/Style/XLBorder.cs @@ -1,73 +1,86 @@ using System; using System.Text; +using System.Collections.Generic; +using System.Linq; 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; - - public XLBorder() : this(null, XLWorkbook.DefaultStyle.Border) + #region Static members + 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; + } + #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); } } - public XLBorder(IXLStylized container, IXLBorder defaultBorder, Boolean useDefaultModify = true) + #region Constructors + /// + /// Create an instance of XLBorder initializing it with the specified value. + /// + /// 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) { @@ -94,7 +107,7 @@ { set { - if (_container == null || _container.UpdatingStyle) return; + if (_container == null) return; if (_container is XLWorksheet || _container is XLConditionalFormat) { @@ -120,18 +133,16 @@ { 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; } else { @@ -177,18 +188,16 @@ { 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; } else { @@ -237,227 +246,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("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("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("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("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("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) @@ -570,11 +458,19 @@ #endregion - 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 +502,24 @@ 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/XLFill.cs b/ClosedXML/Excel/Style/XLFill.cs index d7155af..2310713 100644 --- a/ClosedXML/Excel/Style/XLFill.cs +++ b/ClosedXML/Excel/Style/XLFill.cs @@ -1,146 +1,163 @@ using System; +using System.Collections.Generic; using System.Linq; namespace ClosedXML.Excel { internal class XLFill : IXLFill { - #region IXLFill Members - - public bool Equals(IXLFill other) + #region static members + 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 readonly XLStyle _style; - private XLColor _backgroundColor; - private XLColor _patternColor; - private XLFillPatternValues _patternType; + private XLFillValue _value; + + internal XLFillKey Key + { + get { return _value.Key; } + private set { _value = XLFillValue.FromKey(value); } + } + + #endregion Properties + + #region Constructors + /// + /// 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(XLStyle style, XLFillKey key) : this(style, XLFillValue.FromKey(key)) + { + } + + public XLFill(XLStyle style = null, IXLFill d = null) : this(style, GenerateKey(d)) + { + } + #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 _backgroundColor; } + get { return XLColor.FromKey(Key.BackgroundColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Fill.BackgroundColor = value); - else + if (value == null) + throw new ArgumentNullException("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)) { - // 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; + PatternType = value.HasValue ? XLFillPatternValues.Solid : XLFillPatternValues.None; } + + Modify(k => { k.BackgroundColor = value.Key; return k; }); } } public XLColor PatternColor { - get { return _patternColor; } + get { return XLColor.FromKey(Key.PatternColor); } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Fill.PatternColor = value); - else - { - _patternColor = value; - } + if (value == null) + throw new ArgumentNullException("Color cannot be null"); + + Modify(k => { k.PatternColor = value.Key; return k; }); } } public XLFillPatternValues PatternType { - get { return _patternType; } + get { return Key.PatternType; } set { - SetStyleChanged(); - if (_container != null && !_container.UpdatingStyle) - _container.Styles.ForEach(s => s.Fill.PatternType = value); - else - { - _patternType = value; - } + Modify(k => { k.PatternType = value; return k; }); } } public IXLStyle SetBackgroundColor(XLColor value) { BackgroundColor = value; - return _container.Style; + return _style; } public IXLStyle SetPatternColor(XLColor value) { PatternColor = value; - return _container.Style; + return _style; } public IXLStyle SetPatternType(XLFillPatternValues value) { PatternType = value; - return _container.Style; + return _style; } - - #endregion Properties - - #region Constructors - - private readonly IXLStylized _container; - - public XLFill() : this(null, XLWorkbook.DefaultStyle.Fill) - { - } - - public XLFill(IXLStylized container, IXLFill defaultFill = null, Boolean useDefaultModify = true) - { - _container = container; - if (defaultFill == null) return; - _patternType = defaultFill.PatternType; - _backgroundColor = defaultFill.BackgroundColor; - _patternColor = defaultFill.PatternColor; - - if (useDefaultModify) - { - var d = defaultFill as XLFill; - } - } - - #endregion Constructors + #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 +173,12 @@ } } + public override int GetHashCode() + { + var hashCode = -1938644919; + hashCode = hashCode * -1521134295 + Key.GetHashCode(); + return hashCode; + } #endregion Overridden } } diff --git a/ClosedXML/Excel/Style/XLFont.cs b/ClosedXML/Excel/Style/XLFont.cs index 87915b4..6d091df 100644 --- a/ClosedXML/Excel/Style/XLFont.cs +++ b/ClosedXML/Excel/Style/XLFont.cs @@ -5,379 +5,280 @@ { 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 + 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; - public XLFont() - : this(null, XLWorkbook.DefaultStyle.Font) + 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; + } + #endregion Constructors - _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; + private void Modify(Func modification) + { + Key = modification(Key); - if (useDefaultModify) + _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("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; - - 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 +307,24 @@ 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/XLNumberFormat.cs b/ClosedXML/Excel/Style/XLNumberFormat.cs index 0fc2f4a..f7a0de3 100644 --- a/ClosedXML/Excel/Style/XLNumberFormat.cs +++ b/ClosedXML/Excel/Style/XLNumberFormat.cs @@ -4,112 +4,144 @@ { internal class XLNumberFormat : IXLNumberFormat { - #region IXLNumberFormat Members - - public bool Equals(IXLNumberFormatBase other) + #region Static members + 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 Static members + + + #region Properties + + private readonly XLStyle _style; + + private XLNumberFormatValue _value; + + internal XLNumberFormatKey Key + { + get { return _value.Key; } + private set { _value = XLNumberFormatValue.FromKey(value); } } #endregion - private void SetStyleChanged() + #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) { - if (_container != null) _container.StyleChanged = true; + _style = style ?? XLStyle.CreateEmptyStyle(); + _value = value; } - public override bool Equals(object obj) + public XLNumberFormat(XLStyle style, XLNumberFormatKey key) : this(style, XLNumberFormatValue.FromKey(key)) { - return Equals((IXLNumberFormatBase)obj); } - public override int GetHashCode() + public XLNumberFormat(XLStyle style = null, IXLNumberFormat d = null) : this(style, GenerateKey(d)) { - return NumberFormatId - ^ Format.GetHashCode(); } + #endregion Constructors - #region Properties - - private readonly IXLStylized _container; - private String _format = String.Empty; - - private Int32 _numberFormatId; - + #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; } + 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 } } diff --git a/ClosedXML/Excel/Style/XLProtection.cs b/ClosedXML/Excel/Style/XLProtection.cs index 51ba453..c795ad2 100644 --- a/ClosedXML/Excel/Style/XLProtection.cs +++ b/ClosedXML/Excel/Style/XLProtection.cs @@ -4,109 +4,129 @@ { internal class XLProtection : IXLProtection { - private readonly IXLStylized _container; - private Boolean _hidden; + #region Static members + internal static XLProtectionKey GenerateKey(IXLProtection defaultProtection) + { + if (defaultProtection == null) + return XLProtectionValue.Default.Key; + if (defaultProtection is XLProtection) + return (defaultProtection as XLProtection).Key; - private Boolean _locked; + 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 + + 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 +136,13 @@ 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/XLStyle.cs b/ClosedXML/Excel/Style/XLStyle.cs index 939aa96..4a59846 100644 --- a/ClosedXML/Excel/Style/XLStyle.cs +++ b/ClosedXML/Excel/Style/XLStyle.cs @@ -1,60 +1,158 @@ using System; +using System.Linq; using System.Text; namespace ClosedXML.Excel { 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 + public static XLStyle Default { get { return new XLStyle(XLStyleValue.Default); } } - DateFormat = NumberFormat; + 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; + + public 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.InnerStyle = new XLStyle(_container, Key); + + _container.Styles.OfType() + .Where(s => s._container != _container) + .ForEach(style => + { + style.Modify(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() { var sb = new StringBuilder(); @@ -75,29 +173,26 @@ 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 } } diff --git a/ClosedXML/Excel/Style/XLStylizedBase.cs b/ClosedXML/Excel/Style/XLStylizedBase.cs new file mode 100644 index 0000000..c09f530 --- /dev/null +++ b/ClosedXML/Excel/Style/XLStylizedBase.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using System.Linq; + +namespace ClosedXML.Excel +{ + /// + /// Base class for any workbook element that has or may have a style. + /// + public abstract class XLStylizedBase : IXLStylized + { + #region Properties + /// + /// Read-only style property. + /// + public XLStyleValue StyleValue { get; private set; } + + /// + /// 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 virtual IEnumerable Children + { + get + { + return RangesUsed.OfType(); + } + } + + public abstract IXLRanges RangesUsed { get; } + + public abstract IEnumerable Styles { get; } + #endregion Properties + + public 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)); + } + } + #endregion Private methods + } +} diff --git a/ClosedXML/Excel/Style/XLStylizedContainer.cs b/ClosedXML/Excel/Style/XLStylizedContainer.cs index e9177a3..1f09eb9 100644 --- a/ClosedXML/Excel/Style/XLStylizedContainer.cs +++ b/ClosedXML/Excel/Style/XLStylizedContainer.cs @@ -2,36 +2,26 @@ namespace ClosedXML.Excel { - using System; - - internal class XLStylizedContainer: IXLStylized + internal class XLStylizedContainer: XLStylizedBase, IXLStylized { - public Boolean StyleChanged { get; set; } - readonly IXLStylized _container; - public XLStylizedContainer(IXLStyle style, IXLStylized container) + protected readonly IXLStylized _container; + + public XLStylizedContainer(IXLStyle style, IXLStylized container) : base(style.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 IXLStyle InnerStyle { get; set; } - - public IXLRanges RangesUsed { get; set; } + public override IXLRanges RangesUsed + { + get { return _container.RangesUsed; } + } } } diff --git a/ClosedXML/Excel/Style/XLStylizedEmpty.cs b/ClosedXML/Excel/Style/XLStylizedEmpty.cs index 161f15f..c916a6a 100644 --- a/ClosedXML/Excel/Style/XLStylizedEmpty.cs +++ b/ClosedXML/Excel/Style/XLStylizedEmpty.cs @@ -1,37 +1,24 @@ -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) + public XLStylizedEmpty(IXLStyle defaultStyle) : base(defaultStyle?.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; } } } diff --git a/ClosedXML/Excel/Tables/XLTableField.cs b/ClosedXML/Excel/Tables/XLTableField.cs index 4ddcd73..c007643 100644 --- a/ClosedXML/Excel/Tables/XLTableField.cs +++ b/ClosedXML/Excel/Tables/XLTableField.cs @@ -160,7 +160,7 @@ var styles = this.Column .Cells() .Skip(this.table.ShowHeaderRow ? 1 : 0) - .Select(c => c.Style); + .Select(c => c.Style.Value); if (this.table.ShowTotalsRow) styles = styles.Take(styles.Count() - 1); diff --git a/ClosedXML/Excel/Tables/XLTableRows.cs b/ClosedXML/Excel/Tables/XLTableRows.cs index 71cc081..a07a871 100644 --- a/ClosedXML/Excel/Tables/XLTableRows.cs +++ b/ClosedXML/Excel/Tables/XLTableRows.cs @@ -5,26 +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.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; @@ -35,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 { @@ -84,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 ac9e0d7..2db2077 100644 --- a/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/Excel/XLWorkbook.cs @@ -44,69 +44,11 @@ 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; } } @@ -167,29 +109,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 ec7ae2f..2c5fd9d 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) @@ -1490,6 +1489,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); } /// @@ -2552,18 +2554,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) + }; } } @@ -2574,90 +2581,97 @@ { LoadFill(fill, xlStylized.InnerStyle.Fill, differentialFillFormat: false); } + xlStyle.Fill = xlStylized.InnerStyle.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; } } @@ -2665,71 +2679,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 35f43af..cfe251c 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 7d7ee72..887ff16 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -906,16 +906,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(); @@ -1837,10 +1834,10 @@ var style = xlField.Column.Cells() .Skip(xlTable.ShowHeaderRow ? 1 : 0) .First() - .Style; + .Style.Value; - if (!DefaultStyle.Equals(style) && context.DifferentialFormats.ContainsKey(style)) - tableColumn.DataFormatId = UInt32Value.FromUInt32(Convert.ToUInt32(context.DifferentialFormats[style])); + if (!DefaultStyle.Value.Equals(style) && context.DifferentialFormats.ContainsKey(style.Key)) + tableColumn.DataFormatId = UInt32Value.FromUInt32(Convert.ToUInt32(context.DifferentialFormats[style.Key])); } else tableColumn.DataFormatId = null; @@ -3147,28 +3144,10 @@ private void GenerateWorkbookStylesPartContent(WorkbookStylesPart workbookStylesPart, SaveContext context) { - var defaultStyle = new XLStyle(null, DefaultStyle); - var defaultStyleId = GetStyleId(defaultStyle); + var defaultStyle = DefaultStyle.Value; + 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(); @@ -3194,7 +3173,7 @@ else defaultFormatId = 0; - context.SharedStyles.Add(defaultStyleId, + context.SharedStyles.Add(defaultStyle.Key, new StyleInfo { StyleId = defaultFormatId, @@ -3211,70 +3190,77 @@ 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.ColumnsCollection.Select(kp => kp.Value.GetStyleId()).Where( - s => !xlStyles.Contains(s))) + } + foreach (var s in worksheet.Internals.RowsCollection.Select(r => r.Value.StyleValue)) + { xlStyles.Add(s); - - foreach ( - var s in - worksheet.Internals.RowsCollection.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 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); @@ -3287,25 +3273,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); @@ -3316,7 +3300,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; @@ -3353,7 +3337,7 @@ { //var ie = context.DifferentialFormats.Keys.First().Equals(cf.Style); - if (!cf.Style.Equals(DefaultStyle) && !context.DifferentialFormats.ContainsKey(cf.Style)) + if (!cf.Style.Value.Equals(DefaultStyle.Value) && !context.DifferentialFormats.ContainsKey(cf.Style.Value.Key)) AddConditionalDifferentialFormat(workbookStylesPart.Stylesheet.DifferentialFormats, cf, context); } @@ -3364,9 +3348,9 @@ var style = tf.Column.Cells() .Skip(tf.Table.ShowHeaderRow ? 1 : 0) .First() - .Style; + .Style.Value; - if (!style.Equals(DefaultStyle) && !context.DifferentialFormats.ContainsKey(style)) + if (!style.Equals(DefaultStyle.Value) && !context.DifferentialFormats.ContainsKey(style.Key)) AddStyleAsDifferentialFormat(workbookStylesPart.Stylesheet.DifferentialFormats, style, context); } } @@ -3378,7 +3362,7 @@ } private void FillDifferentialFormatsCollection(DifferentialFormats differentialFormats, - Dictionary dictionary) + Dictionary dictionary) { dictionary.Clear(); var id = 0; @@ -3386,18 +3370,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); - - emptyContainer.UpdatingStyle = false; - - if (!dictionary.ContainsKey(style)) - dictionary.Add(style, id++); + 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); + + if (!dictionary.ContainsKey(emptyContainer.StyleValue.Key)) + dictionary.Add(emptyContainer.StyleValue.Key, id++); } } @@ -3405,7 +3386,7 @@ SaveContext context) { var differentialFormat = new DifferentialFormat(); - differentialFormat.Append(GetNewFont(new FontInfo { Font = cf.Style.Font as XLFont }, false)); + differentialFormat.Append(GetNewFont(new FontInfo { Font = cf.Style.Value.Font }, false)); if (!String.IsNullOrWhiteSpace(cf.Style.NumberFormat.Format)) { var numberFormat = new NumberingFormat @@ -3415,19 +3396,19 @@ }; differentialFormat.Append(numberFormat); } - differentialFormat.Append(GetNewFill(new FillInfo { Fill = cf.Style.Fill as XLFill }, differentialFillFormat: true, ignoreMod: false)); - differentialFormat.Append(GetNewBorder(new BorderInfo { Border = cf.Style.Border as XLBorder }, false)); + differentialFormat.Append(GetNewFill(new FillInfo { Fill = cf.Style.Value.Fill }, differentialFillFormat: true, ignoreMod: false)); + differentialFormat.Append(GetNewBorder(new BorderInfo { Border = cf.Style.Value.Border }, false)); differentialFormats.Append(differentialFormat); - context.DifferentialFormats.Add(cf.Style, differentialFormats.Count() - 1); + context.DifferentialFormats.Add(cf.Style.Value.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(); - differentialFormat.Append(GetNewFont(new FontInfo { Font = style.Font as XLFont }, false)); + differentialFormat.Append(GetNewFont(new FontInfo { Font = style.Font }, false)); if (!String.IsNullOrWhiteSpace(style.NumberFormat.Format) || style.NumberFormat.NumberFormatId != 0) { var numberFormat = new NumberingFormat(); @@ -3451,12 +3432,12 @@ differentialFormat.Append(numberFormat); } - differentialFormat.Append(GetNewFill(new FillInfo { Fill = style.Fill as XLFill }, differentialFillFormat: true, ignoreMod: false)); - differentialFormat.Append(GetNewBorder(new BorderInfo { Border = style.Border as XLBorder }, false)); + differentialFormat.Append(GetNewFill(new FillInfo { Fill = style.Fill }, differentialFillFormat: true, ignoreMod: false)); + differentialFormat.Append(GetNewBorder(new BorderInfo { Border = style.Border }, false)); 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) @@ -3582,9 +3563,9 @@ ; } - private static bool ProtectionsAreEqual(Protection protection, IXLProtection xlProtection) + private static bool ProtectionsAreEqual(Protection protection, XLProtectionValue xlProtection) { - var p = new XLProtection(); + var p = new XLProtectionKey(); if (protection != null) { if (protection.Locked != null) @@ -3592,14 +3573,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 = new XLAlignmentKey(); if (alignment.Indent != null) a.Indent = (Int32)alignment.Indent.Value; @@ -3620,17 +3601,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; @@ -3659,16 +3644,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); @@ -3676,10 +3661,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); @@ -3687,10 +3672,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); @@ -3698,10 +3683,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); @@ -3709,10 +3694,11 @@ 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) + if (borderInfo.Border.DiagonalBorderColor != XLBorderValue.Default.DiagonalBorderColor || ignoreMod) + if (borderInfo.Border.DiagonalBorderColor != null) { var DiagonalBorderColor = GetNewColor(borderInfo.Border.DiagonalBorderColor); DiagonalBorder.AppendChild(DiagonalBorderColor); @@ -3723,9 +3709,9 @@ return border; } - private bool BordersAreEqual(Border b, IXLBorder xlBorder) + private bool BordersAreEqual(Border b, XLBorderValue xlBorder) { - var nb = new XLBorder(); + var nb = new XLBorderKey(); if (b.DiagonalUp != null) nb.DiagonalUp = b.DiagonalUp.Value; @@ -3738,7 +3724,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) @@ -3747,7 +3733,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) @@ -3756,7 +3742,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) @@ -3765,7 +3751,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) @@ -3774,14 +3760,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(); @@ -3789,7 +3775,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; @@ -3952,13 +3938,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) @@ -3966,7 +3952,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; @@ -3997,32 +3983,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; @@ -4084,9 +4071,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 @@ -4105,18 +4095,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) @@ -4129,7 +4119,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 @@ -4165,16 +4155,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 @@ -4487,7 +4474,7 @@ maxInColumnsCollection = 0; } - var worksheetStyleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; + var worksheetStyleId = context.SharedStyles[xlWorksheet.StyleValue.Key].StyleId; if (minInColumnsCollection > 1) { UInt32Value min = 1; @@ -4517,7 +4504,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; @@ -4525,7 +4512,7 @@ } else { - styleId = context.SharedStyles[xlWorksheet.GetStyleId()].StyleId; + styleId = context.SharedStyles[xlWorksheet.StyleValue.Key].StyleId; columnWidth = worksheetColumnWidth; } @@ -4562,7 +4549,7 @@ maxInColumnsCollection = (Int32)col.Max.Value; } - if (maxInColumnsCollection < XLHelper.MaxColumnNumber && !xlWorksheet.Style.Equals(DefaultStyle)) + if (maxInColumnsCollection < XLHelper.MaxColumnNumber && !xlWorksheet.StyleValue.Equals(DefaultStyle.Value)) { var column = new Column { @@ -4639,9 +4626,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; } @@ -4684,7 +4671,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 be9cc23..2b4c2f4 100644 --- a/ClosedXML/Excel/XLWorksheet.cs +++ b/ClosedXML/Excel/XLWorksheet.cs @@ -40,7 +40,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.Value) { EventTrackingEnabled = workbook.EventTracking == XLEventTracking.Enabled; @@ -63,7 +64,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); @@ -103,20 +103,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(false).OfType()) + yield return col; + foreach (var row in RowsUsed(false).OfType()) + yield return row; + } } internal Boolean RowHeightChanged { get; set; } @@ -133,20 +134,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; } @@ -578,7 +565,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; @@ -1079,11 +1066,6 @@ #endregion Outlines - public HashSet GetStyleIds() - { - return Internals.CellsCollection.GetStyleIds(GetStyleId()); - } - public XLRow FirstRowUsed() { return FirstRowUsed(false); @@ -1163,17 +1145,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) @@ -1420,10 +1402,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) @@ -1439,11 +1421,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_Tests/ClosedXML_Tests.csproj b/ClosedXML_Tests/ClosedXML_Tests.csproj index 199e828..cff8196 100644 --- a/ClosedXML_Tests/ClosedXML_Tests.csproj +++ b/ClosedXML_Tests/ClosedXML_Tests.csproj @@ -96,6 +96,7 @@ + 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); + } + } + } +}