All I\'m trying to do here is save a reference to the currently active window, but it doesn\'t seem to be working. It gives me a run time error on the last line.
In VB object variables require the Set
keyword to be assigned. Object properties that are objects also need to be Set
. Runtime error 91 "object variable not set" is raised when the assignment doesn't use that keyword.
This is inherited from legacy Let
keyword to assign values, and Set
keyword to assign references; the Let
eventually was deprecated (although still needed for defining properties) and the Set
remained, leaving the VB6/VBA value assignment syntax like [Let] variable = value
, where "Let" is optional.
In the declaration and assignment:
Dim SourceWindow As Window, QACheckWindow As Window
'this is like saying "Let SourceWindow = ActiveWindow":
SourceWindow = ActiveWindow
SourceWindow
is an object, assigned as if it were a value - this causes VBA to attempt let-coercion through a default member call. If the object wasn't initialized, the member call fails with error 91. If the object was initialized but doesn't have a default member, error 438 is raised.
So in this case error 91 is being raised because of an implicit member call; the .net equivalent would be a NullReferenceException
:
Dim SourceWindow As Window, Dim WindowTitle As String
'"SourceWindow" reference isn't set, the object can't be accessed yet:
WindowTitle = SourceWindow.Caption
I'm going to go a bit overboard here, but the legacy Let
statement should not be confused with the Let
clause (in VB.net) which, in the LINQ query syntax (in VB.net), computes a value and assigns it to a new, query-scoped variable (example taken from MSDN):
From p In products
Let Discount = p.UnitPrice*0.1 '"Discount" is only available within the query!
Where Discount >= 50
Select p.ProductName, p.UnitPrice, Discount
VB.net assigns both values and references, without the need to specify a Let
or a Set
, because in .net this distinction is a much thinner line, given how everything ultimately derives from System.Object
... including System.ValueType
. That's why the Set keyword was also deprecated in VB.net, and also why the VB.net syntax for defining properties has dropped the Let
in favor of Set
- because parameterless default members are illegal in VB.NET, so this ambiguous let-coercion doesn't happen.