# finding Last row ??



## Michael M (Oct 14, 2009)

Hi All
I thought this would be a lounge type question.
I have noticed over some time that many users have a different spin on finding the last row.
I was wondering which is the fastest, most efficient, etc.

I use:

```
Lrow=Cells(Rows.Count,"A").End(xlUp).Row
```

while others use:

```
LR = Range("A" & Rows.Count).End(xlUp).Row
```
and some are still using the range reference of 65000, or 1 million now.

It probably makes bugger all difference, but it has been *****ing my curiosity

Regards
Michael M


----------



## lenze (Oct 14, 2009)

I suggest you search (Google? or the board?)for how to time a macro and test it out. It's a good learning exercise.
lenze
FYI: Bill has this in the book _Excel Gurus Gone Wild_


----------



## Michael M (Oct 14, 2009)

Thanks Lenze
I was more interested in the reasoning behind the different ways you guys find the last row.
In the 2 examples I mentioned, both are used by very experienced and skilled MVP's.
I was curious as to why one MVP would use 1 example over the other.
Maybe I'm just having a quiet day....what do they say about idle minds, or is it hands.


Regards
Michael M


----------



## Michael M (Oct 14, 2009)

Just for interest sake
sample 2 was 1.01 secs slower than sample 1, in my model.

Regards
Michael M


----------



## lenze (Oct 14, 2009)

Actually, it's a matter of style and almost always goes back to how we learned!! A good example is Smitty and myself. We're good internet friends via MrExcel, but in many cases we don't code anything alike. Neither one of us thinks the other is wrong. We just do it differently. In fact, the difference can be obvious. Recently, I got a PM from a user with some code that they said I had posted somewhere, but I knew immediately it wasn't mine because to my knowledge I had NEVER done that task that way. But, I wrote back and told the guy(gal?) that I was 95% sure it was written by Smitty, and it was.

lenze

BTW: I am suprised the difference is that big


----------



## Michael M (Oct 14, 2009)

OK....that's what I was looking at.
I had seen a number of things done differently, but this was a simple one liner, so I chose it, as it seems to be one of things we almost always do in a macro.
I have learned that you guys all approach things a little differently. If you didn't, we woudln't need a Mr Excel Forum. 
Thanks for the comments.
Regards
Michael M


----------



## DonkeyOte (Oct 15, 2009)

Method utilising Rows.Count is preferred given it is version independent.
Use of 65536 is open to error in 2007 and beyond, use of 1m is only viable in 2007 onwards.  
Use of Range / Cells is generally a case of preference (I tend to use Cells myself).
Also worth pointing out that the variable if explicitly declared should be declared as Long.


----------



## Colin Legg (Oct 15, 2009)

In terms of Cells property vs Range property

```
Cells(Rows.Count,"A").
```
vs.

```
Range("A" & Rows.Count).
```
There are clear situations when one would be required over the other, but I'd use either here.

More important is knowing some limitations of using Range.End() property to determine the last used cell. It's quick but it only works in simple situations. You can only use it on a single column so, short of looping through every column, it's no good if you want to find the last used row of a worksheet, and, if the last cell in the column hidden (say filtering is applied) then it will return the *wrong* result.


----------



## yytsunamiyy (Oct 15, 2009)

Colin, 

How would one find the real LRw in filtered datasets?


```
Sub foo2()
Dim lrw As Long
lrw = Sheets(1).Range(Cells(1, 1), Cells(Rows.Count, Columns.Count)).Find(what:="*", searchdirection:=xlPrevious, searchorder:=xlByRows).Row
Debug.Print lrw
End Sub
```
 
This finds the real LRw if hidden, but not if filtered.


----------



## DonkeyOte (Oct 15, 2009)

I guess there are various options, perhaps:


```
Sub foo2()
Dim lrw As Long
With Sheets(1)
    If .FilterMode Then lrw = .AutoFilter.Range.Row + .AutoFilter.Range.Rows.Count - 1
    lrw = Application.Max(lrw,.Cells.Find(what:="*", searchdirection:=xlPrevious, searchorder:=xlByRows).Row)
End With
Debug.Print lrw
End Sub
```


----------



## Colin Legg (Oct 15, 2009)

Like you, I tend to use Range.Find(). It's normally an option to remove any filtering before I call it. Other than filtering, another thing Range.Find() will miss is if the last cell only contains a prefix character, '. Taking those into account too, I don't think there is a 100% foolproof method to determine the last row without some sort of looping involved.

There's a temptation to try using Range.SpecialCells() [xlCellTypeConstants and xlCellTypeFormulas] and to derive the last cell from those, but there could be problems on large worksheets because the Range.SpecialCells() method has a limitation of 2^13 non-contiguous cells.


----------



## HalfAce (Oct 19, 2009)

For what it's worth, the most reliable & consistent method of determining the last used row (or column) I have seen uses .Find (filtered or not) like so:

```
Dim LstRw As Long, LstCol As Integer
LstRw = Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
LstCol = Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
```
This seems to work anytime, anywhere and is not effected by 'phantom' used cells (such as values & formulas that have been deleted) which are sometimes still seen as a used range by excel.
I don't remember who showed this to me (it was years ago) but I think it may have been Tom Urtis

Hope it helps.


----------



## Oorang (Oct 19, 2009)

There is a pretty exhaustive discussion of this topic here. It's a long thread about a lot of different stuff. But I do think the best way to accomplish this task (and the discussion of why) was hit on here. 


```
Public Function LastRowInSheet(wks As Worksheet) As Long 
     'From Rorya on MrExcel:
     'http://www.mrexcel.com/forum/showthread.php?p=1793851&posted=1#post17938521
     ' Returns the number of the last row with data anywhere in it
    LastRowInSheet = 1 
    On Error Resume Next 
    With wks.UsedRange 
        LastRowInSheet = .Cells.Find("*", .Cells(1), SearchOrder:=xlByRows, _ 
        SearchDirection:=xlPrevious).Row 
    End With 
End Function
```


----------



## snowblizz (Oct 20, 2009)

Interesting thread. It is something that pops up many times a day, and I *never* remember the same syntax twice.

Though that immediately sparks a follow up question.
Would you give a "good enough" answer or try and fit in the "perfect" one.

The End(xlUp) is fairly easy to understand, and quite often sufficient.Usually one can say with a certain degree of accuracy if a suggestion will be good enough to solve the problem. I usually avoid deviating too far from what someone has already posted, if at all posssible, as that's usually where their comfort level is.


----------



## Tom Urtis (Oct 20, 2009)

As I inch my way towards filing out the content on my web site, these 3 links might help anyone who's interested in finding the last row, column, or used range under various scenarios:

How to know the  last row or last column:
http://www.atlaspm.com/faqvbalastrow.html#61

Address of the sheet's used range:
http://www.atlaspm.com/faqvbausedrange.html#63

Address of used range when teh start and end cells are all unknown:
http://www.atlaspm.com/faqvbaunknownrange.html#65


----------



## Michael M (Oct 20, 2009)

Hmm, it seems my question did indeed, have many different thoughts from others and I will try some of the other ways of "finding the last cell"

Tom
I visited your website and I think it is going to provide a lot of assistance to people like myself, that always seem to have to "go find" the snippet I need, even though I have thousands of lines of my own, I never seem to have the couple of lines I want.

I look forward to visiting it again when it's completed.

Regards
Michael M


----------

