Home > Artikel > Ausgabe 7/2015 > Arbeiten mit externen Bibliotheken

Arbeiten mit externen Bibliotheken

  PDF ansehen

  Download PDF und Beispieldatenbank

Wahrscheinlich sind Sie schon einmal auf Begriffe gestoßen, wie Verweise, VBA-Bibliotheken oder Type Libraries. Alle bezeichnen dabei dieselbe Sache. Klären wir auf, was es damit auf sich hat, und wie Sie als VBA-Programmierer mit VBA-Bibliotheken umgehen.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1507_Libraries.zip.

Das VBA-Projekt

Sobald Sie in eine Datenbank neu anlegen, erzeugt Access automatisch auch ein VBA-Projekt in ihr, das zunächst den gleichen Namen trägt, wie die Datei. Öffnen Sie den VBA-Editor, so steht dieser Name ganz oben im Projekt-Explorer. Dieser Name bezeichnet bereits die grundlegende Bibliothek des VBA-Projekts dieser Datenbank. Der Inhalt dieser Bibliothek wäre die Sammlung von Modulen und Klassen mit ihren Methoden, die Sie gegebenenfalls entwickeln.

Verweise

VBA funktioniert grundsätzlich nicht ohne solche Bibliotheken. Um bestimmte Funktionen und Anweisungen ausführen zu können, benötigt es eine Referenz auf diese. Von Haus aus weiß es nichts über Namen, wie Left, Right, Abs, CurrentDb, und so weiter. All diese Namen müssen aus Bibliotheken kommen, die erstens die Bezeichnungen kennen, und zweitens den Ort, wo sich die Funktionen befinden, auf die sie sich beziehen.

Auf den ersten Blick ist dieser Zusammenhang nicht unbedingt gleich ersichtlich. Denn beim Anlegen des VBA-Projekts einer Datenbank legt Access sogleich Referenzen auf zwei Bibliotheken fest, die Teil der Office-Installation sind: VBA und Access. Das sind die beiden grundlegenden Bibliotheken, mit denen unter VBA einer Datenbank gearbeitet wird.

Left und Right etwa stammen aus der Bibliothek VBA, während CurrentDb Teil der Access-Library ist. Type Library, kurz Library, und Bibliothek sind synonyme Bezeichnungen. Während diese Begriffe auch unter anderen Programmiersprachen gängig sind, spricht man unter VBA eher von Verweisen, oder englisch References. Korrekt wäre eigentlich die ausführliche Bezeichnung Verweis auf eine Bibliothek.

Welche Bibliotheken in das VBA-Projekt der aktuellen Datenbank integriert sind – ohne Datenbank auch kein VBA-Projekt und somit keine Bibliotheken –, erfahren Sie über den Verweise-Dialog des VBA-Editors. Öffnen Sie ihn über sein Menü und die Abfolge Extras|Verweise... . Dort (siehe Bild 1) finden Sie links eine Liste mit allen Bibliotheken, die auf Ihrem Rechner zur Verfügung stehen. Über die Kontrollkästchen können Sie darin beliebige Einträge aktivieren oder deaktivieren. Nach dem Schließen des Dialogs über OK sind die jeweiligen Bibliotheken dann in das VBA-Projekt integriert oder aus ihm entfernt. Um zu erläutern, woher die Einträge dieser Liste überhaupt kommen und wie sie funktionieren, ist etwas weiter auszuholen.

Der Verweise-Dialog für die Bibliotheken von VBA

Bild 1: Der Verweise-Dialog für die Bibliotheken von VBA

VBA holt sie sich aus der Registry von Windows und da aus dem Zweig HKEY_CLASSES_ROOT\TypeLib. Dort stehen alle Bibliotheken, die im System installiert wurden. Genauer gesagt handelt es sich um sogenannte COM-Bibliotheken, oft auch als ActiveX-Komponenten bezeichnet. Zu beschreiben, wie diese Komponenten genau arbeiten und wie die Registry-Schlüssel mit ihnen zusammenhängen, würde hier zu weit führen. Wesentlich ist nur, dass diese COM-Bibliotheken durch Installation von Komponenten zustande kamen und eine Art Inhaltsverzeichnis darstellen. Über die GUID-Schlüssel wird eine Verbindung von Name der Bibliothek und der ausführbaren Datei hergestellt, die in der Regel als DLL daher kommt, oder als EXE-Datei. Ein VBA-Verweis ist also nichts anderes, als eine Referenz auf eine ausführbare Datei samt ihrer Funktionsliste.

