UtterAccess HomeUtterAccess Wiki

Welcome Guest ( Log In | Register )

Edit Discussion
> Compiler Directives    
Revision as of 03:15, 25 February 2012; view current revision
←Older revision | Newer revision→
Compiler Directives

Related Content:
    API
    Wiki API Index (VBA7)


Contents

Overview

Occasionally you may want to compile different forms of your code but not have multiple copies of essentially the same database and modules. Compiler directives allow you to determine which code segment should be compiled.

For example, you may be developing code in one version of Access that has certain features that the previous version lacks. In A2002 (XP), the DoCmd.OpenReport method, for instance, has windowmode and openargs arguments. A2000, and most likely all earler versions, do not have these arguments. To make the code compatible with 2000 you have to use a less straightforward approach than is possible in XP. A compiler directive will let you include both versions and select which will be compiled.

First you must declare a compiler constant. You can declare a numeric global compiler constant in your projects properties. If you need several compiler constants separate them with a colon. To add to the project properties, take the following steps: 1. Open the VBA Editor 2. On the Menu, select Tools -> Properties 3. In the dialog, on General tab, put the constants in the textbox labelled "Conditional Compilation Arguments" 4. If you want to store multiple constants, separate them with colons. Example:

CODE
MyAppVersion = 1:MyAppMode = 2

Alternatively, you can declare local compiler constant strings. In this case the compiler constant is restricted to the module in which it is declared.

[/code]#Const Version = "A2000"[/code]

For any given compiler constant use either the property approach or the module declaration approach. Don't mix them. Note also that the global constant is numeric, the local is string.

Now, to put the constant to work you include the compiler conditional structure wherever you need the code to be version specific:

CODE
#if Version = "A2000" Then
'access 2000 code here
#else
' alternative version here
#end if

Depending on the current value of the compiler constant, either the A2000 specific code or the alternaive code will be compiled. If you use the global approach the if statement would refer to the numeric value you specified in the project properties.


Determining VBA7 or Win64

Using Conditional Compiling can be helpful for API programming when we may need to distinguish between VB7 declarations. Two built in contsants, VBA7 and Win64 allow us to determine the current architecture and compile accordingly:

CODE
Public Function TestMe()

#If VBA7 Then
 MsgBox "VBA7"
#Else
 MsgBox "VBA"
#End If

End Function


Placement in Code

Conditional Compilation can be performed inside a procedure or at module level. This is useful for both procedural processing as well as external function declarations.

Example:

CODE
Option Compare Database
Option Explicit

#If VBA7 Then
 Private Declare PtrSafe Function MyAPI Lib "SomeLib" (ByVal SomePointer As LongPtr) As Long
#Else
 Private Declare Function MyAPI Lib "SomeLib" (ByVal SomePointer As Long) As Long
#End If

Public Function TestMe()
 Dim x As Long, y As Long
 y = 123456
 x = MyAPICall(y)

 #If Win64 Then
   'do win64 specific stuff
 #Else
   'do win32 specific stuff
 #End If

End Function

The conditional compilation can be also used to form constructs that may not be ordinarily legal but can be useful. For example, suppose we need a procedure to be always available but have different signature. We can structure thus:

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.


This page was originally ported from the UtterAccess Forums. It is based heavily or in part on a post by Glenn Lloyd.
Conditional Compilation - Compiler Directives

Edit Discussion
Thank you for your support!
Disclaimers