VBA-Code bearbeiten

André Minhorst, Duisburg

VBA-Code ist die Quelle des Lebens in einer Access-Datenbankanwendung. Ohne VBA-Code gibt es keine professionelle Anwendung. Diese Meinung ist gängig. VBA-Code gibt man selbst ein; eventuell kopiert man die eine oder andere Routine und verwertet sie weiter. Auch diese Meinung kann man als landläufig bezeichnen. Es verhält sich aber ganz anders. Mit dem VBE-Objektmodell können Sie Code auch generieren, lesen oder anpassen lassen – mit ein wenig Fantasie sparen Sie sich so viel Arbeit. Mit dem vorliegenden Beitrag steigen Sie in die Programmierung der VBA-Entwicklungsumgebung ein und lernen die wichtigsten Grundlagen kennen.

Hinweis

Die Beispieldatenbank zu diesem Beitrag heißt VBESamples00.mdb für Access 2000 und höher. Sie finden die Datenbank auf der Heft-CD oder im Internet unter http://www.access-im-unternehmen.de unter dem Shortlink 277. Beispiele für den Einsatz der hier vorgestellten Technik finden Sie im Beitrag Erweitern des VBA-Editors: CodeHistory, Shortlink 278 und Erweitern der VBA-Entwicklungsumgebung, Shortlink 237.

Die Entwicklung von Anwendungen unter Verwendung von VBA-Code dürfte den meisten von Ihnen bekannt sein – zumindest, wenn Sie schon die eine oder andere Ausgabe dieses Magazins gelesen oder anderweitig Erfahrungen gesammelt haben. Die Eingabe des Codes ist dabei eine sehr individuelle Tätigkeit; jede Prozedur ist anders und außerdem hat jeder seinen eigenen Programmierstil. Aber ist das wirklich so überlegen Sie einmal, wie viele Male Sie Code aus anderen Anwendungen und Modulen herauskopiert haben, um ihn an anderer Stelle wiederzuverwenden – und die innerhalb von Prozeduren zu findenden Strukturen wiederholen sich auch immer wieder. Warum also nicht die Entwicklungsumgebung um ein paar Funktionen erweitern, die automatisch VBA-Code für Sie erstellen Vielleicht enthalten die folgenden Vorschläge einen Anreiz für Sie, sich mit dieser Technik auseinander zu setzen:

  • Speichern bestehender Prozeduren oder Codeschnipsel in eine Datenbank für ständige Verfügbarkeit des Codes – Sie müssen nicht mehr die letzten zehn Projekte nach dem Code durchsuchen, den Sie garantiert dort irgendwo integriert haben …
  • Automatisches Erstellen von Property Set/Let/Get-Prozeduren nach Vorgabe weniger Parameter
  • Erstellen von Code-Konstrukten wie If…Then-, Select Case-, Do…While- und anderen Statements nach bestimmten, leicht einzugebenden Vorgaben
  • Hilfe bei der Erstellung von Funktionen wie MsgBox, InputBox, DLookup, DCount und anderen Domänenfunktionen
  • Einsatz der VBE-Helferlein

    Die oben genannten Lösungen lassen sich in einer Access-Datenbank unterbringen und von dort verwenden. Sie können auch von anderen Access-Anwendungen auf diese Datenbank verweisen und deren Funktionalität damit einbinden; es sind allerdings einige weitere Schritte mit dem Einsatz der Erweiterung verbunden.

    Die zweite, wesentlich effizientere Methode ist, die Funktionen für die Manipulation in einer .dll-Datei unterzubringen. Es gibt dort spezielle Elemente, die das direkte Einbinden in die VBA-Entwicklungsumgebung wesentlich erleichtern – weitere Informationen dazu finden Sie in den Beiträgen Erweitern der VBA-Entwicklungsumgebung in Ausgabe 5/2004 und Erweitern des VBA-Editors: CodeHistory in der vorliegenden Ausgabe. Wer jedoch nicht über Microsoft Visual Studio verfügt, kann die hier verwendeten COM-Add-Ins nicht erstellen und muss auf das etwas weniger komfortable Access-Pendant zurückgreifen. Dazu finden Sie allerdings nachfolgend jede Menge Know-how und Beispiele.

    Für die folgenden Beispiele stellen Sie in der VBA-Entwicklungsumgebung zwei Verweise auf die folgenden Bibliotheken ein (s. Abb. 1):

  • Microsoft Visual Basic for Applications Extensibility 5.3: Stellt das VBE-Objektmodell zur Verfügung.
  • Microsoft Office x.y Object Library: Ermöglicht den Zugriff auf die Menüleisten von Access und der VBA-Entwicklungsumgebung und deren Erweiterung.
  • Abb. 1: Verweise für die Programmierung der VBE

    Bevor Sie sich an das Manipulieren des Codes begeben, lernen Sie die Objekte kennen, über die Sie auf den Code zugreifen können. Das Wurzelobjekt der VBE-Bibliothek ist das VBE-Objekt. Auf dieses müssen Sie zunächst einen Verweis erstellen – natürlich nicht, ohne vorher eine entsprechende Objektvariable zu deklarieren. Das Gerüst für die folgenden Beispielprozeduren sieht dementsprechend so aus:

    Public Function VBEInitialisieren()
        Dim objVBE As VBE
        Set objVBE = Application.VBE
        ''VBE-Aktionen
        Set objVBE = Nothing
    End Function

    Die Eingabe der Objektbezeichnung objVBE gefolgt von einem Punkt (.) lässt IntelliSense alle Elemente des Objektmodells anzeigen. Für einen detaillierten überblick schauen Sie sich das Ganze im Objektkatalog an (s. Abb. 2).

    Abb. 2: Elemente des VBE-Objektmodells

    Fenster auflisten

    Die Windows-Auflistung enthält alle in der VBA-Entwicklungsumgebung eingebauten Fenster, die sich über das Ansicht-Menü aktivieren lassen, und alle sonstigen Fenster wie die Code-Fenster der jeweiligen Module. Die folgende Prozedur listet die Titel aller Fenster auf:

    Public Function Fenster()
        Dim objWindow As Window
        For Each objWindow In VBE.Windows
            Debug.Print objWindow.Caption
        Next objWindow
    End Function

    Der Titel von Fenstern, die Code enthalten, besteht aus dem Modulnamen und dem angehängten Ausdruck (Code).

    Natürlich lassen sich über diese Auflistung noch weitere Fenstereigenschaften ermitteln; außerdem stehen zwei Methoden zur Verfügung, mit denen Sie ein Fenster schließen (Close) und den Fokus darauf setzen können (SetFocus).

    Codepanes

    Die Fenster, die den Code eines Klassen- oder Standardmoduls enthalten, heißen Codepane. Die Titel aller Codepanes können Sie mit folgender Prozedur ausgeben:

    Public Function CodepanesZeigen()
        Dim objCodepane As CodePane
        For Each objCodepane In VBE.CodePanes
            Debug.Print _            objCodepane.Window.Caption
        Next objCodepane
    End Function

    Dabei greifen Sie über die Windows-Eigenschaft auf das zugrunde liegende Fenster-Element zu und geben dessen Titel aus. Der Zugriff auf ein CodePane über die CodePanes-Auslistung ist nur sinnvoll, wenn Sie den Index des benötigten CodePane kennen oder wenn Sie eine Aktion mit allen CodePanes durchführen möchten.

    Oft möchte man direkt auf das aktuell aktive CodePane zugreifen. Dazu kann man folgenden Verweis verwenden:

    VBE.ActiveCodePane

    Um damit den Titel des CodePane zu ermitteln, verwenden Sie folgende Erweiterung:

    VBE.ActiveCodePane.Window.Caption

    Das CodePane-Objekt enthält noch weitere interessante Methoden und Eigenschaften, die später in einem anderen Zusammenhang vorgestellt werden.

    CodeModules

    Das für die nachfolgenden Beispiele wichtigste Element ist das CodeModule. Das CodeModule enthält den eigentlichen Code des durch das CodePane repräsentierten Moduls. Auf den Inhalt eines CodeModule-Objekts können Sie auf unterschiedliche Weise zugreifen. Am einfachsten ist der Zugriff auf das CodeModule des aktuellen CodePanes:

    Public Function CodeModulesAnzeigen()
        Dim objCodeModule As CodeModule
        Set objCodeModule = _        VBE.ActiveCodePane.CodeModule
        With objCodeModule
            .CountOfLines
        End With
        Set objCodeModule = Nothing
    End Function

    Wenn Sie auf das CodeModule eines bestimmten Moduls zugreifen möchten und dieses namentlich kennen, verwenden Sie die folgende Anweisung (ohne Zeilenumbruch):

     VBE.ActiveVBProject.VBComponents("mdlVBE").CodeModule.CountOfLines

    Damit haben Sie noch ein weiteres Element des VBE-Objektmodells kennen gelernt: ActiveVBProject gibt einen Verweis auf das aktuell in der VBA-Entwicklungsumgebung verwendete Projekt an.

    Einbinden weiterer VBA-Projekte

    Möglicherweise fragen Sie sich, wie man mehr als ein VBA-Projekt gleichzeitig in der VBA-Entwicklungsumgebung verwenden kann. Das geht ganz einfach: öffnen Sie einfach den Verweise-Dialog über den Menüpunkt Extras/Verweise und klicken Sie dort auf die Schaltfläche Durchsuchen. Stellen Sie im nun erscheinenden Dialog den Dateityp Microsoft Office Access-Datenbanken (*.mdb) ein und wählen Sie eine andere Datenbank als die aktuelle aus.

    Public Function CreateModule(strModulename As String, lngModuletype As Modultype)
        Dim objVBComponent As VBComponent
        Set objVBComponent = VBE.ActiveVBProject.VBComponents.Add(lngModuletype)
        objVBComponent.Name = strModulename
        DoCmd.Save acModule, strModulename
        Set objVBComponent = Nothing
    End Function

    Quellcode 1

    Abb. 3: Bearbeiten eines VBA-Projekts einer anderen Datenbank

    Der Projekt-Explorer zeigt das aktuelle und zusätzlich das per Verweis verfügbar gemachte VBA-Projekt an. Sie können auf die Module dieses Projekts zugreifen und sogar neue Module anlegen und bearbeiten (s. Abb. 3).

    Wenn Sie mehrere VBA-Projekte gleichzeitig in der VBA-Entwicklungsumgebung anzeigen, empfiehlt sich der explizite Zugriff auf eines der Projekte statt der Verwendung der Funktion ActiveVBProject:

    VBE.VBProjects("VBESample").VBComponents("mdlVBE").CodeModule

    Die Arbeit mit dem in den Modulen enthaltenen VBA-Code schließt auch das Anlegen, Löschen und Bearbeiten der Module ein.

    Erstellen eines Moduls

    Das Erstellen eines Moduls läuft in mehreren Schritten ab. über die Add-Methode der Auflistung VBComponents legen Sie ein neues Modul an. Um seinen Namen einzustellen, verweisen Sie direkt per entsprechender Objektvariable auf das neue Objekt. Schließlich müssen Sie das Modul noch speichern; dazu verwenden Sie die herkömmliche DoCmd.Save-Methode. Die folgende Prozedur legt ein neues Modul mit dem gewünschten Namen und Typ an. Es gibt drei Typen: Standardmodule, Klassenmodule und Formular- oder Berichtsmodule. Für das Festlegen des Typs verwendet die Prozedur eine Enum-Auflistung. Diese dient lediglich der besseren Lesbarkeit der Konstanten, die Werte selbst stimmen mit den Originalkonstanten überein:

    Public Enum Modultype
        Classmodule = 2
        FormReportModul = 100
        Standardmodule = 1
    End Enum

    Die Prozedur sieht schließlich wie in Quellcode 1 aus. Mit dem Aufruf aus Abb. 4 legen Sie beispielsweise ein Klassenmodul namens clsTest an.

    Public Function DeleteModule(strModulename As String)
        Dim objVBComponent As VBComponent
        Set objVBComponent = VBE.ActiveVBProject.VBComponents(strModulename)
        VBE.ActiveVBProject.VBComponents.Remove objVBComponent
        Set objVBComponent = Nothing
    End Function

    Quellcode 2

    Public Function ListModules()
        Dim objVBComponent As VBComponent
        For Each objVBComponent In VBE.ActiveVBProject.VBComponents
            Debug.Print objVBComponent.Name
        Next objVBComponent
    End Function

    Quellcode 3

    Abb. 4: Anlegen eines neuen Klassenmoduls

    Hinweis

    Diese und die folgenden Beispielprozeduren enthalten aus Platzgründen keine Fehlerbehandlung. Im vorliegenden Fall müssten Sie beispielsweise noch Vorkehrungen für den Fall treffen, dass das anzulegende Klassenmodul bereits vorhanden ist.

    Löschen eines Moduls

    Für das Löschen eines Moduls erstellen Sie zunächst eine Objektvariable, die auf das Modul verweist. Anschließend verwenden Sie die Remove-Methode der VBComponents-Auflistung.

    Die Funktion aus Quellcode 2 kapselt diese Funktionalität und erwartet lediglich den Namen des Moduls als Parameter.

    Auflisten der bestehenden Module

    Auf einzelne Module können Sie über die VBComponents-Auflistung zugreifen, wie Sie in den beiden vorhergehenden Beispielen sehen konnten.

    Das Auflisten aller Module des aktuellen Projekts erfolgt ebenfalls über diese Auflistung, wie Quellcode 3 zeigt.

    Nachdem Sie erfahren haben, wie Sie auf verschiedene Art und Weise auf die Code-Module zugreifen können, schauen Sie sich nun die Funktionen an, um auf die Eigenschaften der Module und des enthaltenen Codes zuzugreifen.

    Die Eigenschaften und Methoden sind auf zwei Objekte aufgeteilt: auf das CodePane-Objekt und das darin enthaltene CodeModule-Objekt.

    Eigenschaften und Methoden des CodePane-Objekts

    Die im CodePane-Objekt enthaltenen Elemente beziehen sich eher auf die sichtbaren Eigenschaften des im Code-Fenster angezeigten Codes.

    Oberste Zeile

    Die Eigenschaft TopLine gibt die Nummer der Zeile zurück, die ganz oben im Fenster angezeigt wird. Nach dem öffnen eines Code-Fensters ist dies typischerweise die 1:

     VBE.ActiveCodePane.TopLine
     1 

    Scrollen Sie ein wenig herunter und lassen Sie sich den Eigenschaftswert erneut ausgeben, um die Veränderung zu beobachten.

    Public Function Markierungskoordinaten()
        Dim objCodePane As CodePane
        Dim lngStartLine As Long
        Dim lngStartColumn As Long
        Dim lngEndLine As Long
        Dim lngEndColumn As Long
        Set objCodePane = VBE.ActiveCodePane
        With objCodePane
            .GetSelection lngStartLine, lngStartColumn, lngEndLine, lngEndColumn
            MsgBox "Die Koordinaten lauten:" & vbCrLf _
                & "Erste Zeile: " & lngStartLine & vbCrLf _
                & "Erste Spalte: " & lngStartColumn & vbCrLf _
                & "Letzte Zeile: " & lngEndLine & vbCrLf _
                & "Letzte Spalte: " & lngEndColumn & vbCrLf
        End With
        Set objCodePane = Nothing
    End Function

    Quellcode 3

    Public Function MarkierungSetzen()
        Dim objCodePane As CodePane
        Dim lngStartLine As Long
        Dim lngStartColumn As Long
        Dim lngEndLine As Long
        Dim lngEndColumn As Long
        Set objCodePane = VBE.ActiveCodePane
        lngStartLine = 1
        lngStartColumn = 1
        lngEndLine = 2
        lngEndColumn = 2
        With objCodePane
            .SetSelection lngStartLine, lngStartColumn, lngEndLine, lngEndColumn
        End With
        Set objCodePane = Nothing
    End Function

    Quellcode 4

    Koordinaten der aktuellen Markierung

    Für viele Funktionen ist die Kenntnis der aktuellen Markierung interessant. Die VBA-Entwicklungsumgebung erlaubt keinen Blockauswahl-Modus wie etwa Textpad. Die vier von der Funktion GetSelection gefüllten Parameter geben daher an, in welcher Zeile und Spalte das erste Zeichen und wo das letzte Zeichen der Markierung liegt. Das bedeutet, dass der Wert für die erste Spalte durchaus größer als der Wert für die letzte Spalte sein kann.

    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

    Schreibe einen Kommentar