diff --git a/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/Excel/Cells/XLCell.cs index f5e9084..3373837 100644 --- a/ClosedXML/Excel/Cells/XLCell.cs +++ b/ClosedXML/Excel/Cells/XLCell.cs @@ -73,49 +73,7 @@ internal XLCellValues _dataType; private XLHyperlink _hyperlink; private XLRichText _richText; - - #endregion Fields - - #region Constructor - - private Int32 _styleCacheId; - - public XLCell(XLWorksheet worksheet, XLAddress address, Int32 styleId) - { - Address = address; - ShareString = true; - _worksheet = worksheet; - SetStyle(styleId); - } - - private IXLStyle GetStyleForRead() - { - return Worksheet.Workbook.GetStyleById(GetStyleId()); - } - - public Int32 GetStyleId() - { - if (StyleChanged) - SetStyle(Style); - - return _styleCacheId; - } - - 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; - } - - #endregion Constructor + private Int32? _styleCacheId; public bool SettingHyperlink; public int SharedStringId; @@ -123,6 +81,28 @@ 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) + { + Address = address; + ShareString = true; + _worksheet = worksheet; + } + + + + #endregion Constructor + + public XLWorksheet Worksheet { get { return _worksheet; } @@ -454,7 +434,7 @@ if (!SetRichText(value)) SetValue(value); - if (_cellValue.Length > 32767) throw new ArgumentException("Cells can only hold 32,767 characters."); + if (_cellValue.Length > 32767) throw new ArgumentException("Cells can hold only 32,767 characters."); } } @@ -1173,10 +1153,15 @@ public Boolean IsEmpty(Boolean includeFormats) { + return IsEmpty(includeFormats, includeFormats); + } + + public Boolean IsEmpty(Boolean includeNormalFormats, Boolean includeConditionalFormats) + { if (InnerText.Length > 0) return false; - if (includeFormats) + if (includeNormalFormats) { if (!Style.Equals(Worksheet.Style) || IsMerged() || HasComment || HasDataValidation) return false; @@ -1191,10 +1176,12 @@ if (Worksheet.Internals.ColumnsCollection.TryGetValue(Address.ColumnNumber, out column) && !column.Style.Equals(Worksheet.Style)) return false; } - - if (Worksheet.ConditionalFormats.Any(cf => cf.Range.Contains(this))) - return false; } + + if (includeConditionalFormats + && Worksheet.ConditionalFormats.Any(cf => cf.Range.Contains(this))) + return false; + return true; } @@ -1574,14 +1561,57 @@ return _worksheet.Range(Address, Address); } + #region Styles private IXLStyle GetStyle() { if (_style != null) return _style; - return _style = new XLStyle(this, Worksheet.Workbook.GetStyleById(_styleCacheId)); + 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(); + } + + 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; + + } + + public Boolean IsDefaultWorksheetStyle() + { + return !_styleCacheId.HasValue && !StyleChanged || GetStyleId() == Worksheet.GetStyleId(); + } + #endregion Styles + + public void DeleteComment() { _comment = null; @@ -2056,7 +2086,8 @@ CopyValuesFrom(source); - SetStyle(source._style ?? source.Worksheet.Workbook.GetStyleById(source._styleCacheId)); + if (source._styleCacheId.HasValue) + SetStyle(source._style ?? source.Worksheet.Workbook.GetStyleById(source._styleCacheId.Value)); var conditionalFormats = source.Worksheet.ConditionalFormats.Where(c => c.Range.Contains(source)).ToList(); foreach (var cf in conditionalFormats) diff --git a/ClosedXML/Excel/Cells/XLCells.cs b/ClosedXML/Excel/Cells/XLCells.cs index 5f49b98..c8fef10 100644 --- a/ClosedXML/Excel/Cells/XLCells.cs +++ b/ClosedXML/Excel/Cells/XLCells.cs @@ -52,16 +52,18 @@ { if (oneRange) { - var cellRange = range.Worksheet.Internals.CellsCollection - .GetCells( - range.FirstAddress.RowNumber, - range.FirstAddress.ColumnNumber, - range.LastAddress.RowNumber, - range.LastAddress.ColumnNumber) - .Where(c => - !c.IsEmpty(_includeFormats) - && (_predicate == null || _predicate(c)) - ); + var cellRange = range + .Worksheet + .Internals + .CellsCollection + .GetCells( + range.FirstAddress.RowNumber, + range.FirstAddress.ColumnNumber, + range.LastAddress.RowNumber, + range.LastAddress.ColumnNumber) + .Where(c => !c.IsEmpty(_includeFormats) + && (_predicate == null || _predicate(c)) + ); foreach(var cell in cellRange) { @@ -121,13 +123,16 @@ { if (_usedCellsOnly) { - var cellRange = cellsInRanges.SelectMany( - cir => - cir.Value.Select(a => cir.Key.Internals.CellsCollection.GetCell(a)).Where( - cell => cell != null && ( - !cell.IsEmpty(_includeFormats) - && (_predicate == null || _predicate(cell)) - ))); + var cellRange = cellsInRanges + .SelectMany( + cir => + cir.Value.Select(a => cir.Key.Internals.CellsCollection.GetCell(a)).Where( + cell => + cell != null + && !cell.IsEmpty(_includeFormats) + && (_predicate == null || _predicate(cell)) + ) + ); foreach (var cell in cellRange) { @@ -277,4 +282,4 @@ cell.Select(); } } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/Cells/XLCellsCollection.cs b/ClosedXML/Excel/Cells/XLCellsCollection.cs index 32a89aa..8f11a98 100644 --- a/ClosedXML/Excel/Cells/XLCellsCollection.cs +++ b/ClosedXML/Excel/Cells/XLCellsCollection.cs @@ -95,7 +95,7 @@ Count--; DecrementUsage(RowsUsed, row); DecrementUsage(ColumnsUsed, row); - + HashSet delHash; if (deleted.TryGetValue(row, out delHash)) { @@ -119,7 +119,7 @@ } } - + } internal IEnumerable GetCells(Int32 rowStart, Int32 columnStart, @@ -148,14 +148,22 @@ { HashSet ids = new HashSet(); ids.Add(initial); - foreach (var row in rowsCollection) + foreach (var row in rowsCollection.Values) { - foreach (var column in row.Value) + foreach (var cell in row.Values) { - var id = column.Value.GetStyleId(); - if (!ids.Contains(id)) + Int32? id = null; + + if (cell.StyleChanged) + id = cell.GetStyleId(); + else if (cell.StyleCacheId() != cell.Worksheet.GetStyleId()) { - ids.Add(id); + id = cell.GetStyleId(); + } + + if (id.HasValue && !ids.Contains(id.Value)) + { + ids.Add(id.Value); } } } @@ -494,4 +502,4 @@ return GetCells(row, 1, row, MaxColumnUsed); } } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/Excel/Ranges/XLRangeBase.cs index 0534107..190d473 100644 --- a/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -841,12 +841,14 @@ 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) - newCellStyleId = worksheetStyleId; + if (styleId == 0 && worksheetStyleId != 0 || styleId == worksheetStyleId) + newCell = new XLCell(Worksheet, absoluteAddress); + else + newCell = new XLCell(Worksheet, absoluteAddress, newCellStyleId); - var newCell = new XLCell(Worksheet, absoluteAddress, newCellStyleId); Worksheet.Internals.CellsCollection.Add(absRow, absColumn, newCell); return newCell; } diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs index d8f6e71..7156782 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -4231,7 +4231,9 @@ { var styleId = context.SharedStyles[xlCell.GetStyleId()].StyleId; var cellReference = (xlCell.Address).GetTrimmedAddress(); - var isEmpty = xlCell.IsEmpty(true); + + // For saving cells to file, ignore conditional formatting. They just bloat the file + var isEmpty = xlCell.IsEmpty(true, false); Cell cell = null; if (cellsByReference.ContainsKey(cellReference)) diff --git a/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIsBlank.xlsx b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIsBlank.xlsx index 80be4ab..e57b38d 100644 --- a/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIsBlank.xlsx +++ b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIsBlank.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFNotBlank.xlsx b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFNotBlank.xlsx index 5f4f6ce..e233171 100644 --- a/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFNotBlank.xlsx +++ b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFNotBlank.xlsx Binary files differ