diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs index 5039b6c..4ba4b46 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs @@ -354,7 +354,9 @@ IXLBaseAutoFilter AutoFilter { get; } - IXLRows RowsUsed(Boolean includeFormats = false); - IXLColumns ColumnsUsed(Boolean includeFormats = false); + IXLRows RowsUsed(Boolean includeFormats = false, Func predicate = null); + IXLRows RowsUsed(Func predicate); + IXLColumns ColumnsUsed(Boolean includeFormats = false, Func predicate = null); + IXLColumns ColumnsUsed(Func predicate); } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/IXLRange.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/IXLRange.cs index 56aa5d8..b813037 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/IXLRange.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/IXLRange.cs @@ -46,25 +46,25 @@ /// /// Gets the first column of the range. /// - IXLRangeColumn FirstColumn(); + IXLRangeColumn FirstColumn(Func predicate = null); /// /// Gets the first column of the range that contains a cell with a value. /// - IXLRangeColumn FirstColumnUsed(); - IXLRangeColumn FirstColumnUsed(Boolean includeFormats); + IXLRangeColumn FirstColumnUsed(Boolean includeFormats, Func predicate = null); + IXLRangeColumn FirstColumnUsed(Func predicate = null); /// /// Gets the last column of the range. /// - IXLRangeColumn LastColumn(); + IXLRangeColumn LastColumn(Func predicate = null); /// /// Gets the last column of the range that contains a cell with a value. /// - IXLRangeColumn LastColumnUsed(); - IXLRangeColumn LastColumnUsed(Boolean includeFormats); + IXLRangeColumn LastColumnUsed(Boolean includeFormats, Func predicate = null); + IXLRangeColumn LastColumnUsed(Func predicate = null); /// /// Gets a collection of all columns in this range. /// - IXLRangeColumns Columns(); + IXLRangeColumns Columns(Func predicate = null); /// /// Gets a collection of the specified columns in this range. /// @@ -87,30 +87,29 @@ /// /// Gets the first row of the range. /// - IXLRangeRow FirstRow(); + IXLRangeRow FirstRow(Func predicate = null); /// /// Gets the first row of the range that contains a cell with a value. /// - IXLRangeRow FirstRowUsed(); - IXLRangeRow FirstRowUsed(Boolean includeFormats); + IXLRangeRow FirstRowUsed(Boolean includeFormats, Func predicate = null); + IXLRangeRow FirstRowUsed(Func predicate = null); /// /// Gets the last row of the range. /// - IXLRangeRow LastRow(); + IXLRangeRow LastRow(Func predicate = null); /// /// Gets the last row of the range that contains a cell with a value. /// - IXLRangeRow LastRowUsed(); - IXLRangeRow LastRowUsed(Boolean includeFormats); + IXLRangeRow LastRowUsed(Boolean includeFormats, Func predicate = null); + IXLRangeRow LastRowUsed(Func predicate = null); /// /// Gets the specified row of the range. /// /// The range row. IXLRangeRow Row(int row); - /// - /// Gets a collection of all rows in this range. - /// - IXLRangeRows Rows(); + + IXLRangeRows Rows(Func predicate = null); + /// /// Gets a collection of the specified rows in this range. /// @@ -239,11 +238,10 @@ /// Specify what you want to clear. new IXLRange Clear(XLClearOptions clearOptions = XLClearOptions.ContentsAndFormats); - IXLRangeRows RowsUsed(Boolean includeFormats = false); - IXLRangeColumns ColumnsUsed(Boolean includeFormats = false); - - IXLRangeRows Rows(Func predicate); - IXLRangeColumns Columns(Func predicate); + IXLRangeRows RowsUsed(Boolean includeFormats, Func predicate = null); + IXLRangeRows RowsUsed(Func predicate = null); + IXLRangeColumns ColumnsUsed(Boolean includeFormats, Func predicate = null); + IXLRangeColumns ColumnsUsed(Func predicate = null); } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs index 57946b3..75c5d76 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRange.cs @@ -15,8 +15,8 @@ if (!xlRangeParameters.IgnoreEvents) { - SubscribeToShiftedRows((range, rowsShifted) => WorksheetRangeShiftedRows(range, rowsShifted)); - SubscribeToShiftedColumns((range, columnsShifted) => WorksheetRangeShiftedColumns(range, columnsShifted)); + SubscribeToShiftedRows(WorksheetRangeShiftedRows); + SubscribeToShiftedColumns(WorksheetRangeShiftedColumns); xlRangeParameters.IgnoreEvents = true; } SetStyle(xlRangeParameters.DefaultStyle); @@ -28,65 +28,6 @@ #region IXLRange Members - IXLRangeColumn IXLRange.FirstColumn() - { - return FirstColumn(); - } - - IXLRangeColumn IXLRange.LastColumn() - { - return LastColumn(); - } - - IXLRangeColumn IXLRange.FirstColumnUsed() - { - return FirstColumnUsed(); - } - - IXLRangeColumn IXLRange.FirstColumnUsed(bool includeFormats) - { - return FirstColumnUsed(includeFormats); - } - - IXLRangeColumn IXLRange.LastColumnUsed() - { - return LastColumnUsed(); - } - - IXLRangeColumn IXLRange.LastColumnUsed(bool includeFormats) - { - return LastColumnUsed(includeFormats); - } - - IXLRangeRow IXLRange.FirstRow() - { - return FirstRow(); - } - - IXLRangeRow IXLRange.LastRow() - { - return LastRow(); - } - - IXLRangeRow IXLRange.LastRowUsed() - { - return LastRowUsed(); - } - - IXLRangeRow IXLRange.LastRowUsed(bool includeFormats) - { - return LastRowUsed(includeFormats); - } - - IXLRangeRow IXLRange.FirstRowUsed() - { - return FirstRowUsed(); - } - - IXLRangeRow IXLRange.FirstRowUsed(bool includeFormats) - { - return FirstRowUsed(includeFormats); - } IXLRangeRow IXLRange.Row(Int32 row) { @@ -103,23 +44,14 @@ return Column(column); } - public IXLRangeColumns Columns() - { - var retVal = new XLRangeColumns(); - Int32 columnCount = ColumnCount(); - for (Int32 c = 1; c <= columnCount; c++ ) - retVal.Add(Column(c)); - return retVal; - } - - public IXLRangeColumns Columns(Func predicate) + public IXLRangeColumns Columns(Func predicate = null) { var retVal = new XLRangeColumns(); Int32 columnCount = ColumnCount(); for (Int32 c = 1; c <= columnCount; c++) { var column = Column(c); - if (predicate(column)) + if (predicate == null || predicate(column)) retVal.Add(column); else column.Dispose(); @@ -228,23 +160,14 @@ return Range(firstCellRow, firstCellColumn, lastCellRow, lastCellColumn); } - public IXLRangeRows Rows() - { - var retVal = new XLRangeRows(); - Int32 rowCount = RowCount(); - for (Int32 r = 1; r <= rowCount; r++ ) - retVal.Add(Row(r)); - return retVal; - } - - public IXLRangeRows Rows(Func predicate) + public IXLRangeRows Rows(Func predicate = null) { var retVal = new XLRangeRows(); Int32 rowCount = RowCount(); for (Int32 r = 1; r <= rowCount; r++) { var row = Row(r); - if (predicate(row)) + if (predicate == null || predicate(row)) retVal.Add(Row(r)); else row.Dispose(); @@ -428,92 +351,276 @@ ShiftRows(RangeAddress, range, rowsShifted); } - public XLRangeColumn FirstColumn() + IXLRangeColumn IXLRange.FirstColumn(Func predicate) { - return Column(1); + return FirstColumn(predicate); + } + public XLRangeColumn FirstColumn(Func predicate = null) + { + if (predicate == null) + return Column(1); + + Int32 columnCount = ColumnCount(); + for (Int32 c = 1; c <= columnCount; c++) + { + var column = Column(c); + if (predicate(column)) return column; + + column.Dispose(); + } + + return null; } - public IXLRangeColumn LastColumn() + IXLRangeColumn IXLRange.LastColumn(Func predicate) { - return Column(ColumnCount()); + return LastColumn(predicate); + } + public XLRangeColumn LastColumn(Func predicate = null) + { + Int32 columnCount = ColumnCount(); + if (predicate == null) + return Column(columnCount); + + for (Int32 c = columnCount; c >= 1; c--) + { + var column = Column(c); + if (predicate(column)) return column; + + column.Dispose(); + } + + return null; } - public XLRangeColumn FirstColumnUsed() + IXLRangeColumn IXLRange.FirstColumnUsed(Func predicate ) { - return FirstColumnUsed(false); + return FirstColumnUsed(false, predicate); + } + public XLRangeColumn FirstColumnUsed(Func predicate = null) + { + return FirstColumnUsed(false, predicate); } - public XLRangeColumn FirstColumnUsed(bool includeFormats) + IXLRangeColumn IXLRange.FirstColumnUsed(Boolean includeFormats, Func predicate) { - Int32 firstColumnUsed = Worksheet.Internals.CellsCollection.FirstColumnUsed( - RangeAddress.FirstAddress.RowNumber, - RangeAddress.FirstAddress.ColumnNumber, - RangeAddress.LastAddress.RowNumber, - RangeAddress.LastAddress.ColumnNumber, - includeFormats); + return FirstColumnUsed(includeFormats, predicate); + } + public XLRangeColumn FirstColumnUsed(Boolean includeFormats, Func predicate = null) + { + Int32 columnCount = ColumnCount(); + for (Int32 co = 1; co <= columnCount; co++) + { + var column = Column(co); - return firstColumnUsed == 0 ? null : Column(firstColumnUsed); + if (!column.IsEmpty(includeFormats) && (predicate == null || predicate(column))) + return column; + column.Dispose(); + } + return null; } - public XLRangeColumn LastColumnUsed() + IXLRangeColumn IXLRange.LastColumnUsed(Func predicate) { - return LastColumnUsed(false); + return LastColumnUsed(false, predicate); + } + public XLRangeColumn LastColumnUsed(Func predicate = null) + { + return LastColumnUsed(false, predicate); } - public XLRangeColumn LastColumnUsed(bool includeFormats) + IXLRangeColumn IXLRange.LastColumnUsed(Boolean includeFormats, Func predicate) { - Int32 lastColumnUsed = Worksheet.Internals.CellsCollection.LastColumnUsed( - RangeAddress.FirstAddress.RowNumber, - RangeAddress.FirstAddress.ColumnNumber, - RangeAddress.LastAddress.RowNumber, - RangeAddress.LastAddress.ColumnNumber, - includeFormats); + return LastColumnUsed(includeFormats, predicate); + } + public XLRangeColumn LastColumnUsed(Boolean includeFormats, Func predicate = null) + { + if (predicate == null) + { + 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); + return lastColumnUsed == 0 ? null : Column(lastColumnUsed); + } + + Int32 columnCount = ColumnCount(); + for (Int32 co = columnCount; co >= 1; co--) + { + var column = Column(co); + + if (!column.IsEmpty(includeFormats) && predicate(column)) + return column; + column.Dispose(); + } + return null; } - public XLRangeRow FirstRow() + IXLRangeRow IXLRange.FirstRow(Func predicate) { - return Row(1); + return FirstRow(predicate); + } + public XLRangeRow FirstRow(Func predicate = null) + { + if (predicate == null) + return Row(1); + + Int32 rowCount = RowCount(); + for (Int32 ro = 1; ro <= rowCount; ro++) + { + var row = Row(ro); + if (predicate(row)) return row; + + row.Dispose(); + } + + return null; } - public IXLRangeRow LastRow() + IXLRangeRow IXLRange.LastRow(Func predicate) { - return Row(RowCount()); + return LastRow(predicate); + } + public XLRangeRow LastRow(Func predicate = null) + { + Int32 rowCount = RowCount(); + if (predicate == null) + return Row(rowCount); + + for (Int32 ro = rowCount; ro >= 1; ro--) + { + var row = Row(ro); + if (predicate(row)) return row; + + row.Dispose(); + } + + return null; } - public XLRangeRow LastRowUsed() + IXLRangeRow IXLRange.FirstRowUsed(Func predicate) { - return LastRowUsed(false); + return FirstRowUsed(false, predicate); + } + public XLRangeRow FirstRowUsed(Func predicate = null) + { + return FirstRowUsed(false, predicate); } - public XLRangeRow LastRowUsed(bool includeFormats) + IXLRangeRow IXLRange.FirstRowUsed(Boolean includeFormats, Func predicate) { - Int32 lastRowUsed = Worksheet.Internals.CellsCollection.LastRowUsed( - RangeAddress.FirstAddress.RowNumber, - RangeAddress.FirstAddress.ColumnNumber, - RangeAddress.LastAddress.RowNumber, - RangeAddress.LastAddress.ColumnNumber, - includeFormats); + return FirstRowUsed(includeFormats, predicate); + } + public XLRangeRow FirstRowUsed(Boolean includeFormats, Func predicate = null) + { + Int32 rowCount = RowCount(); + for (Int32 ro = 1; ro <= rowCount; ro++) + { + var row = Row(ro); - return lastRowUsed == 0 ? null : Row(lastRowUsed); + if (!row.IsEmpty(includeFormats) && (predicate == null || predicate(row))) + return row; + row.Dispose(); + } + return null; } - public XLRangeRow FirstRowUsed() + IXLRangeRow IXLRange.LastRowUsed(Func predicate) { - return FirstRowUsed(false); + return LastRowUsed(false, predicate); + } + public XLRangeRow LastRowUsed(Func predicate = null) + { + return LastRowUsed(false, predicate); } - public XLRangeRow FirstRowUsed(bool includeFormats) + IXLRangeRow IXLRange.LastRowUsed(Boolean includeFormats, Func predicate) { - Int32 firstRowUsed = Worksheet.Internals.CellsCollection.FirstRowUsed( - RangeAddress.FirstAddress.RowNumber, - RangeAddress.FirstAddress.ColumnNumber, - RangeAddress.LastAddress.RowNumber, - RangeAddress.LastAddress.ColumnNumber, - includeFormats); + return LastRowUsed(includeFormats, predicate); + } + public XLRangeRow LastRowUsed(Boolean includeFormats, Func predicate = null) + { + if (predicate == null) + { + Int32 lastRowUsed = Worksheet.Internals.CellsCollection.LastRowUsed( + RangeAddress.FirstAddress.RowNumber, + RangeAddress.FirstAddress.ColumnNumber, + RangeAddress.LastAddress.RowNumber, + RangeAddress.LastAddress.ColumnNumber, + includeFormats); - return firstRowUsed == 0 ? null : Row(firstRowUsed); + return lastRowUsed == 0 ? null : Row(lastRowUsed); + } + + Int32 rowCount = RowCount(); + for (Int32 ro = rowCount; ro >= 1; ro--) + { + var row = Row(ro); + + if (!row.IsEmpty(includeFormats) && predicate(row)) + return row; + row.Dispose(); + } + return null; + } + + + IXLRangeRows IXLRange.RowsUsed(Boolean includeFormats, Func predicate) + { + return RowsUsed(includeFormats, predicate); + } + public XLRangeRows RowsUsed(Boolean includeFormats, Func predicate = null) + { + XLRangeRows rows = new XLRangeRows(); + Int32 rowCount = RowCount(); + for (Int32 ro = 1; ro <= rowCount; ro++) + { + var row = Row(ro); + + if (!row.IsEmpty(includeFormats) && (predicate == null || predicate(row))) + rows.Add(row); + else + row.Dispose(); + } + return rows; + } + IXLRangeRows IXLRange.RowsUsed(Func predicate) + { + return RowsUsed(predicate); + } + public XLRangeRows RowsUsed(Func predicate = null) + { + return RowsUsed(false, predicate); + } + IXLRangeColumns IXLRange.ColumnsUsed(Boolean includeFormats, Func predicate) + { + return ColumnsUsed(includeFormats, predicate); + } + public XLRangeColumns ColumnsUsed(Boolean includeFormats, Func predicate = null) + { + XLRangeColumns columns = new XLRangeColumns(); + Int32 columnCount = ColumnCount(); + for (Int32 co = 1; co <= columnCount; co++) + { + var column = Column(co); + + if (!column.IsEmpty(includeFormats) && (predicate == null || predicate(column))) + columns.Add(column); + else + column.Dispose(); + } + return columns; + } + IXLRangeColumns IXLRange.ColumnsUsed(Func predicate) + { + return ColumnsUsed(predicate); + } + public XLRangeColumns ColumnsUsed(Func predicate = null) + { + return ColumnsUsed(false, predicate); } public XLRangeRow Row(Int32 row) diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs index 3acc109..3325338 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -1415,44 +1415,6 @@ return Worksheet.AutoFilter.Set(asRange); } - public IXLRangeRows RowsUsed(Boolean includeFormats = false) - { - var rows = new XLRangeRows(); - using (var rangeUsed = RangeUsed(includeFormats)) - { - if (rangeUsed != null) - { - using (var usedRows = rangeUsed.Rows(r => !r.IsEmpty(includeFormats))) - { - foreach (var row in usedRows) - { - rows.Add(row); - } - } - } - } - return rows; - } - - public IXLRangeColumns ColumnsUsed(Boolean includeFormats = false) - { - var columns = new XLRangeColumns(); - using (var rangeUsed = RangeUsed(includeFormats)) - { - if (rangeUsed != null) - { - using (var usedColumns = rangeUsed.Columns(c => !c.IsEmpty(includeFormats))) - { - foreach (var column in usedColumns) - { - columns.Add(column); - } - } - } - } - return columns; - } - #region Sort public IXLSortElements SortRows diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/IXLRows.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/IXLRows.cs index c05cdcb..834a87b 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/IXLRows.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/IXLRows.cs @@ -3,7 +3,7 @@ namespace ClosedXML.Excel { - public interface IXLRows: IEnumerable + public interface IXLRows: IEnumerable, IDisposable { /// /// Sets the height of all rows. diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRows.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRows.cs index f02aa96..1c8deb3 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRows.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Rows/XLRows.cs @@ -264,5 +264,11 @@ _rows.ForEach(c => c.Clear(clearOptions)); return this; } + + public void Dispose() + { + if (_rows != null) + _rows.ForEach(r => r.Dispose()); + } } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/IXLTable.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/IXLTable.cs index 19e25dd..dfd954e 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/IXLTable.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/IXLTable.cs @@ -84,25 +84,12 @@ IXLTableField Field(int fieldIndex); IEnumerable Fields { get; } - /// - /// Gets the first data row of the table. - /// - IXLTableRow FirstRow(); - - /// - /// Gets the first data row of the table that contains a cell with a value. - /// - IXLTableRow FirstRowUsed(); - - /// - /// Gets the last data row of the table. - /// - IXLTableRow LastRow(); - - /// - /// Gets the last data row of the table that contains a cell with a value. - /// - IXLTableRow LastRowUsed(); + IXLTableRow FirstRow(Func predicate = null); + IXLTableRow FirstRowUsed(Boolean includeFormats, Func predicate = null); + IXLTableRow FirstRowUsed(Func predicate = null); + IXLTableRow LastRow(Func predicate = null); + IXLTableRow LastRowUsed(Boolean includeFormats, Func predicate = null); + IXLTableRow LastRowUsed(Func predicate = null); /// /// Gets the specified row of the table data. @@ -110,10 +97,7 @@ /// The table row. IXLTableRow Row(int row); - /// - /// Gets a collection of all data rows in this table. - /// - IXLTableRows Rows(); + IXLTableRows Rows(Func predicate = null); /// /// Gets a collection of the specified data rows in this table. @@ -178,30 +162,14 @@ /// The range column. IXLRangeColumn Column(string column); - /// - /// Gets the first column of the range. - /// - IXLRangeColumn FirstColumn(); - - /// - /// Gets the first column of the range that contains a cell with a value. - /// - IXLRangeColumn FirstColumnUsed(); - - /// - /// Gets the last column of the range. - /// - IXLRangeColumn LastColumn(); - - /// - /// Gets the last column of the range that contains a cell with a value. - /// - IXLRangeColumn LastColumnUsed(); - - /// - /// Gets a collection of all columns in this range. - /// - IXLRangeColumns Columns(); + IXLRangeColumn FirstColumn(Func predicate = null); + IXLRangeColumn FirstColumnUsed(Boolean includeFormats, Func predicate = null); + IXLRangeColumn FirstColumnUsed(Func predicate = null); + IXLRangeColumn LastColumn(Func predicate = null); + IXLRangeColumn LastColumnUsed(Boolean includeFormats, Func predicate = null); + IXLRangeColumn LastColumnUsed(Func predicate = null); + + IXLRangeColumns Columns(Func predicate = null); /// /// Gets a collection of the specified columns in this range. @@ -357,5 +325,10 @@ new IXLTable Clear(XLClearOptions clearOptions = XLClearOptions.ContentsAndFormats); IXLBaseAutoFilter AutoFilter { get; } + + IXLTableRows RowsUsed(Boolean includeFormats, Func predicate = null); + IXLTableRows RowsUsed(Func predicate = null); + IXLRangeColumns ColumnsUsed(Boolean includeFormats, Func predicate = null); + IXLRangeColumns ColumnsUsed(Func predicate = null); } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/XLTable.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/XLTable.cs index 47d642f..937a201 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/XLTable.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Tables/XLTable.cs @@ -118,31 +118,130 @@ public IXLRangeRow TotalsRow() { if (ShowTotalsRow) - return new XLTableRow(this, (XLRangeRow)base.LastRow()); + return new XLTableRow(this, base.LastRow()); throw new InvalidOperationException("Cannot access TotalsRow if ShowTotals property is false"); } - public new IXLTableRow FirstRow() + IXLTableRow IXLTable.FirstRow(Func predicate) { - return Row(1); + return FirstRow(predicate); + } + public XLTableRow FirstRow(Func predicate = null) + { + using (var dataRange = DataRange) + { + if (predicate == null) + return new XLTableRow(this, (dataRange.FirstRow() as XLRangeRow)); + + Int32 rowCount = dataRange.RowCount(); + + for (Int32 ro = 1; ro <= rowCount; ro++) + { + var row = new XLTableRow(this, (dataRange.Row(ro) as XLRangeRow)); + if (predicate(row)) return row; + + row.Dispose(); + } + } + return null; } - public new IXLTableRow FirstRowUsed() + IXLTableRow IXLTable.FirstRowUsed(Func predicate) { - return new XLTableRow(this, (XLRangeRow)(DataRange.FirstRowUsed())); + return FirstRowUsed(false, predicate); + } + public XLTableRow FirstRowUsed(Func predicate = null) + { + return FirstRowUsed(false, predicate); } - public new IXLTableRow LastRow() + IXLTableRow IXLTable.FirstRowUsed(Boolean includeFormats, Func predicate) { - return ShowTotalsRow - ? new XLTableRow(this, base.Row(RowCount() - 1)) - : new XLTableRow(this, base.Row(RowCount())); + return FirstRowUsed(includeFormats, predicate); + } + public XLTableRow FirstRowUsed(Boolean includeFormats, Func predicate = null) + { + using (var dataRange = DataRange) + { + if (predicate == null) + return new XLTableRow(this, (dataRange.FirstRowUsed(includeFormats) as XLRangeRow)); + + Int32 rowCount = dataRange.RowCount(); + + for (Int32 ro = 1; ro <= rowCount; ro++) + { + var row = new XLTableRow(this, (dataRange.Row(ro) as XLRangeRow)); + + if (!row.IsEmpty(includeFormats) && predicate(row)) + return row; + row.Dispose(); + } + } + + return null; } - public new IXLTableRow LastRowUsed() + + + + IXLTableRow IXLTable.LastRow(Func predicate) { - return new XLTableRow(this, (XLRangeRow)(DataRange.LastRowUsed())); + return LastRow(predicate); + } + public XLTableRow LastRow(Func predicate = null) + { + using (var dataRange = DataRange) + { + if (predicate == null) + return new XLTableRow(this, (dataRange.LastRow() as XLRangeRow)); + + Int32 rowCount = dataRange.RowCount(); + + for (Int32 ro = rowCount; ro >= 1; ro--) + { + var row = new XLTableRow(this, (dataRange.Row(ro) as XLRangeRow)); + if (predicate(row)) return row; + + row.Dispose(); + } + } + return null; + } + + IXLTableRow IXLTable.LastRowUsed(Func predicate) + { + return LastRowUsed(false, predicate); + } + public XLTableRow LastRowUsed(Func predicate = null) + { + return LastRowUsed(false, predicate); + } + + IXLTableRow IXLTable.LastRowUsed(Boolean includeFormats, Func predicate) + { + return LastRowUsed(includeFormats, predicate); + } + public XLTableRow LastRowUsed(Boolean includeFormats, Func predicate = null) + { + using (var dataRange = DataRange) + { + if (predicate == null) + return new XLTableRow(this, (dataRange.LastRowUsed(includeFormats) as XLRangeRow)); + + Int32 rowCount = dataRange.RowCount(); + + for (Int32 ro = rowCount; ro >= 1; ro--) + { + var row = new XLTableRow(this, (dataRange.Row(ro) as XLRangeRow)); + + if (!row.IsEmpty(includeFormats) && predicate(row)) + return row; + row.Dispose(); + } + } + + return null; } IXLTableRow IXLTable.Row(int row) @@ -150,11 +249,22 @@ return Row(row); } - public new IXLTableRows Rows() + public new IXLTableRows Rows(Func predicate = null) { var retVal = new XLTableRows(Worksheet.Style); - foreach (int r in Enumerable.Range(1, DataRange.RowCount())) - retVal.Add(Row(r)); + using (var dataRange = DataRange) + { + Int32 rowCount = dataRange.RowCount(); + + for (int r = 1; r <= rowCount; r++) + { + var row = Row(r); + if (predicate == null || predicate(row)) + retVal.Add(row); + else + row.Dispose(); + } + } return retVal; } @@ -209,7 +319,7 @@ return DataRange.Column(GetFieldIndex(column) + 1); } - public new IXLRangeColumns Columns() + public new IXLRangeColumns Columns(Func predicate = null) { return DataRange.Columns(); } @@ -382,19 +492,34 @@ } - IXLRangeColumn IXLTable.FirstColumn() + IXLRangeColumn IXLTable.FirstColumn(Func predicate) { - return FirstColumn(); + return FirstColumn(predicate); } - IXLRangeColumn IXLTable.FirstColumnUsed() + IXLRangeColumn IXLTable.LastColumn(Func predicate) { - return FirstColumnUsed(); + return LastColumn(predicate); } - IXLRangeColumn IXLTable.LastColumnUsed() + IXLRangeColumn IXLTable.FirstColumnUsed(Func predicate) { - return LastColumnUsed(); + return FirstColumnUsed(false, predicate); + } + + IXLRangeColumn IXLTable.FirstColumnUsed(Boolean includeFormats, Func predicate) + { + return FirstColumnUsed(includeFormats, predicate); + } + + IXLRangeColumn IXLTable.LastColumnUsed(Func predicate) + { + return LastColumnUsed(false, predicate); + } + + IXLRangeColumn IXLTable.LastColumnUsed(Boolean includeFormats, Func predicate) + { + return LastColumnUsed(includeFormats, predicate); } public new IXLRange Sort(String columnsToSortBy, XLSortOrder sortOrder = XLSortOrder.Ascending, @@ -526,5 +651,50 @@ throw new ArgumentOutOfRangeException("The header row doesn't contain field name '" + name + "'."); } + + IXLRangeColumns IXLTable.ColumnsUsed(Boolean includeFormats, Func predicate) + { + return ColumnsUsed(includeFormats, predicate); + } + + IXLRangeColumns IXLTable.ColumnsUsed(Func predicate) + { + return ColumnsUsed(predicate); + } + + IXLTableRows IXLTable.RowsUsed(Boolean includeFormats, Func predicate) + { + return RowsUsed(includeFormats, predicate); + } + public IXLTableRows RowsUsed(Boolean includeFormats, Func predicate = null) + { + var rows = new XLTableRows(Worksheet.Style); + Int32 rowCount; + if (_showTotalsRow) + rowCount = RowCount() - 1; + else + rowCount = RowCount(); + + for (Int32 ro = 1; ro <= rowCount; ro++) + { + var row = Row(ro); + + if (!row.IsEmpty(includeFormats) && (predicate == null || predicate(row))) + rows.Add(row); + else + row.Dispose(); + } + return rows; + } + + + IXLTableRows IXLTable.RowsUsed(Func predicate) + { + return RowsUsed(predicate); + } + public IXLTableRows RowsUsed(Func predicate = null) + { + return RowsUsed(false, predicate); + } } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs index 8c8046d..f77c0cd 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs @@ -863,21 +863,49 @@ get { return AutoFilter; } } - public new IXLRows RowsUsed(Boolean includeFormats = false) + public IXLRows RowsUsed(Boolean includeFormats = false, Func predicate = null) { var rows = new XLRows(Worksheet); - foreach (IXLRangeRow row in base.RowsUsed(includeFormats)) - rows.Add(Row(row.RowNumber())); + using (var asRange = AsRange()) + { + var rowsUsed = asRange.RowsUsed(includeFormats); + foreach (IXLRangeRow row in rowsUsed) + { + var retRow = Row(row.RowNumber()); + if (predicate == null || predicate(retRow)) + rows.Add(retRow); + else + retRow.Dispose(); + } + } return rows; } + public IXLRows RowsUsed(Func predicate = null) + { + return RowsUsed(false, predicate); + } - public new IXLColumns ColumnsUsed(Boolean includeFormats = false) + public IXLColumns ColumnsUsed(Boolean includeFormats = false, Func predicate = null) { var columns = new XLColumns(Worksheet); - foreach (IXLRangeColumn column in base.ColumnsUsed(includeFormats)) - columns.Add(Column(column.ColumnNumber())); + using (var asRange = AsRange()) + { + var columnsUsed = asRange.ColumnsUsed(includeFormats); + foreach (IXLRangeColumn column in columnsUsed) + { + var retColumn = Column(column.ColumnNumber()); + if (predicate == null || predicate(retColumn)) + columns.Add(retColumn); + else + retColumn.Dispose(); + } + } return columns; } + public IXLColumns ColumnsUsed(Func predicate = null) + { + return ColumnsUsed(false, predicate); + } public new void Dispose() { @@ -886,8 +914,6 @@ Internals.Dispose(); - - base.Dispose(); }