VBA: Run time error ’91’?

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.

Leave a Comment