Diese speziellen COM-DLLs unterscheiden sich von anderen dadurch, dass sie außer den enthaltenen Exportfunktionen eben auch noch eine integrierte Type Library aufweisen. Nur diese kann VBA lesen. Der Objektkatalog von VBA ist fähig, ihren Inhalt darzustellen. Es gibt aber zusätzlich auch solche Verweise, die nur aus einer Type Library bestehen und gar keine binären Funktionen enthalten. Das sind etwa die Dateien mit der Endung tlb oder olb. Ein Beispiel wäre die Access-Bibliothek selbst, die in der Datei msacc.olb steckt, welche sich im Office-Installationsverzeichnis befindet. Bei erfolgreicher Installation von Access hat sie sich selbst als Type Library in die Registry eingetragen.

Dort findet VBA sie und lädt ihren Inhalt, also das Verzeichnis aller Funktionen von Access, falls ein Verweis auf sie im VBA-Projekt der Datenbank eingetragen ist. Das allerdings ist immer der Fall. Sie können ihn über den Verweise-Dialog auch gar nicht entfernen. Access verhindert die Manipulation der Access-Bibliothek, wie auch die von VBA. Mit alle anderen Verweisen können Sie verfahren, wie Sie möchten.

Sehen wir uns die Funktionsweise folgender VBA-Zeile an:

S = Mid$("ACCESS BASICS", 8, 2)

> "BA"

Der Parser von VBA analysiert sie und stößt auf den ihm unbekannten Ausdruck Mid$. Daraufhin klappert er die Namen der Funktionen aller geladenen Bibliotheken ab und wird unter VBA fündig. Deren Klasse Strings enthält diese Funktion Mid$. Weil es eine globale Funktion ist, deren Klasse immer zur Verfügung steht und nicht erst instanziiert werden muss, ist dieser Funktionsname gültig. Im weiteren Verlauf schaut der Parser nach der ausführbaren Datei, welche diese Funktion enthält. Er erfährt dies aus der Registry, wo festgehalten wurde, dass die Datei vbe6.dll für den Verweis verantwortlich sei. Im Windows-Suchpfad findet er sie schließlich unter Common Files\ Microsoft Shared\VBA und lädt sie in den Prozess von Access. Da die Funktion Teil einer Objektklasse Strings ist, wird weiter automatisch eine Instanz dieser Klasse erzeugt. Nun kann in ihrem Interface die Funktion Mid$ angesprungen werden, deren Speicheradresse ebenfalls über die Type Library ermittelt wird. Die Parameter für die Funktion können jetzt übergeben werden.

Wäre ein Verweis auf VBA nicht im Projekt geladen, so fände der Parser die Funktion Mid$ auch nicht und quittierte dies beim Kompilieren mit der Fehlermeldung Unbekannte Funktion in Ausdruck.

Verweiseigenschaften

Was Sie in der Liste der Verweise zu sehen bekommen, sind nicht die Namen der Bibliotheken, sondern deren Beschreibungstexte. Für den Namen VBA lautet die Beschreibung etwa Visual Basic For Applications, für Access ist es Microsoft Access 14.0 Object Library. Sie laden den Verweis also über den Beschreibungstext, finden im Objektkatalog die Bibliothek dann aber über deren Namen.

VBA interessieren intern allerdings beide nicht. Der einzig wichtige Identifikator für die Bibliothek ist nämlich ihre GUID, die für Access den Wert

{4AFFC9A0-5F99-101B-AF4E-00AA003F0F07}

aufweist. Unter diesem Schlüssel ist sie in der Registry zu finden. Sowohl der Verweise-Dialog, wie auch der Objektkatalog schweigen sich jedoch über diese GUID aus.

Zurück zum Beispiel mit Mid$. Sie könnten eine gleichnamige Funktion auch in ein Modul Ihrer Datenbank programmieren – so geschehen in der Beispieldatenbank im Modul mdlTest. Der Parser von VBA stört sich daran nicht. Jetzt gäbe es aber zwei gleichlautende Funktionsnamen: den Ihres eigenen VBA-Projekts und den der Strings-Klasse von VBA. Wenn Sie nun irgendwo Mid$ aufrufen, so verwendet VBA automatisch die Funktion, die es zuerst in der Liste der Bibliotheken findet. Und das wäre Ihre eigene Projektbibliothek!

Die Sache ist nämlich etwas undurchsichtig. Zwar klappert der Parser die Bibliotheken genau in der Reihenfolge ab, wie sie im Verweise-Dialog zu sehen ist. Sie können dort die Position einer markierten Library über die Pfeil-Buttons einstellen. Dort aber taucht Ihre Projektbibliothek gar nicht auf, weil es sich bei dieser nicht um eine COM-Bibliothek handelt.

Im Objektkatalog wiederum ist sie zwar auswählbar, sie erfahren hier aber nichts über deren Position in der Reihenfolge der Bibliotheken. Lange Rede, kurzer Sinn: Die Bibliothek des geladenen VBA-Projekts steht immer oben! Also nimmt der Parser für Mid$ auch Ihre selbst programmierte Funktion!

Wenn Sie solchen Interferenzen aus dem Weg gehen möchten, so schreiben Sie einfach genau hin, wo die Funktion zu suchen ist. Die Aufrufe in Listing 1 etwa klappen beide.

Sub TestMid()

     Debug.Print VBA.Strings.Mid$("ACCESS BASICS", 8, 2)

     Debug.Print [1507_libraries].mdlLibraries.Mid$("ACCESS BASICS", 8, 2)

End Sub

Listing 1: Zusätzliche Angabe der Bibliothek bei Funktionsaufrufen

Hier werden die Namen der Bibliotheken angegeben, die Klasse oder das Modul, welches die Funktion enthält, und schließlich der Funktionsname selbst, alles über Punkte aneinandergefügt. Bei Namen, die anfangs nicht-alphanumerische Zeichen enthalten, müssen Sie diese übrigens in rechteckige Klammern einfassen.

Ein prominentes Beispiel dafür ist das Recordset-Objekt. Haben Sie in Ihrem Projekt Verweise auf die Bibliotheken DAO und ADO geladen, so gibt es die Recordset-Klasse gleich zweimal. Damit der Parser von VBA weiß, welche er zu nehmen hat, schreiben Sie den Bibliotheksnamen dezidiert in die Variablendeklaration:

Dim rs1 As DAO.Recordset

Dim rs2 As ADODB.Recordset

Projektbibliotheken

Aus dem Bisherigen ging bereits hervor, dass VBA nicht nur COM-Bibliotheken laden kann, sondern auch Projektbibliotheken. Das aktuelle VBA-Projekt ist eine solche. Es besteht aber auch die Möglichkeit, zusätzliche Projektbibliotheken zu integrieren. Machen Sie die Probe, und öffnen den Verweise-Dialog der Beispieldatenbank. Über den Button Durchsuchen..., der einen Dateiauswahldialog anzeigt, wählen Sie nun die begleitende Datenbank ref.accdb aus. Nach Bestätigen mit OK findet sich das VBA-Projekt dieser Datenbank sowohl im Objektkatalog, wie auch im VBA-Projekt-Explorer. Der Name lautet TestProjektBibliothek, denn das ist der Projektname, der in dieser ref.accdb angegeben wurde. Den VBA-Projektnamen können Sie jederzeit modifizieren, indem Sie im Projekt-Explorer rechtsklicken und über den Kontextmenüeintrag Eigenschaften... den gleichnamigen Dialog öffnen.

Gültige Projektbibliotheken für Access liegen grundsätzlich bei allen Access-Datenbanken vor, also etwa accdb-, accde- oder mdb-Dateien. Unter Word kämen doc- oder docx-Dateien infrage, unter Excel die xls- oder xlsx-Dateien. Die eine Office-Anwendung versteht allerdings nicht das VBA-Projekt der anderen. Mit Doc-Dateien und deren eventuellen Programminhalten kann Access nichts anfangen.

Verweise über VBA manipulieren

