diff --git a/ClosedXML/Excel/Ranges/IXLRanges.cs b/ClosedXML/Excel/Ranges/IXLRanges.cs index cadda81..815f6f0 100644 --- a/ClosedXML/Excel/Ranges/IXLRanges.cs +++ b/ClosedXML/Excel/Ranges/IXLRanges.cs @@ -20,10 +20,13 @@ void Remove(IXLRange range); /// - /// Removes all ranges from the collection optionally disposing them. + /// Removes ranges matching the criteria from the collection, optionally releasing their event handlers. /// - /// - void RemoveAll(bool dispose = true); + /// Criteria to filter ranges. Only those ranges that satisfy the criteria will be removed. + /// Null means the entire collection should be cleared. + /// Specify whether or not should removed ranges be unsubscribed from + /// row/column shifting events. Until ranges are unsubscribed they cannot be collected by GC. + void RemoveAll(Predicate match = null, bool releaseEventHandlers = true); Int32 Count { get; } diff --git a/ClosedXML/Excel/Ranges/XLRanges.cs b/ClosedXML/Excel/Ranges/XLRanges.cs index 9a5c9b4..3b0650e 100644 --- a/ClosedXML/Excel/Ranges/XLRanges.cs +++ b/ClosedXML/Excel/Ranges/XLRanges.cs @@ -47,12 +47,25 @@ _ranges.RemoveAll(r => r.ToString() == range.ToString()); } - public void RemoveAll(bool dispose = true) + /// + /// Removes ranges matching the criteria from the collection, optionally releasing their event handlers. + /// + /// Criteria to filter ranges. Only those ranges that satisfy the criteria will be removed. + /// Null means the entire collection should be cleared. + /// Specify whether or not should removed ranges be unsubscribed from + /// row/column shifting events. Until ranges are unsubscribed they cannot be collected by GC. + public void RemoveAll(Predicate match = null, bool releaseEventHandlers = true) { - Count = 0; - if (dispose) - _ranges.ForEach(r => r.Dispose()); - _ranges.Clear(); + match = match ?? (_ => true); + + if (releaseEventHandlers) + { + _ranges + .Where(r => match(r)) + .ForEach(r => r.Dispose()); + } + + Count -= _ranges.RemoveAll(match); } public int Count { get; private set; } diff --git a/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs b/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs index 8171db0..5668d01 100644 --- a/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs +++ b/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs @@ -415,7 +415,7 @@ ranges.Add(ws.Range("B1:B2")); var rangesCopy = ranges.ToList(); - ranges.RemoveAll(false); + ranges.RemoveAll(null, false); ws.FirstColumn().InsertColumnsBefore(1); Assert.AreEqual(0, ranges.Count); @@ -423,5 +423,22 @@ Assert.AreEqual("B1:B2", rangesCopy.First().RangeAddress.ToString()); Assert.AreEqual("C1:C2", rangesCopy.Last().RangeAddress.ToString()); } + + + [Test] + public void RangesRemoveAllByCriteria() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var ranges = new XLRanges(); + ranges.Add(ws.Range("A1:A2")); + ranges.Add(ws.Range("B1:B3")); + ranges.Add(ws.Range("C1:C4")); + var otherRange = ws.Range("A3:D3"); + + ranges.RemoveAll(r => r.Intersects(otherRange)); + + Assert.AreEqual(1, ranges.Count); + Assert.AreEqual("A1:A2", ranges.Single().RangeAddress.ToString()); + } } }