Detecting last data row in Excel.Workbook Object
I am reading in data from an Excel Workbook into an Access Database in Access.
How can I detect what is the last filled row of the Spreadsheet?
For example if the spreadsheet only has two rows populated, how can I stop the code from running down all 65000 rows?
Some things look too good to be true... mostly because they are!
Code:
MaxRowNumber = ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row
I can only seem to use this code only once during runtime, the second time I get a message 'Object Variable or With Block Variable not set'.
I am setting my ExcelApp object to nothing each time and closing the opened Workbook.
Good old Microsoft... something somewhere isn't being set to nothing!
I am using Excel 9.0 Object Library.
Re: Detecting last data row in Excel.Workbook Object
This works great, simple too. VB.NET
Dim OBJExcelc As Excel.Application
OBJExcelc.Worksheets(1).Select()
Dim rowCount = OBJExcelc.ActiveSheet.UsedRange.Rows.Count
MsgBox(rowCount)
Re: Detecting last data row in Excel.Workbook Object
Though this thread got bumped up from what looks like years ago, it's probably archived by search engines so I figured I'd contribute.
If you use
Code:
ActiveSheet.UsedRange.Rows.Count
to count the last row of data in a sheet, you will get the wrong row value if there are blank rows anywhere before the first used row.
For example, put a value in a cell on row 10 of a blank worksheet and use ActiveSheet.UsedRange.Rows.Count . You will get "1" instead of "10".
If you use
Code:
ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).row
as was suggested above, you will also get improper values under some circumstances. xlCellTypeLastCell seems to track NOT a cell that has a value in it, but cells that have been modified.
For example, put a value in cell A1 and run
Code:
msgbox ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).row
from a macro. Then select any cell below that and go Edit->Clear->All and run the macro again. The last row value returned will now be whatever the cleared cell's row was.
I use a method provided here; I have not yet found a situation where it has failed to give the proper result. (This is also what user Shivaraj posted above):
Code:
ActiveSheet.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).row
You can compare results yourself with this simple subroutine, ran on a new worksheet:
Code:
ActiveSheet.Cells(10, 1).Value = "test"
MsgBox ActiveSheet.UsedRange.Rows.Count
ActiveSheet.Cells(1, 1).Value = "Blah"
ActiveSheet.Cells(2, 1).Value = "hai"
ActiveSheet.Cells(10, 1).Clear
MsgBox ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).row
MsgBox ActiveSheet.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).row
I can confirm that the above is true and works with Excel 03; I am unable to test other versions.
Re: Detecting last data row in Excel.Workbook Object
Another method you can use if you know a column which will always contain data for a row is
Code:
Worksheet.Range("B65536").End(xlUp)
Of course this LastRow.End(xlUp) type of thing would need to be updated for the new 2007 formats. The strength of this method is it is much faster than looping cells in a range which could take forever. It also uses no extra memory. The weakness is that other columns in the row could contain data thus providing a false positive.
If you have to loop every cell in a row to determine if it is blank or not, I'd recommend this method.
Code:
Dim val2 as Variant
Dim sht as Worksheet
Set sht = <somesheet>
val2 = sht.UsedRange.Value2
Now val2 will be a 2 dimension array or variants that you can loop through. The benefit of using this method is that arrays are a billion times faster to loop through than ranges.
Re: Detecting last data row in Excel.Workbook Object
1. As mentioned, ActiveSheet.UsedRange.Rows.Count returns number of rows in UsedRange,
it may not indicate the last used row on the worksheet if the first row of the UsedRange is not row 1.
The correct way should be like this:
Code:
LastUsedRow = ActiveSheet.UsedRange.Rows.Count - ActiveSheet.UsedRange.Row + 1
ActiveSheet.UsedRange.Row is the first row of the UsedRange, in case if that is 1 then
LastUsedRow = ActiveSheet.UsedRange.Rows.Count - 1 + 1
However, what does "UsedRange" mean?
Yes, it means the used range on a worksheet!!!
The last row and the last column of UsedRange may NOT contain any data if they was used before with data entered then cleared or cell formated.
So, be careful when using UsedRange to find last row or last column.
This may also happen the same way when using .SpecialCells(xlCellTypeLastCell)
2. The .End(xlUp) method can give only the last row that contains data on a specified column but more reliable.
If you want to use it without worry about Excel version (2003 or 2007) then do not hard code 65536 there. Use this:
Code:
With Activesheet '-- or any sheet
LastRowOnColumn2 = .Cells(.Rows.Count, 2).End(xlUp).Row
End With
or without using [With] block:
Code:
LastRowOnColumn2 = Activesheet.Cells(Activesheet.Rows.Count, 2).End(xlUp).Row
.Rows.Count will return 65536 on Excel 2003 or 1048576 on Excel 2007.
Similarly, .Columns.Count will return 256 on Excel 2003 or 16384 on Excel 2007.
Re: Detecting last data row in Excel.Workbook Object
Quote:
Originally Posted by
anhn
1. As mentioned,
ActiveSheet.UsedRange.Rows.Count returns number of rows in UsedRange,
it may not indicate the last used row on the worksheet if the first row of the UsedRange is not row 1.
The correct way should be like this:
Code:
LastUsedRow = ActiveSheet.UsedRange.Rows.Count - ActiveSheet.UsedRange.Row + 1
ActiveSheet.UsedRange.Row is the first row of the UsedRange, in case if that is 1 then
LastUsedRow = ActiveSheet.UsedRange.Rows.Count - 1 + 1
However, what does "UsedRange" mean?
Yes, it means the used range on a worksheet!!!
The last row and the last column of UsedRange may
NOT contain any data if they was used before with data entered then cleared or cell formated.
So, be careful when using UsedRange to find last row or last column.
This may also happen the same way when using
.SpecialCells(xlCellTypeLastCell)
2. The
.End(xlUp) method can give only the last row that contains data on a specified column but more reliable.
If you want to use it without worry about Excel version (2003 or 2007) then do not hard code 65536 there. Use this:
Code:
With Activesheet '-- or any sheet
LastRowOnColumn2 = .Cells(.Rows.Count, 2).End(xlUp).Row
End With
or without using [With] block:
Code:
LastRowOnColumn2 = Activesheet.Cells(Activesheet.Rows.Count, 2).End(xlUp).Row
.Rows.Count will return 65536 on Excel 2003 or 1048576 on Excel 2007.
Similarly,
.Columns.Count will return 256 on Excel 2003 or 16384 on Excel 2007.
IHow can the last code above -LastRowOnColumn2 = ActiveSheet.Cells(ActiveSheet.Rows.Count, 2).End(xlUp).row --be modified to start with the first data row )10) and do a row count only to the first blank line? My worksheet is divided into two informal panels. To properly position the lower panel I need to get the last data line of the upper panel which may vary as rows are added or deleted in that panel.
Re: Detecting last data row in Excel.Workbook Object
try
vb Code:
lastrowbeforeemptycell = cells(10, col).end(xldown).row
where col is a column number that will not be empty within the block