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 werden die Officeversionen von 2010 bis einschließlich 2016 als 32-Bit installiert, aber unter einem 64-Bit Windows kann man alternativ auch ein 64-Bit Setup auswählen. Office 2019 versucht sich dagegen standardmäßig als 64-Bit zu installieren, wenn Windows als 64-Bit installiert ist, aber man kann alternativ auch das 32-Bit Setup auswählen. In Zukunft wird ein 64-Bit Office sicher sinnvoll werden, mindestens bis Version 2016 überwiegen doch eher die Nachteile - aber das soll hier nicht das Thema sein. Wichtig ist nur: Um konvertierbaren und zukunftsfähigen Code zu schreiben, muss man bei der API-Programmierung 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

Der Unterschied besteht also vor allem in PtrSafe. Aus den bisherigen Erläuterungen ergibt sich: In Office bis einschließlich 2007 darf PtrSafe nicht enthalten sein, in neueren 32-Bit Versionen darf es enthalten sein, und in 64-Bit Versionen muss es enthalten sein. Die #If-Verzweigung stellt sicher, dass der Code unter allen Versionen funktioniert.