Mit der References-Auflistung des Access-Application-Objekts kann auch über VBA auf die Verweise zugegriffen werden. Im Modul mdlLibraries der Beispieldatenbank wird davon Gebrauch gemacht. Listing 2 zeigt zwei Prozeduren, die die Verweise des aktuellen VBA-Projekts auslesen. SingleReferenceInfos nimmt den Namen der Bibliothek entgegen und erzeugt aus diesem ein Reference-Objekt objRef. Hier kommt allerdings eine andere Bibliothek zum Einsatz, nämlich die VBIDE Library, die Office immer installiert. Deren Reference-Objekt kennt nämlich im Gegensatz zum Reference-Objekt von Access zusätzlich die Eigenschaft Description für den Beschreibungstext einer Bibliothek. Die Eigenschaften des Verweises werden nun über Debug.Print-Anweisungen im VBA-Direktfenster ausgegeben.

Sub ReferencesInfos()

     Dim objRef As Access.Reference

     

     For Each objRef In Application.References

         SingleReferenceInfos objRef.Name

         Debug.Print

     Next objRef

     

End Sub

Sub SingleReferenceInfos(Optional ByVal sRefName As String = "win32")

     Dim objRef As VBIDE.Reference

     

     Set objRef = VBE.ActiveVBProject.References(sRefName)

     With objRef

         Debug.Print "NAME", .Name

         Debug.Print "DESCRIPTION", .description

         Debug.Print "BuiltIn", .BuiltIn

         Debug.Print "Path", .FullPath

         Debug.Print "GUID", .Guid

         Debug.Print "Major/Minor Version", .Major, .Minor

         Debug.Print "Type", IIf(.Type = vbext_rk_TypeLib, "COM", "DocProject")

     End With

     Set objRef = Nothing

End Sub

Listing 2: Auslesen der Verweiseigenschaften über VBA-Routinen

Die Prozedur ReferenceInfos klappert in einer Schleife alle Elemente der References-Auflistung ab und übergibt deren Namen an die bereits beschriebene Routine. Im Ergebnis finden Sie im Direktfenster alle Infos zu den geladenen Verweisen.

Dass Verweise auch über VBA neu gesetzt werden können, zeigt Listing 3. Dafür kommen zwei Funktionen infrage: einmal AddFromFile und einmal AddFromGUID. AddFromFile erwartet die Angabe einer Datei als Parameter. Im Fall von Projekt-Bibliotheken ist das die einzige Möglichkeit, denn diese weisen keine GUID auf und sind nicht in die Registry eingetragen. AddFromGUID wiederum funktioniert nur bei COM-Bibliotheken, die sich in die Registry verewigt haben. Wie die GUID eines Verweises lautet, können Sie über die gleichnamige Eigenschaft erfahren:

Sub AddReferenceGUID()

     References.AddFromGuid "{22B38A80-C09B-11D0-8253-00805F2A72AB}", 2&, 5&

     'Win32 Type Library v 0.6 - © Patrice Scribe 1998

End Sub

Sub AddReferenceFile()

     Dim sFile As String

     

     sFile = CurrentProject.Path & "\win32.tlb"

     References.AddFromFile sFile

     'Win32 Type Library v 0.6 - © Patrice Scribe 1998

End Sub

Listing 3: Methoden zum Setzen von Verweisen über VBA

References("Access").Guid

Für den Parameter der References-Auflistung können Sie entweder den Namen der Bibliothek angeben, oder eine Ordinalzahl. Diese Zeile wäre gleichbedeutend zur vorigen:

References(2).Guid

Das Setzen von Verweisen zur Laufzeit hat allerdings eher akademische Bedeutung. In produktiven Datenbanken gibt es keinen Grund dafür. Im Gegenteil: Das Laden eines zusätzlichen Verweises nötigt den Parser von VBA, alle Bibliotheken erneut zu laden, um deren Funktionsnamen zu ermitteln. In der Folge werden alle Module des VBA-Projekts dekompiliert, denn die Funktionsaufrufe könnten nun auf andere Bibliotheken verweisen. Dabei kann es zu Fehlern kommen. Das Anlegen zusätzlicher Verweise wäre somit eine Angelegenheit, die, wenn überhaupt, ausschließlich Add-Ins vorbehalten sein sollte.