Early Binding und Late Binding sind zwei Konzepte für das gleiche Ziel: Die Eigenschaften und Methoden von Elementen einer Bibliothek unter VBA verfügbar zu machen. Beide unterscheiden sich in verschiedenen Punkten und haben Vor- und Nachteile. Diese ein wenig auszugleichen ist das Ziel dieses Beitrags: Wir wollen zeigen, wie man die Vorteile von Early Binding, wie z.B. den Einsatz von IntelliSense, nutzen und gleichzeitig schnell zu Late Binding übergehen kann, um die Vorteile von Late Binding zu nutzen. Dazu schauen wir uns zunächst noch einmal die wesentlichen Unterschiede an und kommen dann zu unserer Idee, beide Versionen parallel zu nutzen – mit einer Technik namens „bedingte Kompilierung“.
Early Binding vs. Late Binding
Beide Methoden dienen dazu, die Klassen, Eigenschaften, Methoden und gegebenenfalls auch Ereignisse einer COM-Bibliothek in einem VBA-Projekt verfügbar zu machen. Solche COM-Bibliotheken können fertige Bibliotheken sein, aber wir können diese auch selbst erstellen – beispielsweise mit Visual Studio .NET oder twinBASIC.
Beispiele für fertige Bibliotheken sind etwa die für den Zugriff auf die verschiedenen Office-Anwendungen. Wenn wir auf Outlook, Word oder Excel zugreifen wollen, um diese Anwendungen fernzusteuern oder auf die enthaltenen Daten zuzugreifen, benötigen wir die entsprechenden Klassen, die wiederum in Bibliotheken enthalten sind.
Um auf diese Elemente zuzugreifen, referenzieren wir in der Regel eine Klasse mit einer Objektvariablen.
Beim Early Binding fügen wir unserem VBA-Projekt einen festen Verweis auf die Bibliothek hinzu und können dann per VBA über IntelliSense auf die enthaltenen Klassen, Eigenschaften, Methoden und Ereignisse zugreifen.
Beim Late Binding fügen wir keinen festen Verweis hinzu und können nicht über IntelliSense auf die Elemente zugreifen, da das VBA-Projekt die zu verwendenden Klassen nicht kennt.
Early Binding verwenden
Wenn wir Early Binding nutzen wollen, benötigen wir als Erstes einen Verweis auf die jeweilige Bibliothek. Um diesen hinzuzufügen, wechseln wir von Access aus zum VBA-Editor (zum Beispiel mit der Tastenkombination Alt + F11). Hier können wir nun beispielsweise die Objektbibliothek für den Zugriff auf Microsoft Outlook über den Eintrag Microsoft Outlook 16.0 Object Library hinzufügen (siehe Bild 1).
Bild 1: Verweis auf Outlook hinzufügen
Fügen wir nun ein neues, leeres VBA-Modul hinzu, können wir wie in Bild 2 eine Variable des Typs Outlook.Application deklarieren, diese mit einer neuen Instanz von Outlook.Application füllen und dann auf die Eigenschaften und Methoden dieser Klasse zugreifen.
Bild 2: Outlook-Klassen referenzieren und verwenden
Late Binding verwenden
Wenn wir Late Binding nutzen, können wir für die Variable objOutlook nicht explizit den Typ festlegen, sondern verwenden den Datentyp Object.
Außerdem können wir nicht das New-Schlüsselwort verwenden, sondern müssen mit CreateObject arbeiten. Die notwendigen Zeilen sehen wie folgt aus:
Public Sub OutlookReferenzierenLateBinding() Dim objOutlook As Object Set objOutlook = CreateObject("Outlook.Application") Debug.Print objOutlook.Name End Sub
Damit können wir beinahe alles erledigen, was wir auch mit Early Binding tun können. Die Unterschiede schauen wir uns nun im Detail an.
Vor- und Nachteile von Early Binding
Beim Early Binding haben wir den Vorteil, dass wir IntelliSense nutzen können.
Wenn wir kein IntelliSense nutzen können, müssen wir entweder alle relevanten Elemente, Eigenschaften und Methoden auswendig kennen oder die Dokumentation verwenden.
Mit Early Binding bekommen wir alle Elemente zu sehen, wenn wir nach dem Variablennamen den Punkt eingeben.
Ein weiterer Vorteil beim Early Binding ist die Performance. Dadurch, dass wir bereits definiert haben, mit welchen Objekttypen wir arbeiten, sparen wir Zeit bei der Ausführung.
Der Code ist unter Umständen besser lesbar, weil wir in der Deklarationszeile angeben, welchen Typ die verschiedenen Objektvariablen aufweisen.
Schließlich können wir für verschiedene Parameter mit vorgegebenen Werten aussagekräftige Konstanten statt der tatsächlichen Zahlenwerte verwenden. Ein Beispiel sehen Sie in Bild 3. Hier geben wir statt des Zahlenwertes 0 für die zu erstellende E-Mail die Konstante olMailItem an.
Bild 3: Verwenden von Konstanten
Vor- und Nachteile von Late Binding
Bei Verwendung von Late Binding gestalten sich die Vor- und Nachteile wie folgt.
Der wichtigste Vorteil beim Late Binding ist, dass wir keinen Verweis benötigen. Dadurch können auch keine Fehler beim Ausführen des Codes durch fehlerhafte Verweise auftreten.
Ein fehlerhafter Verweis liegt vor, wenn wir beispielsweise die Bibliothek Microsoft Office 16.0 Object Library in unserem VBA-Projekt hinzugefügt haben, aber die Anwendung auf einem Rechner ausführen, auf dem sich eine andere Version dieser Bibliothek befindet.
Oder wir nutzen einen Verweis auf eine selbst erstellte DLL, die wir bei der Entwicklung verwenden, die aber auf dem System des Kunden nicht vorhanden ist. Dann treten schnell Fehler wegen des fehlerhaften Verweises auf – interessanterweise an Stellen, die wir gar nicht damit in Verbindung bringen, zum Beispiel beim Aufruf von einfachen VBA-Funktionen wie Left oder Mid.
Da unter Verwendung von Late Binding kein solcher Verweis vorhanden ist, erhalten wir auch nicht automatisch die beschriebenen Fehlermeldungen. Und im Gegensatz zu Early Binding können wir bei Late Binding auch recht einfach prüfen, ob die jeweilige Bibliothek vorhanden ist, bevor es Fehlermeldungen hagelt. Dazu später mehr.
Ein Nachteil von Late Binding ist, dass wir Objektvariablen nur mit dem Typ Object und nicht mit dem spezifischen Typ deklarieren können. Somit können wir auch kein IntelliSense nutzen.
Ein weiterer Nachteil ist, dass wir die von den Bibliotheken bereitgestellten Konstanten nicht nutzen können, sondern die dahinter stehenden Zahlenwerte verwenden müssen.
Beide Methoden parallel verwenden
Wie kommen wir nun an das Beste aus beiden Welten?
Genau genommen meinen wir damit, dass wir mit IntelliSense programmieren und das Projekt aber ohne feste Verweise weitergeben.
Hierbei müssen wir natürlich abwägen, welche Bibliotheken wir dieser Spezialbehandlung unterziehen wollen.
Solche Bibliotheken, die mit sehr hoher Wahrscheinlichkeit auf dem Rechner des Benutzers enthalten sind, können wir durchaus per Early Binding nutzen.
Interessanter ist der Einsatz von Late Binding in solchen Fällen, in denen das Vorhandensein einer anderen Version als der bei der Entwicklung verwendeten Version wahrscheinlich ist oder in denen eine Bibliothek gar nicht verfügbar ist.
Hier könnten wir zunächst mit Early Binding entwickeln und dann vor der Weitergabe der Anwendung auf Late Binding umstellen. Dazu sind die folgenden Schritte nötig:
- Ersetzen der expliziten Datentypen durch den Datentyp Object
- Ersetzen des New-Schlüsselwortes durch die Create-Object-Methode
- Ersetzen der Konstanten durch die dahinter stehenden Zahlenwerte oder explizite Deklaration der Konstanten
Beim obigen Beispiel könnten wir unter Early Binding diesen Code verwenden:
Public Sub OutlookReferenzierenEarlyBinding() Dim objOutlook As Outlook.Application Dim objMailItem As Outlook.MailItem Set objOutlook = New Outlook.Application Set objMailItem = objOutlook.CreateItem(olMailItem) ... End Sub
Um zu testen, wo Anpassungen notwendig sind, damit dieser Code ohne den Verweis auf die Outlook-Bibliothek läuft, brauchen wir einfach nur den Verweis zu entfernen und den Code zu starten.
Wir werden schon beim Debuggen auf den ersten Fehler stoßen (siehe Bild 4).
Bild 4: Fehler beim Kompilieren
Also ersetzen wir zunächst die Deklarationen durch solche mit dem Datentyp Object – all dies in einer neuen Prozedur namens OutlookReferenzierenLateBinding:
Dim objOutlook As Object Dim objMailItem As Object
Den gleichen Fehler erhalten wir für die Zuweisung von Outlook.Application zur Variablen objOutlook. Hier ersetzen wir das New-Schlüsselwort durch CreateObject. Dabei können wir als Parameter den Namen der zu erstellenden Klasse in Anführungszeichen angeben:
Set objOutlook = _
CreateObject("Outlook.Application")
Beim nächsten Versuch des Kompilierens erhalten wir noch einen Fehler für eine nicht definierte Variable (siehe Bild 5). Genau genommen handelt es sich um die Konstante olMailItem, die üblicherweise in der Bibliothek Microsoft Outlook 16.0 Object Library definiert ist.
Bild 5: Nicht deklarierte Variable
Diese finden wir im Objektkatalog, wenn die Bibliothek per Verweis referenziert wird (siehe Bild 6).
Bild 6: Die Konstanten werden in der Objektbibliothek definiert.
Konstanten definieren oder durch Zahlenwerte ersetzen
Hier haben wir zwei Möglichkeiten:
- Wir geben statt der Konstanten, wie hier olMailItem, einfach den entsprechenden Zahlenwert an, in diesem Fall 0. Den Zahlenwert können wir auf zwei Arten ermitteln: Entweder durch Ablesen im Objektkatalog oder durch die Ausgabe des Wertes der Konstanten im Direktbereich mit Debug.Print olMailItem (siehe Bild 7). Hier müssen wir darauf achten, dass die Bibliothek zu diesem Zeitpunkt referenziert wird. Anderenfalls würde diese Anweisung eine leere Zeichenkette ausgeben.
- Wir definieren die Konstante explizit. Das können wir im gleichen Modul erledigen, in dem wir die Prozeduren unterbringen, die auf diese Konstante zugreifen oder auch in einem eigenen Klassenmodul nur für Konstantendeklarationen. Die entsprechende Zeile finden wir in Bild 8.
Bild 7: Ausgabe des Zahlenwertes einer Konstanten
Bild 8: Definition einer Konstanten
Damit können wir die Prozedur nun ohne Fehler kompilieren und auch ausführen.
Auf die gleiche Weise wie mit der Konstanten olMailItem würden wir auch mit weiteren Konstanten umgehen.
Beides in einem Modul
Nehmen wir nun an, Sie möchten einerseits mit Early Binding arbeiten, um IntelliSense nutzen zu können, und andererseits auch schnell eine Version der Anwendung veröffentlichen können, die Late Binding nutzt und keinen Verweis mehr auf die fragliche Bibliothek verwendet.
Dann können wir die sogenannte „bedingte Kompilierung“ nutzen und einfach beide Varianten parallel bedienen.
Bedingte Kompilierung bedeutet, dass wir spezielle If…Then…Else-Bedingungen verwenden, die wir mit einem führenden Raute-Zeichen versehen. Für die Bedingung verwenden wir eine Konstante namens EarlyBinding, die wir entweder auf den Wert True oder False einstellen. Wichtig für den Einsatz der Konstanten bei der bedingten Kompilierung ist, dass der Anweisung das Raute-Zeichen vorangestellt wird (#):
#Const EarlyBinding = False
Danach folgt eine If…Then…Else-Bedingung, bei der alle drei Elemente wiederum ein führendes Raute-Zeichen aufweisen:
#If EarlyBinding = True Then
...
#Else
...
#End If
Wie funktioniert das nun? Wir legen mit der Konstanten EarlyBinding fest, ob wir mit Early Binding arbeiten, also mit einem Verweis auf die betroffene Bibliothek (#Const EarlyBinding = True), oder mit Late Binding (#Const EarlyBinding = False).
In der If…Then…Else-Bedingung prüfen wir diesen Wert. Und nun kommt der Clou: Die Anweisungen, die sich in dem Zweig der Bedingung befinden, die nicht erfüllt ist, werden nicht nur nicht ausgeführt – sie werden noch nicht einmal kompiliert (siehe Bild 9).
Bild 9: Definition einer der Bedingung der bedingten Kompilierung
Dadurch werden beispielsweise bei #Const EarlyBinding = False die Anweisungen, die sich auf die Klasse Outlook.Application beziehen, nicht kompiliert und infolgedessen kann hier auch kein Kompilierfehler entstehen. Wir können also nun beide Versionen gleichzeitig weiterentwickeln. Dabei werden wir vermutlich zunächst die Version bearbeiten, bei der wir IntelliSense nutzen können und die Änderungen dann auf die Version für Late Binding übertragen.
Wenn wir uns den Code genau ansehen, sind es aber ohnehin nur wenige Anweisungen, die Unterschiede bezüglich Early Binding und Late Binding aufweisen – nämlich die Deklarationen und das Erstellen der jeweiligen Objekte.
Dazu müssen wir allerdings zwei Dinge erledigen:
- Wir müssen den Verweis jeweils wieder hinzufügen.
- Und wir müssen #Const EarlyBinding = True setzen.
Wenn wir nur den Verweis hinzufügen, aber durch Setzen von #Const EarlyBinding = False die Anweisungen von der Kompilierung ausnehmen, in denen die Variablen wie objOutlook mit den expliziten Klassen deklariert werden, können wir auch kein IntelliSense nutzen – VBA geht dann davon aus, dass die Variablen als Object deklariert sind.
Gültigkeit der Konstanten für die bedingte Kompilierung
Die hier verwendete Konstante EarlyBinding ist nur in dem Modul gültig, in dem sie deklariert wurde. Wenn wir also mit der gleichen Konstanten die bedingte Kompilierung in mehr als einem Modul steuern wollen, müssen wir dazu in jedem betroffenen Modul jeweils eine eigene Konstante definieren. Das lässt die Vorgehensweise etwas aufwendiger aussehen als geplant. Es wäre praktischer, wenn wir nur an einer einzigen Stelle festlegen könnten, ob wir Early Binding oder Late Binding nutzen wollen. Dies an mehreren Stellen anpassen zu müssen scheint uns doch fehleranfällig zu sein.
Globale bedingte Konstante definieren
Doch es gibt auch hier einen Workaround. Dazu öffnen wir mit dem Menübefehl Extras|Eigenschaften von [Datenbankname]… den Dialog [Datenbankname] – Projekteigenschaften. Hier finden wir unten die Eigenschaft Argumente für bedingte Kompilierung. Für diese können wir die Bedingung eintragen, die für die bedingte Kompilierung dienen soll (siehe Bild 10).
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo