Reputation: 289
Is it possible to call a function within the "with" block? I kept getting error "invalid or unqualified reference". How may I reference the parent object in the "with" statement? Thank you!
Sub Test()
Set wb = Workbooks.Open(“C:\Book1.xls", True, True)
With wb.Worksheets("Sheet1")
lRow = LastRow()
msgbox(lRow)
End With
With wb.Worksheets("Sheet2")
lRow = LastRow()
msgbox(lRow)
End With
wb.Close False
End Sub
Function LastRow()
LastRow =.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End Function
Upvotes: 4
Views: 618
Reputation: 71177
A With
block can hold an object reference; that object reference is scoped to the procedure the With
block lives in, is born at With
and dead & buried at End With
: a With
block variable doesn't suddenly become global/transient. The compiler has a much more grammatical view of the code, what you're asking for would require context that can only exist at run-time.
However, the function can easily get that context from a parameter:
'...
With wb.Worksheets("Sheet1")
lRow = LastRow(.Cells)
MsgBox lRow
End With
'...
Avoid using parentheses in VB6/VBA when invoking a Function
(or Property Get
) without capturing its return value into a local variable, or when invoking a Sub
procedure. This isn't a question of coding style, grammatically superfluous parentheses change the semantics of the code and will inevitably end up causing problems (both at compile and run time).
I've added an explicit access modifier and an explicit return type, the source
parameter, and some validation:
Private Function LastRow(ByVal source As Range) As Long
Dim result As Range
Set result = source.Find(What:="*", _
After:=source.Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not result Is Nothing Then
LastRow = result.Row
Else
'source is empty
LastRow = -1
End If
End Function
Range.Find
returns Nothing
when it doesn't find what it's looking for. In this case given an empty source
, .Row
will be invoked against Nothing
, and that would throw run-time error 91 in your code: you can never assume that Range.Find
will return a valid object reference ;-)
Also After:=Range("A1")
wouldn't necessarily be on the same sheet as source.Range("A1")
, if this function is written in a standard code module (.bas) - unqualified, Range
would be an implicit reference to [_Global].Range
, a public property on a hidden application-scope module that returns the reference for ActiveSheet
. In this case it's not a big deal, but in other situations, with other functions in the Excel object model, qualifying a method with one sheet, and parameterizing with a range from another sheet, can mean a cryptic run-time error 1004 being thrown.
Upvotes: 6