Wenn Sie sich mit den anderen Beiträgen dieser Reihe bis zum VBComponent-Objekt eines Moduls vorgearbeitet haben, ist es nur noch ein Katzensprung bis zur CodeMod-ule-Klasse. Damit können Sie dann die Inhalte eines VBA-Moduls auslesen und bearbeiten. Dieser Beitrag zeigt, welche Methoden die CodeModule-Klasse bietet und wie Sie diese für die verschiedenen Anwendungszwecke einsetzen können.
Vorbereitung
Um die Elemente der Klasse VBE nutzen zu können, benötigen Sie einen Verweis auf die Bibliothek Microsoft Visual Basic for Applications Extensibility 5.3 Object Library, den Sie im Verweise-Dialog des VBA-Editors hinzufügen können (Menüeintrag Extras|Verweise).
Vorbereitende Beiträge
Wenn Sie erfahren wollen, wie Sie überhaupt bis zu der hier beschriebenen Klasse gelangen, helfen die folgenden Beiträge weiter:
- VBA-Projekt per VBA referenzieren (www.access-im-unternehmen.de/1337)
- Zugriff auf den VBA-Editor mit der VBE-Klasse (www.access-im-unternehmen.de/1350)
- Zugriff auf VBA-Projekte per VBProject (www.access-im-unternehmen.de/1351)
- Module und Co. im Griff mit VBComponent (www.access-im-unternehmen.de/1352)
Elemente der VBComponent-Klasse
Die CodeModule-Klasse und ihre Eigenschaften, Methoden und Auflistungen können Sie im Objektkatalog im Überblick ansehen, wenn Sie dort nach CodeModule suchen (siehe Bild 1). Hier sehen wir neben den Elementen dieser Klasse auch, dass diese sowohl ein Unterelement von VBComponent als auch von CodePane ist. Als Element von VBComponent können Sie es anlegen, und CodePane ist die Schnittstelle zwischen dem anzeigenden Window-Element im VBA-Editor und dem CodeModule-Objekt, das einige Möglichkeiten für den Zugriff auf den Code über die Benutzeroberfläche ermöglicht.
Bild 1: Die CodeModule-Klasse im Objektkatalog
Die Klasse CodeModule bietet folgende Elemente:
- AddFromFile: Fügt VBA-Code aus der per Parameter angegebenen Textdatei hinzu.
- AddFromString: Fügt VBA-Code aus der per Parameter übergebenen Zeichenkette hinzu.
- CodePane: Liefert einen Verweis auf das CodePane-Element, mit dem Sie speziell Zugriffsmöglichkeiten auf die angezeigte Version des CodeModule-Objekts haben – beispielsweise um Markierungen abzufragen oder zu setzen.
- CountOfDeclarationLines: Liefert die Anzahl der Zeilen im Deklarationsbereich des Moduls.
- CountOfLines: Liefert die gesamte Anzahl der Zeilen im Modul.
- CreateEventProc: Erstellt eine Ereignisprozedur für das mit den beiden Parametern angegebene Ereignis und Objekt.
- DeleteLines: Löscht die mit dem zweiten Parameter angegebene Anzahl von Zeilen ab der mit dem ersten Parameter angegebenen Zeile.
- Find: Sucht nach dem mit dem ersten Parameter angegebenen Ausdruck und liefert mit den folgenden Parametern die Position des Fundorts zurück.
- InsertLines: Fügt ab der mit dem ersten Parameter angegebenen Zeile den mit dem zweiten Parameter angegebenen Text im Modul ein.
- Lines: Liefert den Inhalt einer oder mehrerer Zeilen, wobei der erste Parameter die Nummer der ersten Zeile und der zweite die Anzahl der Zeilen angibt.
- Parent: Referenziert das übergeordnete Objekt, in diesem Fall ein Objekt des Typs VBComponent.
- ProcBodyLine: Liefert die Nummer der Zeile der angegebenen Prozedur mit dem Sub|Function|Property-Schlüsselwort.
- ProcCountLines: Liefert die Anzahl der Zeilen einer Prozedur.
- ProcOfLine: Gibt die Prozedur und den Typ der Prozedur für eine bestimmte Zeile zurück.
- ProcStartLine: Liefert die Nummer der ersten Zeile nach der letzten Zeile der vorherigen Prozedur oder des allgemeinen Deklarationsteils.
- ReplaceLine: Ersetzt die Zeile mit der im ersten Parameter angegebenen Nummer durch den mit dem zweiten Parameter angegebenen Text.
- VBE: Referenziert das VBA-Editor-Objekt des CodeModule-Objekts.
Das CodeModule-Objekt referenzieren
Um das CodeModule-Objekt eines Moduls zu referenzieren, benötigen Sie zuerst Zugriff auf das entsprechende VBComponent-Element. Meist wollen Sie direkt auf ein bestimmtes Objekt zugreifen, dessen Namen Sie kennen. Dann können Sie dieses über die VBComponents-Auflistung des VBProject-Elements referenzieren.
Das VBComponent-Element bietet dann über die CodeModule-Eigenschaft die Möglichkeit des Zugriffs auf das CodeModule-Objekt an. Im folgenden Beispiel referenzieren wir dieses und geben dann die Anzahl der Codezeilen in diesem CodeModule-Objekt aus:
Public Sub CodeModuleReferenzieren() Dim objVBProject As VBProject Dim objVBComponent As VBComponent Dim objCodeModule As CodeModule Set objVBProject = VBE.ActiveVBProject Set objVBComponent = objVBProject.VBComponents("mdlVBE") Set objCodeModule = objVBComponent.CodeModule Debug.Print objCodeModule.CountOfLines End Sub
Code aus einer Textdatei hinzufügen
Mit der Export-Methode des VBComponent-Objekts können Sie eine Textdatei mit dessen Inhalt exportieren. Diese können Sie beispielsweise mit der AddFromFile-Methode der CodeModule-Klasse wieder einlesen.
Wie das gelingt, zeigen wir in folgendem Beispiel. Hier legen wir ein neues, leeres VBComponent-Objekt an und nutzen dann die AddFromFile-Methode seines CodeModule-Objekts, um den Inhalt des exportierten Moduls in das neue Modul einzulesen:
Public Sub CodeModuleAddFromFile() Dim objVBProject As VBProject Dim objVBComponent As VBComponent Dim objCodeModule As CodeModule Set objVBProject = VBE.ActiveVBProject Set objVBComponent = objVBProject.VBComponents.Add(vbext_ct_StdModule) Set objCodeModule = objVBComponent.CodeModule objCodeModule.AddFromFile CurrentProject.Path & "\Neu.txt" End Sub
Zu beachten ist hier, dass bei exportierten Modulen auch die Attribute mit exportiert werden, also zum Beispiel der Modulname.
Dieser wird beim Importieren in ein vorhandenes Modul dann für das übergeordnete VBComponent-Objekt verwendet.
Sie können mit AddFromFile jedoch auch Textdateien mit dem reinen Inhalt des Moduls laden.
Code per Zeichenkette hinzufügen
Gegebenenfalls stellen Sie den Code für ein Modul in einer Textvariablen zusammen oder lesen diesen von anderer Stelle ein, beispielsweise aus einem Feld einer Datenbanktabelle. Wenn Sie den Inhalt der Variablen schnell in ein neues, leeres Modul einfügen möchten, bietet sich die Methode AddFromString an. Diese schreibt den Code direkt in das CodeModule-Objekt.
Im folgenden Beispiel stellen wir den einzufügenden Code zuvor in der Variablen strCode zusammen und weisen diesen dann mit AddFromString dem CodeModule-Objekt zu:
Public Sub CodeModuleAddFromString() Dim objVBProject As VBProject Dim objVBComponent As VBComponent Dim objCodeModule As CodeModule Dim strCode As String Set objVBProject = VBE.ActiveVBProject Set objVBComponent = objVBProject.VBComponents. Add(vbext_ct_StdModule) objVBComponent.Name = "mdlAddFromString" Set objCodeModule = objVBComponent.CodeModule strCode = "Dim strTest As String" & vbCrLf & vbCrLf strCode = strCode & "Public Sub Test()" & vbCrLf strCode = strCode & " Debug.Print ""Test""" & vbCrLf strCode = strCode & "End Sub" objCodeModule.AddFromString strCode End Sub
Das Ergebnis finden Sie in Bild 2.
Bild 2: Per AddFromString initial hinzugefügter Code
Sie können AddFromString auch nutzen, um Code in ein Modul einzufügen, das bereits Code enthält. Der neu einzufügende Code landet dann genau hinter der letzten Deklarationszeile im Modul.
Das macht Sinn, denn wenn der einzufügende Code auch im oberen Bereich Deklarationszeilen und im unteren Routinen enthält, dann gibt es weiterhin eine Trennung zwischen den Deklarationen im oberen Bereich und der Programmlogik im unteren Bereich. Die folgende Prozedur fügt eine Deklarationszeile zum bestehenden Code aus dem vorherigen Beispiel hinzu:
Public Sub CodeModuleAddMoreFromString() Dim objVBProject As VBProject Dim objCodeModule As CodeModule Dim strCode As String Set objVBProject = VBE.ActiveVBProject Set objCodeModule = objVBProject.VBComponents( "mdlAddFromString").CodeModule strCode = "Dim strTest2 As String" objCodeModule.AddFromString strCode End Sub
Dieser wird dann im Modul wie in Bild 3 eingefügt.
Bild 3: Per AddFromString nachträglich hinzugefügter Code
Das CodePane-Objekt eines Moduls referenzieren
Im Beitrag Zugriff auf den VBA-Editor mit der VBE-Klasse (www.access-im-unternehmen.de/1350) haben wir den Unterschied und die Zusammenhänge zwischen VBComponent, Window und CodePane erläutert. Das CodePane ist das Element, in dem das CodeModule-Objekt im Window-Objekt angezeigt wird.
Deshalb können wir vom CodeModule-Element über die Eigenschaft CodePane auch auf das betroffene Code-Pane-Element zugreifen. Das CodePane-Element referenzieren wir dabei wie folgt:
Public Sub CodePaneReferenzieren() Dim objVBProject As VBProject Dim objCodeModule As CodeModule Dim objCodePane As CodePane Set objVBProject = VBE.ActiveVBProject Set objCodeModule = objVBProject.VBComponents( "mdlCodeModule").CodeModule Set objCodePane = objCodeModule.CodePane ''... Dinge mit dem CodePane erledigen End Sub
Welche Möglichkeiten die CodePane-Klasse bietet, lesen Sie im Beitrag Auf VBA-Code zugreifen per CodePane (www.access-im-unternehmen.de/1354).
Schneller Zugriff auf das CodeModule per CodePane
Das CodePane-Objekt hat eine Eigenart, die wir uns in den folgenden Beispielen zunutze machen wollen: Sie können das aktive CodePane-Objekt, also den Container im aktuell aktiven VBA-Fenster mit dem CodeModule-Objekt, auch direkt mit der Eigenschaft ActiveCodePane der übergeordneten VBE-Klasse referenzieren.
Zeilen zählen im Modul
Es gibt einige Eigenschaften, mit denen Sie verschiedene Zeilenanzahlen ermitteln können.
Diese schauen wir uns in den nächsten Abschnitten an.
Anzahl aller Zeilen im Modul
Am einfachsten ist das Zählen aller Zeilen. Dies erledigen wir mit der Eigenschaft CountOfLines. Diese liefert die Anzahl der Zeilen von der ersten bis zur letzten Zeile des Moduls.
Wir gehen davon aus, dass das zu untersuchende Modul geöffnet ist und dass das entsprechende VBA-Fenster den Fokus hat.
Dann können wir nämlich ganz einfach wie folgt über den Direktbereich auf zu die untersuchenden Eigenschaften zugreifen – hier auf die Anzahl der Codezeilen:
VBE.ActiveCodePane.CodeModule.CountOfLines 9
Die Eigenschaft CountOfLines liefert die Anzahl der Zeilen, wobei auch solche Zeilen ohne Inhalt mitgezählt werden. In Bild 4 ist die Zeile mit dem Kommentar “09 die letzte Zeile. Wenn wir hinter “09 noch einmal die Eingabetaste betätigen und somit einen Zeilenumbruch hinzufügen, liefert CountOfLines folglich den Wert 10.
Bild 4: Abfragen von CodeModule-Eigenschaften per Direktbereich
Beispielmodul für die folgenden Beispiele
Damit Sie Beispielmaterial haben, anhand dessen Sie die folgenden Beispiele nachvollziehen können, haben wir das Modul mdlBeispielcode aus Bild 5 zum Projekt hinzugefügt. Mit der CountOfLines-Eigenschaft erhalten Sie für dieses Modul den Wert 28.
Bild 5: Beispielmodul
Anzahl der Deklarationszeilen
Die Eigenschaft CountOfDeclarationLines liefert die Anzahl der Zeilen bis zur letzten Deklarationsanweisung im Modul. Da Sie keine Deklarationszeilen hinter der ersten Routine mehr verwenden dürfen, können Sie beide Bereiche somit sehr gut voneinander unterscheiden.
Im Gegensatz zu CountOfLines kümmert sich CountOfDeclarationLines situationsbedingt nicht um nachfolgende Leerzeilen:
- Wenn nach der letzten Deklarationszeile mindestens eine Sub-, Function– oder Property-Prozedur folgt, dann gibt CountOfDeclarationLines die Anzahl der Zeilen bis zur letzten Deklarationszeile aus.
- Wenn nach der letzten Deklarationszeile keine Sub-, Function– oder Property-Prozedur folgt, wenn das Modul also nur einen Deklarationsteil enthält, dann liefert CountOfDeclarationsLines die Anzahl der Zeilen bis zur letzten Zeile des Moduls.
Im Fall des Moduls aus dem Beispiel erhalten wir also folgendes Ergebnis:
VBE.ActiveCodePane.CodeModule.CountOfDeclarationLines 4
Anzahl der Zeilen einer Prozedur
Wenn Sie die Anzahl der Zeilen einer speziellen Prozedur ermitteln wollen, nutzen Sie die Eigenschaft ProcCountLines. Diese Eigenschaft erwartet zwei Parameter:
- ProcName: Name der zu untersuchenden Prozedur
- ProcKind: Art der zu untersuchenden Prozedur. Mögliche Werte: vbext_pk_Get (Property Get-Prozedur), vbext_pk_Let (Property Let-Prozedur), vbext_pk_Proc (Sub– oder Function-Prozedur) oder vbext_pk_Set (Property Set-Prozedur)
Um diese Eigenschaft nutzen zu können, müssen Sie sowohl den Namen als auch den Typ der Prozedur kennen. Ein Beispielaufruf aus dem Direktbereich heraus lautet:
VBE.ActiveCodePane.CodeModule.ProcCountLines("Testsub", vbext_pk_Proc) 5
Warum erscheint hier der Wert 5 Weil sowohl die Kommentarzeile als auch die leeren Zeilen unmittelbar vor der untersuchten Prozedur mitgezählt werden – also alle seit dem allgemeinen Deklarationsteil oder der vorherigen Prozedur inklusive Kommentarzeilen.
Alle Zeilen eines Moduls ausgeben
Wenn Sie eine oder mehrere Zeilen eines Moduls ausgeben wollen, referenzieren Sie als erstes das CodeModule-Objekt. Dann können Sie mit der Lines-Methode gezielt den Inhalt einer oder mehrerer Zeilen gleichzeitig abfragen.
Im ersten Beispiel geben wir für das erste Argument der Lines-Methode den Wert 1 für die erste Zeile und den Wert der Eigenschaft CountOfLines des CodeModule-Objekts für den zweiten Parameter an. Lines sollte hier also alle Zeilen in einem Rutsch liefern:
Public Sub AlleZeilenGleichzeitigAusgeben() Dim objCodeModule As CodeModule Set objCodeModule = VBE.ActiveVBProject. VBComponents("mdlBeispielcode").CodeModule Debug.Print objCodeModule.Lines(1, objCodeModule.CountOfLines) End Sub
Das Ergebnis finden Sie in Bild 6.
Bild 6: Ausgabe aller Zeilen
Nun wollen wir die Prozedur inklusive Zeilennummern ausgeben. Dazu referenziert die folgende Prozedur das Modul mdlBeispielcode und durchläuft in einer For Next-Schleife die Zahlen von 1 bis zu der mit der Eigenschaft CountOfLines ermittelten Anzahl der Zeilen.
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