3 Ways to Create Class Instances in VBA

Before you can use a class, you need to create an instance of the class and assign it to an object variable. ... Or do you?

3 Ways to Create Class Instances in VBA

You can't directly call the functions and procedures of a class module the way you can a standard module.

Instead, you create an instance of the class module and then call the class's functions and procedures from that instance.  Consider the following class, clsMyClass:

Option Explicit

Dim mCreatedAt As Date

Private Sub Class_Initialize()
    mCreatedAt = VBA.Now()
End Sub

Public Property Get CreatedAt() As Date
    CreatedAt = mCreatedAt
End Property

Explicit Instantiation

With explicit instantiation, you create a new instance of the class using the Set statement:

Sub Explicit()
    Dim MyClass As clsMyClass
    
    Set MyClass = New clsMyClass
    Debug.Print MyClass.CreatedAt
End Sub

Implicit Instantiation

With implicit instantiation, you declare the object variable As New.  An instance of the object is automatically created the first time it gets used.  The Set statement is not required:

Sub Implicit()
    Dim MyClass As New clsMyClass
    
    Debug.Print MyClass.CreatedAt
End Sub

Predeclared Instantiation

With predeclared instantiation, you set the hidden class module attribute VB_PredeclaredID equal to True (see the HOW-TO section below).  VBA creates a default instance of the class with the same name as the class.  As with implicit instantiation, the default instance gets created the first time it is used.

With predeclared instantiation, you don't need to declare an object variable at all:

Sub Predeclared()
    Debug.Print clsMyClass.CreatedAt
End Sub

Notes, Caveats, and How-Tos

CAVEAT: A warning about implicit instantiation

There is one very important thing to know about implicit instantiation: the Is Nothing conditional will always return False for an object variable declared As New.  Even if the object has not been created, the simple act of checking it to see if it exists is enough for VBA to automatically create a new instance if needed.

Sub Implicit_IsNothingTest()
    Dim MyClass As New clsMyClass
    
    Debug.Print MyClass.CreatedAt
    Set MyClass = Nothing
    
    Debug.Print MyClass Is Nothing   'Returns False
End Sub

HOW-TO: Setting the PredeclaredID Attribute

The PredeclaredID attribute is completely hidden in the VBA IDE.  

I know of only two ways to set it.

The Manual Method: Export - Import Cycle

The traditional way this has been done in VBA is as follows:

  • Export the class module to a text file: File > Export File (Ctrl + E)
  • Open the exported text file in a text editor
  • Change the VB_PredeclaredID value from False to True
  • Save and close the text file
  • Delete the clsMyClass class module
  • Import the text file: File > Import File (Ctrl + M)

The Automatic Method: Rubberduck VBA

This method requires that you first install the Rubberduck VBA Add-in.

Once that is done, you can use the Rubberduck PredeclaredID attribute to set this value directly in your source code:

NOTE: VB_PredeclaredID = True Still Allows for Other Instances

Even if the VB_PredeclaredID attribute is set to True, you can still create other instances of the class.  For example:

Option Explicit

Private Declare PtrSafe Sub Sleep Lib "kernel32" _
   (ByVal dwMilliseconds As Long)

Sub Predeclared_MultiInstance()
    Debug.Print "A: "; clsMyClass.CreatedAt
    Sleep 2000
    
    Dim AnotherInstance As clsMyClass
    Set AnotherInstance = New clsMyClass
    Debug.Print "B: "; AnotherInstance.CreatedAt
    Sleep 3000
    
    Debug.Print "A: "; clsMyClass.CreatedAt
End Sub

Image by StockSnap from Pixabay

All original code samples by Mike Wolfe are licensed under CC BY 4.0