AME
AME

Reputation: 5300

Locating Cell Values in Excel VBA

Using: Excel 2007/Win 7

First, I created a subroutine to find the dynamic range of a worksheet called 'WIP':

Sub GetWIPRange()
Dim WIPrng1 As Range
Dim WIPrng2 As Range
Sheets("WIP").Activate
Set WIPrng1 = Cells.find("*", [a1], , , xlByRows, xlPrevious)
Set WIPrng2 = Cells.find("*", [a1], , , xlByColumns, xlPrevious)
If Not WIPrng1 Is Nothing Then
    Set WIPrng3 = Range([a1], Cells(WIPrng1.Row, WIPrng2.Column))
Application.Goto WIPrng3
Else
    MsgBox "sheet is blank", vbCritical
End If
End Sub

Now I want to find a given contract number within the range defined above:

Sub find()
Dim find As Long
find = Application.WorksheetFunction.Match("545499", Range(WIPrng3.Parent.Name & "!" & WIPrng3.Address), 0)
MsgBox "Found at row : " & find
End Sub

But the error I get from the code above is:

Run-time error '91': Object variable With block variable not set.

  1. How can I fix this code so that it returns the row number of the value I'm seeking?
  2. Is there a more efficient way of finding cell values using VBA? For example, if I have many worksheets and I want to search all worksheets and return a value's specific row number and worksheet location.

Many thanks!

Upvotes: 1

Views: 10234

Answers (1)

Dick Kusleika
Dick Kusleika

Reputation: 33145

Where is WIPrng3 defined? Is it defined as Public? The problem is that WIPrng3 has gone out of scope by the time you run "find" and is therefore Nothing. You can check for Nothing in your "find" code and run the Get procedure if needed. Like this

Sub find()
    Dim find As Long

    If WIPrng3 Is Nothing Then GetWIPRange

    find = Application.WorksheetFunction.Match("545499", Range(WIPrng3.Parent.Name & "!" & WIPrng3.Columns(1).Address), 0)
    MsgBox "Found at row : " & find
End Sub

Two things to note: If WIPrng3 returns a multicolumn range, MATCH will fail with a 1004 error. MATCH only works on a single column or row. In the example above, I restricted WIPrng3 to the first column in the MATCH function to avoid this. You didn't have this in your code.

Another thing is that you're looking for the text string "545499", not the number 545499. If your range contains the number and not the string, you'll get an error. You can trap that error with an On Error statement and handle appropriately.

Finally, I don't see the advantage to defining WIPrng3 (but I can't see the whole of what you're doing). You could easily use

Sub Find2()

    Dim lRow As Long

    On Error Resume Next
        lRow = Application.WorksheetFunction.Match("545499", Sheets("WIP").UsedRange.Columns(1), 0)

    If lRow > 0 Then
        'add where the used range starts in case it's not row 1
        MsgBox "Found at row : " & lRow + Sheets("WIP").UsedRange.Cells(1).Row - 1
    Else
        MsgBox "Not found"
    End If

End Sub

You might end up looking through a larger range, but it won't appreciably affect performance.

I added the On Error in this example so you could see how it works. Don't put the On Error in there until you've tested it because it will mask all the other errors.

Charles Williams did some nice analysis on finding efficiency here http://fastexcel.wordpress.com/2011/10/26/match-vs-find-vs-variant-array-vba-performance-shootout/

Upvotes: 1

Related Questions