UtterAccess HomeUtterAccess Wiki

Welcome Guest ( Log In | Register )

Edit Discussion
> Compiler Directives    
(Redirected from Conditional Compilation)
Compiler Directives

Related Content:
    Wiki API Index (VBA7)
    API


Contents

Overview

There may be situations where we want to compile different forms of code, but not have multiple copies of essentially the same database and modules. Compiler Directives allow us to determine which code segment should be compiled.

Because Compiler Directives are compiled conditionally, we are afforded the opportunity to include code in our project that would be illegal in non-directive code.

This technique is particularly useful when working with varying versions of the host application (Access, Word, Excel, etc.), when using different versions of VBA (VBA or VBA7) and when working with different machine architectures (Win32 or Win64).

The basic syntax of a Conditional Compilation statement is:

CODE
#If ThisConstant Then
 'compile this code
#Else
 'compile this code
#End If


Compiler Constants

In order to implement conditional compiling, we must provide be able to use one or more constants for which to base the condition on. We can use some of the built in constants, or create our own.

Built In Compiler Constants

SeeAlso: Word Developer Help: Compiler Constants

VBA offers a handful of built in compiler contsants in later versions that can prove to be very helpful. These contsants provide boolean returns based on certain environment information. They are:

  • VBA6
  • VBA7
  • Win64
  • Win32
  • Win16
  • Mac

The VBA6 compiler constant can be used to differentiate VBA6 code from older versions of VBA. Mac compiler constant is generally inapplicable as Access does not exist for Macintosh but in Excel/Word/Outlook projects, can be used to run code specific to those running Macintoshes instead of PCs. VBA7 returns true if the project is compiled in the VBA7 environment (Office 2010 or newer), and Win64 returns true if the operating system in which the application is running is a 64 bit compatible version of Windows.

Operating System Constants

One thing to be careful of when testing the environment is to note that the built-in Win## constants indicate compatibility rather than the actual system architecture. Thus, even on a 64bit Windows OS, the Win32 constant will return True, because the architecture is compatible with 32 bit Windows. The following tables provide the constant values per environment, and the code snippet that follows suggests a good means to test while taking into consideration that the constants indication compatibility rather than the actual environment architecture.

Constant Win 64 Environments Win 32 Environments Win 16 Environments
Win64 True False False
Win32 True True False
Win16 False False True

As the table above indicates, the correct means of determining the system architecture is to check from highest to lowest:

CODE
#If Win64 Then
 ' Win 64 specific code
#ElseIf Win32
 ' Win 32 specific code
#Else
 ' Win 16 specific code
#End If

VBA Version Constants

The VBA6/VBA7 constants do not require special consideration when checking the values.

Example:

CODE
#If VBA7 Then
 Private Declare PtrSafe Function MyAPI Lib "MyLib" (ByVal MyPointer As LongPtr) As Long
#Else
 Private Declare Function MyAPI Lib "MyLib" (ByVal MyPointer As Long) As Long
#End If


User Defined Compiler Constants

In addition to the built in constants, we have the means to create our own compiler constants. This can be done through the VBA Project Properties, or through module declaration of the constant.

Note that we should be careful of ambiguous naming if we use both the property approach and the module declaration approach. We may wish to choose one or the other for each project.

Module Declaration Approach

The Module Declaration approach simply allows us to create a Const at module level for use with conditional compilation. This constant will be private to the module.

CODE
Option Compare Database
Option Explicit

#Const Version = "A2000"

Sub RunMe()
 #If Version = "A2000" Then
   'run v2000 specific code
 #Else
   'run non v2000 code
 #End If
End Sub


Project Property Approach

The Project Property approach allows us to define compilation constants by setting them in the VBA project's properties. Do to so, follow these steps:

  1. Open the VBA Editor
  2. On the Menu, select Tools -> Properties
  3. In the dialog, on the General tab, place your constants and values in the Condition Compilation Arguments textbox.
    1. To use multiple constants, delimit them with a colon

Example: MyAppVersion = 1:MyAppMode = 2


Usage Examples

The following usage examples give an idea of scenarios when and how compiler directives may be applied.

Application Specific

Implementing application specific compiler directives gives us a large amount of flexibility in our coding. We can customize our constants to cover any number of possibilities.

CODE
Option Compare Database
Option Explicit

#Const Version = "A2000"

Sub RunMe()
 #If Version = "A2000" Then
   'run v2000 specific code
 #Else
   'run non v2000 code
 #End If
End Sub


API Declarations

API Declarations based on VBA or VBA7 can vary: compiler directives allow us to compile one declaration or the other as required:

CODE
Option Compare Database
Option Explicit

#If VBA7 Then
 Private Declare PtrSafe Function LoadLibrary Lib "Kernel32" Alias "LoadLibraryA" _
   (ByVal lpFileName As String) As LongPtr
 )
#Else
 Private Declare Function LoadLibrary Lib "Kernel32" Alias "LoadLibraryA" _
   (ByVal lpFileName As String) As Long
#End If

Public Sub RunMe(libraryFile As String)
 LoadLibrary libraryFile
End Sub


Procedure Signatures

Conditional Compilation can also be used to form constructs that may not be ordinarily legal but can be useful. Suppose we need a procedure to be always available but have a different signature:

CODE
#If EarlyBind Then
Public Sub EmailMyMail (MyMail As Outlook.MailItem)
#Else
Public Sub EmailMyMail (MyMail As Object)

Const olHTML As Long = 5
#End If

With MyMail
  'Fill up the mail with details
  .SaveAs "C:\Temp", olHTML
  .Send
End With

End Sub

Conditional compilation ensures that only one block at any time is in effect and thus compiler only reads the "active' block and treats the other blocks like it treats a comment -- it is completely ignored, so though we have two Sub statement but only one End Sub statement, the compiler see it as a single procedure. When we change the flag, the code still compiles but the procedure now has a different signature (e.g. MyMail is now typed as an object rather than specific Outlook.MailItem. We also included a constant that wasn't ordinarily needed when we reference the Outlook reference.

#If is not the same as If

While the #If construct is similar to the If construct, there is at least one significant difference: the #If logic has no equivalent to Not.

CODE
Option Explicit
Public Sub TestDirective()
'use  undeclared variables
'production = 1 : demo = 0

'this will compile
   #If production Then
       #If demo Then
           X = Y
       #End If
   #Else
       X = Y
   #End If

'this will produce compile error Variable not defined
   #If Not demo Then
       'this statement will compile
       X = Y
   #End If
End Sub

A simple test can verify whether you are using the directive correctly. Try to set a break point in statements within the #If construct. If you can set a break point, the compiler will attempt to compile the statement.

Edit Discussion
Thank you for your support!
This page has been accessed 11,580 times.  This page was last modified 10:52, 22 October 2014 by Glenn Lloyd. Contributions by Jack Leach, BananaRepublic and Alan Greenwood  Disclaimers