diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCellsCollection.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCellsCollection.cs index d2bc288..d53276a 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCellsCollection.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCellsCollection.cs @@ -104,6 +104,105 @@ } } + public XLSheetPoint FirstPointUsed(Int32 rowStart, Int32 columnStart, + Int32 rowEnd, Int32 columnEnd, Boolean includeFormats) + { + int finalRow = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd; + int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd; + + var firstRow = FirstRowUsed(rowStart, columnStart, finalRow, finalColumn, includeFormats); + if (firstRow == 0) return new XLSheetPoint(0,0); + + var firstColumn = FirstColumnUsed(rowStart, columnStart, finalRow, finalColumn, includeFormats); + if (firstColumn == 0) return new XLSheetPoint(0, 0); + + return new XLSheetPoint(firstRow, firstColumn); + } + + public XLSheetPoint LastPointUsed(Int32 rowStart, Int32 columnStart, + Int32 rowEnd, Int32 columnEnd, Boolean includeFormats) + { + int finalRow = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd; + int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd; + + var firstRow = LastRowUsed(rowStart, columnStart, finalRow, finalColumn, includeFormats); + if (firstRow == 0) return new XLSheetPoint(0, 0); + + var firstColumn = LastColumnUsed(rowStart, columnStart, finalRow, finalColumn, includeFormats); + if (firstColumn == 0) return new XLSheetPoint(0, 0); + + return new XLSheetPoint(firstRow, firstColumn); + } + + public int FirstRowUsed(int rowStart, int columnStart, int rowEnd, int columnEnd, Boolean includeFormats) + { + int finalRow = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd; + int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd; + for (int ro = rowStart; ro <= finalRow; ro++) + { + for (int co = columnStart; co <= finalColumn; co++) + { + XLCell cell; + if (_cellsDictionary.TryGetValue(new XLSheetPoint(ro, co), out cell) + && !cell.IsEmpty(includeFormats)) + return ro; + } + } + return 0; + } + + public int FirstColumnUsed(int rowStart, int columnStart, int rowEnd, int columnEnd, Boolean includeFormats) + { + int finalRow = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd; + int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd; + for (int co = columnStart; co <= columnEnd; co++) + { + for (int ro = rowStart; ro <= rowEnd; ro++) + { + XLCell cell; + if (_cellsDictionary.TryGetValue(new XLSheetPoint(ro, co), out cell) + && !cell.IsEmpty(includeFormats)) + return co; + } + } + return 0; + } + + + public int LastRowUsed(int rowStart, int columnStart, int rowEnd, int columnEnd, Boolean includeFormats) + { + int finalRow = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd; + int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd; + for (int ro = finalRow; ro >= rowStart; ro--) + { + for (int co = finalColumn; co >= columnStart; co--) + { + XLCell cell; + if (_cellsDictionary.TryGetValue(new XLSheetPoint(ro, co), out cell) + && !cell.IsEmpty(includeFormats)) + return ro; + } + } + return 0; + } + + public int LastColumnUsed(int rowStart, int columnStart, int rowEnd, int columnEnd, Boolean includeFormats) + { + int finalRow = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd; + int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd; + for (int co = finalColumn; co >= columnStart; co--) + { + for (int ro = finalRow; ro >= rowStart; ro--) + { + XLCell cell; + if (_cellsDictionary.TryGetValue(new XLSheetPoint(ro, co), out cell) + && !cell.IsEmpty(includeFormats)) + return co; + } + } + return 0; + } + public void RemoveAll(Int32 rowStart, Int32 columnStart, Int32 rowEnd, Int32 columnEnd) { diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs index 80630a2..42323f0 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs @@ -766,8 +766,14 @@ public XLRangeColumn FirstColumnUsed(bool includeFormats) { - var firstCellUsed = FirstCellUsed(includeFormats); - return firstCellUsed == null ? null : Column(firstCellUsed.Address.ColumnNumber); + Int32 firstColumnUsed = Worksheet.Internals.CellsCollection.FirstColumnUsed( + RangeAddress.FirstAddress.RowNumber, + RangeAddress.FirstAddress.ColumnNumber, + RangeAddress.LastAddress.RowNumber, + RangeAddress.LastAddress.ColumnNumber, + includeFormats); + + return firstColumnUsed == 0 ? null : Column(firstColumnUsed); } public XLRangeColumn LastColumnUsed() @@ -777,8 +783,14 @@ public XLRangeColumn LastColumnUsed(bool includeFormats) { - var lastCellUsed = LastCellUsed(includeFormats); - return lastCellUsed == null ? null : Column(lastCellUsed.Address.ColumnNumber); + Int32 lastColumnUsed = Worksheet.Internals.CellsCollection.LastColumnUsed( + RangeAddress.FirstAddress.RowNumber, + RangeAddress.FirstAddress.ColumnNumber, + RangeAddress.LastAddress.RowNumber, + RangeAddress.LastAddress.ColumnNumber, + includeFormats); + + return lastColumnUsed == 0 ? null : Column(lastColumnUsed); } public XLRangeRow FirstRow() @@ -798,8 +810,14 @@ public XLRangeRow LastRowUsed(bool includeFormats) { - var lastCellUsed = LastCellUsed(includeFormats); - return lastCellUsed == null ? null : Row(lastCellUsed.Address.RowNumber); + Int32 lastRowUsed = Worksheet.Internals.CellsCollection.LastRowUsed( + RangeAddress.FirstAddress.RowNumber, + RangeAddress.FirstAddress.ColumnNumber, + RangeAddress.LastAddress.RowNumber, + RangeAddress.LastAddress.ColumnNumber, + includeFormats); + + return lastRowUsed == 0 ? null : Row(lastRowUsed); } public XLRangeRow FirstRowUsed() @@ -809,8 +827,14 @@ public XLRangeRow FirstRowUsed(bool includeFormats) { - var firstCellUsed = FirstCellUsed(includeFormats); - return firstCellUsed == null ? null : Row(firstCellUsed.Address.RowNumber); + Int32 firstRowUsed = Worksheet.Internals.CellsCollection.FirstRowUsed( + RangeAddress.FirstAddress.RowNumber, + RangeAddress.FirstAddress.ColumnNumber, + RangeAddress.LastAddress.RowNumber, + RangeAddress.LastAddress.ColumnNumber, + includeFormats); + + return firstRowUsed == 0 ? null : Row(firstRowUsed); } public XLRangeRow Row(Int32 row) diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs index af764a3..8c189b7 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -471,13 +471,14 @@ public XLCell FirstCellUsed(Boolean includeFormats) { - var cellsUsed = CellsUsed(includeFormats); + var sp = Worksheet.Internals.CellsCollection.FirstPointUsed( + RangeAddress.FirstAddress.RowNumber, + RangeAddress.FirstAddress.ColumnNumber, + RangeAddress.LastAddress.RowNumber, + RangeAddress.LastAddress.ColumnNumber, + includeFormats); - if (!cellsUsed.Any()) - return null; - int firstRow = cellsUsed.Min(c => c.Address.RowNumber); - int firstColumn = cellsUsed.Min(c => c.Address.ColumnNumber); - return Worksheet.Cell(firstRow, firstColumn); + return sp.Row == 0 ? null : Worksheet.Cell(sp.Row, sp.Column); } public XLCell LastCellUsed() @@ -487,13 +488,14 @@ public XLCell LastCellUsed(Boolean includeFormats) { - var cellsUsed = CellsUsed(includeFormats); - if (!cellsUsed.Any()) - return null; + var sp = Worksheet.Internals.CellsCollection.LastPointUsed( + RangeAddress.FirstAddress.RowNumber, + RangeAddress.FirstAddress.ColumnNumber, + RangeAddress.LastAddress.RowNumber, + RangeAddress.LastAddress.ColumnNumber, + includeFormats); - int lastRow = cellsUsed.Max(c => c.Address.RowNumber); - int lastColumn = cellsUsed.Max(c => c.Address.ColumnNumber); - return Worksheet.Cell(lastRow, lastColumn); + return sp.Row == 0 ? null : Worksheet.Cell(sp.Row, sp.Column); } public XLCell Cell(Int32 row, Int32 column)