VBA Scope And Lifetime

Scope, visibility, accessibility, and lifetime are related concepts that describe when and where a variable can be used. Scope and lifetime are determined by where a variable is declared and the modifier used to declare it.

Scope And Visibility

Scope and visibility refer to the area in a program where a name is bound to a variable. A name is bound to a variable when using that name refers to that particular variable. It is possible for the same name to exist in another scope but refer to a different variable. There are four scopes in VBA: Public, Project, Module, and Procedure.

Scope Description
Public Entity is available everywhere (in any project, in any module, and in any procedure). Variables declared outside a procedure with the Public modifier are in the Public scope.
Project Entity is available in any module within the project. When Option Private Module is declared, Public members are in Project scope.
Module Entity is only available within the module in which it is declared. Variables declared outside a procedure with the Dim or Private modifier are in the Module scope.
Procedure Entity is only available within the procedure in which it is declared. Variables declared inside a procedure and a procedure's parameters are in the Procedure scope.

Controlling Scope

A variable's scope is determined by where it is declared and what access modifier is used to declare it. Dim and Const can be used inside and outside procedures. Public and Private can only be used outside procedures. Variables can be declared inside procedures using Dim or Static. Static has the same scope as Dim inside a procedure but Static changes a variable's lifetime.

Note: The "Global" modifier has the same effect as the "Public" modifier but is only available in standard modules. The Public modifier should be used instead.

Modifier Location Scope Visibility Lifetime
Dim Inside procedure Procedure Inside procedure During procedure execution
Static Inside procedure Procedure Inside procedure While application is running
Dim Outside procedure Module Inside module While application is running
Const Inside procedure Procedure Inside procedure During procedure execution
Const Outside procedure Module Inside module While application is running
Private Outside procedure Module Inside module While application is running
Public Outside procedure Public Everywhere While application is running
Private Const Outside procedure Module Inside module While application is running
Public Const Outside procedure Public Everywhere While application is running
Option Explicit

Public a  As Long 'Public scope
Private b As Long 'Module scope
Dim c     As Long 'Module scope

Public Const d  As Long = 3 'Public scope
Private Const e As Long = 2 'Module scope
Const f         As Long = 1 'Module scope

Public Sub Example()

    Dim g    As Long     'Procedure scope
    Static h As Long     'Procedure scope
    Const i  As Long = 0 'Procedure scope

End Sub

Declaring Option Private Module makes all Public scope members within the module Project scope.

Option Explicit
Option Private Module

'Message and Example are only available inside the project containing this module.

Public Message As String

Public Sub Example()
    Debug.Print Message
End Sub

Name Shadowing

Name Shadowing is when a variable in a lower scope is given the same name as a variable in a higher scope. The name of the variable in the higher scope is shadowed by the same variable name in the lower scope and is no longer visible to the lower scope. The name is bound to the variable in the most immediate scope and is no longer bound within that scope to the variable in the higher scope. The shadowed variable in the higher scope can still be accessed however by using the variable's fully qualified name. To fully qualify a variable name include the name of the module where the variable is declared followed by the dot (".") operator followed by the variable name.

'Standard Module: Module1

Option Explicit

Public i As Long

Public Sub Example1() 
    
    'Public i is shadowed by local i
    Dim i As Long 
  
    'Public i not affected
    i = 1 

End Sub

Public Sub Example2(i As Long) 
    
    'Public i is shadowed by parameter i

    'Public i not affected
    i = i + 1 

End Sub

Public Sub Example3()

    'Public i is shadowed by local i
    Dim i As Long 
    
    'Public i not affected
    i = 1 
    
    'Public i is affected using fully qualified name
    Module1.i = 2 

End Sub

Variable Lifetime

The Lifetime of a variable is the duration of time where a variable exists in memory. The lifetime of a variable with Procedure scope is the duration the procedure is executing. The variable is loaded in memory when the procedure is called and is unloaded from memory when the procedure finishes. The lifetime of a variable with Module, Public, or Project scope is the duration the application is running. Variables with Module, Public, or Project scope are loaded in memory when the application starts and are unloaded from memory when the application is terminated.

Static

The lifetime of variables declared Static is the duration the application is running. Variables declared Static keep their values between procedure calls. Procedures declared Static keep the values of all their local variables between procedure calls. Static does not change the scope of local procedure variables, which is still procedure scope. Static only changes the lifetime of variables to extend beyond the duration the procedure is executing.

Option Explicit

Public Sub TestStaticVariable()

    'i is loaded in memory when procedure called and unloaded when procedure finishes
    Dim i As Long
    i = i + 1
    Debug.Print i

    'j remains loaded in memory while the application is running
    Static j As Long
    j = j + 1
    Debug.Print j

End Sub

Public Static TestStaticProcedure()

    'i remains loaded in memory while the application is running
    Dim i As Long
    i = i + 1
    Debug.Print i

End Sub