That Whacky Conditional Compiler Argument

VBA | Development

VBA's conditional compilation constants look like Booleans but they are not, and the difference will bite you every time you use Not with Win64.

What Is Conditional Compilation?

Conditional compilation lets you control which lines of VBA actually get compiled and run, depending on the environment. Common use cases:

  • Code needs to run across multiple Office versions with API differences.
  • Support for both 32-bit and 64-bit Office.
  • Using early binding (Intellisense) but distributing with late binding.
  • Using a debug build with verbose logging and a lean production build without it.

Without it, you'd need separate projects or constant commenting and uncommenting. With it, all versions live in one codebase inside #If...#Else...#End If blocks. Note the # prefix — these are not the same as regular If statements.

Conditional Compilation Constants

A conditional compilation constant is a named value set to an integer. The most common values are 0 (False) and -1 (True). Constants can be defined in three ways:

  • Project Properties dialog — available across all modules in the project. Must be an integer from -32768 to 32767 (no thousands separators).
  • Command line at open — also project-wide.
  • #Const directive in a module — available only within that module. More flexible: can be an integer of any size, a real, a Boolean, or a string.

VBA also ships with four built-in constants: VBA7, Win32, Win64, and Mac that reflect the current environment automatically.

The Whacky Part: The Built-In Constants Are Not What They Appear to Be

In standard VBA and Excel formula logic, any value of 0 is False and any non-zero value is True. Negating those values is logically sound: Not 0 is True and Not any non-zero value is False. Straightforward. And the conditional compilation formula evaluator handles this logic as expected — it works correctly on any conditional compilation constant we define ourselves.

But, for some unknown reason, the built-in constants VBA7, Win32, Win64, and Mac are not quite what they appear to be. All written documentation states that they are either 0 (False) or -1 (True).

There are two problems with these constants. First, when True, they are 1, not -1. Second, when the conditional compilation formula evaluator negates them with the Not operator, the negation always evaluates to True for both 0 and 1 values. With a 64-bit installation, Win64 = True and Not Win64 = True.

This is not a problem if we stay away from the Not operator. This logic works as expected:

#If Win64 Then
#Else
#End If

But this does not:

#If Not Win64 Then
#End If

Nor does this:

#If Win64 = -1 Then
#End If

The Fix

Do not use the Not operator with any of the four built-in conditional compilation constants. If only logic for the negative result is needed, use one of these two techniques:

#If Win64 Then
#Else
    ' Code to compile in a non-Win64 environment
#End If

Or:

#If Win64 = 0 Then
    ' Code to compile in a non-Win64 environment
#End If

The Tests and Results

Below are the tests used to figure out what is going on and write this article.

#Const ConditionalCompilationConstantZero = 0
#Const ConditionalCompilationConstantPositive1 = 1
#Const ConditionalCompilationConstantNegative1 = -1

Const VBAZero As Integer = 0
Const VBAPositive1 As Integer = 1
Const VBANegative1 As Integer = -1

Public Sub Test()

    #If Not ConditionalCompilationConstantZero Then
        Debug.Print "Conditional Compilation: Not 0 = True"
    #Else
        Debug.Print "Conditional Compilation: Not 0 = False"
    #End If

    #If Not ConditionalCompilationConstantPositive1 Then
        Debug.Print "Conditional Compilation: Not 1 = True"
    #Else
        Debug.Print "Conditional Compilation: Not 1 = False"
    #End If

    #If Not ConditionalCompilationConstantNegative1 Then
        Debug.Print "Conditional Compilation: Not -1 = True"
    #Else
        Debug.Print "Conditional Compilation: Not -1 = False"
    #End If

    If Not VBAZero Then
        Debug.Print "VBA: Not 0 = True"
    Else
        Debug.Print "VBA: Not 0 = False"
    End If

    If Not VBAPositive1 Then
        Debug.Print "VBA: Not 1 = True"
    Else
        Debug.Print "VBA: Not 1 = False"
    End If

    If Not VBANegative1 Then
        Debug.Print "VBA: Not -1 = True"
    Else
        Debug.Print "VBA: Not -1 = False"
    End If

    #If Not Win64 Then
        Debug.Print "Conditional Compilation: Not Win64 = True (should be False)"
    #Else
        Debug.Print "Conditional Compilation: Not Win64 = False"
    #End If

    #If Not Win32 Then
        Debug.Print "Conditional Compilation: Not Win32 = True"
    #Else
        Debug.Print "Conditional Compilation: Not Win32 = False"
    #End If

    #If Win32 = 0 Then
        Debug.Print "Conditional Compilation: Win32 = 0"
    #End If
    #If Win32 = 1 Then
        Debug.Print "Conditional Compilation: Win32 = 1"
    #End If
    #If Win32 = -1 Then
        Debug.Print "Conditional Compilation: Win32 = -1"
    #End If

    #If Win64 = 0 Then
        Debug.Print "Conditional Compilation: Win64 = 0"
    #End If
    #If Win64 = 1 Then
        Debug.Print "Conditional Compilation: Win64 = 1"
    #End If
    #If Win64 = -1 Then
        Debug.Print "Conditional Compilation: Win64 = -1"
    #End If

End Sub

The results:

Conditional Compilation: Not 0 = True
Conditional Compilation: Not 1 = True
Conditional Compilation: Not -1 = False
VBA: Not 0 = True
VBA: Not 1 = True
VBA: Not -1 = False
Conditional Compilation: Not Win64 = True (should be False)
Conditional Compilation: Not Win32 = True
Conditional Compilation: Win32 = 1
Conditional Compilation: Win64 = 0
Conditional Compilation: Win64 = 1

Feedback

Question, correction, or comment? Let us know.