Versionsunterschiede

Bei der API-Programmierung muss man seit Office 2010 zwischen 32- und 64-Bit Versionen unterscheiden (16-Bit Versionen sind heute ausgestorben und müssen nicht mehr berücksichtigt werden). Standardmäßig wird Office 2010 und höher als 32-Bit installiert, aber unter einem 64-Bit Windows kann man alternativ auch ein 64-Bit Setup auswählen. In Zukunft wird ein 64-Bit Office sicher sinnvoll werden, bisher überwiegen allerdings die Nachteile - aber das soll hier nicht das Thema sein. Um konvertierbaren und zukunftsfähigen Code zu schreiben ist jedenfalls bei der API-Programmierung zu berücksichtigen, dass bei einem 64-Bit Office die DLLs manche Parameter mit 64-Bit Werten erwarten, und die Declare-Anweisung zwingend PtrSafe enthalten muss.

Zur Unterscheidung der verschiedenen Versionen gibt es in VBA sogenannte Compilerkonstanten, die Boolean-Werte liefern. Mit VBA6 bzw. VBA7 kann man unterscheiden, ob es sich um ein neueres Office handelt, das Lösungen für den Umgang mit 64-Bit APIs mitbringt, und mit Win32 bzw. Win64 kann man feststellen, ob Office (und nicht etwa Windows!) in der 32- oder der 64-Bit Version installiert wurde. Diese Konstanten sind nicht wie normale Konstanten aufrufbar, sondern nur im Kontext mit einer speziellen Variante von If..Then, nämlich mit vorangestelltem „#“. Ohne „#“ würde das Programm glauben, dass die Konstante eine normale Variable wäre und den Teil nach dem #Else anspringen.

Bei Verzweigungen mit Compilerkonstanten wird immer nur der Code einer der Verzweigungen compiliert. Der Code in den Teilen, der nicht angesprungen wird, kann fehlerhaft sein, ohne dass das die Ausführung stört.

Sub Version()

#If VBA7 Then
    #If Win64 Then
        Debug.Print "Neueres 64-Bit Office, 64-Bit Windows"
    #Else
        Debug.Print "Neueres 32-Bit Office, 32- oder 64-Bit Windows"
    #End If
#Else
    Debug.Print "Älteres 32-Bit Office"
    Diese Zeile verursacht einen Fehler. Oder auch nicht.
#End If

End Sub

Win32 gibt auch auf 64-Bit Systemen True zurück, damit auch uralter Code, der dereinst zur Unterscheidung zwischen 16- und 32-Bit notwendig war, noch heute irgendwie funktioniert. Daher ist es heute empfehlenswert, nicht Win32 für die Verzweigung abzufragen, sondern statt dessen, wie im obigen Beispiel, immer die höhere Version als Bedingung zu nutzen.

Im Gegensatz zum „normalen“ If kann #If auch im Deklarationsbereich eines Moduls verwendet werden und somit Declare-Anweisungen enthalten. Unser Eingangsbeispiel zum Ermitteln des Systemverzeichnisses muss also lauten:

#If VBA7 Then
    Private Declare PtrSafe Function GetSystemDirectoryA Lib "kernel32" _
       (ByVal lpBuffer As String, ByVal nSize As Long) As Long
#Else
    Private Declare Function GetSystemDirectoryA Lib "kernel32" _
       (ByVal lpBuffer As String, ByVal nSize As Long) As Long
#End If


Public Function
GetSystemDirectory() As String Dim lngLen As Long, lpBuffer As String, nSize As Long nSize = 255 lpBuffer = String(nSize, vbNullChar) lngLen = GetSystemDirectoryA(lpBuffer, nSize) GetSystemDirectory = Left(lpBuffer, lngLen) End Function