{"id":55000426,"date":"2024-04-01T00:00:00","date_gmt":"2024-04-23T12:51:27","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=426"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"VBAEditor_QuellcodeBearbeitung_automatisieren","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/VBAEditor_QuellcodeBearbeitung_automatisieren\/","title":{"rendered":"VBA-Editor: Quellcode-Bearbeitung automatisieren"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/72e17bfc58fb4167b468eeae714f472f\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Der VBA-Editor ist die Gemeinsamkeit der Office-Anwendungen wie Access, Excel, Outlook, PowerPoint und Word. Wer eine oder mehrere dieser Anwendungen programmiert, um dem Benutzer die Arbeit damit zu erleichtern, kennt sich mehr oder weniger mit VBA aus. In der Regel wird im Arbeitsalltag eines Entwicklers jede Codezeile von Hand neu programmiert. Gegebenenfalls kopiert man bestehenden Code und passt diesen an den jeweiligen Anwendungszweck an. Aber warum nicht einen Schritt weitergehen und VBA-Code zur Erstellung von VBA-Code selbst nutzen? Visual Basic bietet eigens zum Zweck der Programmierung der Elemente und des Codes im VBA-Editor eine eigene Bibliothek namens Microsoft Visual Basic for Applications Extensibility 5.3. Welche M&ouml;glichkeiten diese allgemein bietet und welche Elemente, Eigenschaften und Methoden sie bereitstellt, schauen wir uns in diesem Artikel an.<\/b><\/p>\n<p>Der VBA-Editor ist die Entwicklungsumgebung f&uuml;r die Programmierung der verschiedenen Office-Anwendungen und der darin enthaltenen Dokumente und Elemente. Er zeigt im Projekt-Explorer die programmierbaren Elemente wie Standardmodule und Klassenmodule an und erlaubt es, den Code dieser Elemente im Code-Editor anzuzeigen und zu bearbeiten.<\/p>\n<p>Die Codeeingabe selbst ist bis auf wenige Hilfestellungen durch IntelliSense Aufgabe des Entwicklers &#8211; hier ist viel Tipparbeit angezeigt oder gegebenenfalls noch das Kopieren und Anpassen bereits vorhandenen Codes.<\/p>\n<p>IntelliSense unterst&uuml;tzt uns allerdings auch nur dabei, den Datentyp f&uuml;r Variablen auszuw&auml;hlen oder die Eigenschaften oder Methoden von Objektvariablen zu selektieren. Wenn wir mehr aus der Entwicklungsumgebung herausholen wollen, m&uuml;ssen wir uns also selbst helfen.<\/p>\n<p>Dabei k&ouml;nnen wir bereits mit den &uuml;blichen Mitteln von VBA Einiges erreichen: So k&ouml;nnen wir die Zeichenkettenfunktionen in Kombination mit Schleifen nutzen, um bestimmte Abfolgen von Anweisungen im Direktbereich des VBA-Editors auszugeben, die wir dann kopieren und in unseren Code einf&uuml;gen.<\/p>\n<p>Wir k&ouml;nnen jedoch noch viel mehr erreichen, wenn wir eine Bibliothek namens <b>Microsoft Visual Basic for Applications Extensibility 5.3 <\/b>einbinden. Diese f&uuml;gen wir &uuml;ber den <b>Verweise<\/b>-Dialog, den wir mit dem Men&uuml;befehl <b>Extras|Verweise <\/b>&ouml;ffnen, zum aktuellen VBA-Projekt hinzu. Dazu versehen wir den Eintrag wie in Bild 1 mit einem Haken.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_001.png\" alt=\"Setzen eines Verweises auf die Bibliothek Microsoft Visual Basic for Applications Extensibility 5.3\" width=\"499.6267\" height=\"393.8742\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Setzen eines Verweises auf die Bibliothek Microsoft Visual Basic for Applications Extensibility 5.3<\/span><\/b><\/p>\n<h2>Die Klassen und Elemente der VBE-Bibliothek<\/h2>\n<p>Anschlie&szlig;end k&ouml;nnen wir uns im Objektkatalog, zu &ouml;ffnen mit der Taste <b>F2<\/b>, die Klassen und Enumerationen dieser Bibliothek ansehen (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_002.png\" alt=\"Die Elemente der Bibliothek Microsoft Visual Basic for Applications Extensibility 5.3\" width=\"424.6267\" height=\"680.751\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Die Elemente der Bibliothek Microsoft Visual Basic for Applications Extensibility 5.3<\/span><\/b><\/p>\n<p>Damit nur die Elemente der hier <b>VBIDE <\/b>genannten Bibliothek angezeigt werden, haben wir diesen Eintrag im Kombinationsfeld ganz oben ausgew&auml;hlt.<\/p>\n<p>Danach sehen wir in der linken Liste alle Klassen und Enumerationen dieser Bibliothek und rechts die Elemente des aktuell markierten Eintrags der linken Liste, hier der Hauptklasse <b>VBE<\/b>.<\/p>\n<p>Und hier ist eine kurze Beschreibung der Elemente, die wir direkt &uuml;ber die Hauptklasse erreichen k&ouml;nnen:<\/p>\n<ul>\n<li><b>ActiveCodePane<\/b>: Aktueller Codebereich. Codebereich ist erkl&auml;rungsbed&uuml;rftig, darauf gehen wir weiter unten ein.<\/li>\n<li><b>ActiveVBProject<\/b>: Aktuelles VBA-Projekt. Ermittelt das aktive von gegebenenfalls mehreren aktuell ge&ouml;ffneten VBA-Projekten im VBA-Editor.<\/li>\n<li><b>ActiveWindow<\/b>: Aktuelles Fenster. Zu den Fenstern z&auml;hlen nicht nur die Codefenster, sondern auch der Direktbereich, der Projekt-Explorer et cetera.<\/li>\n<li><b>Addins<\/b>: Auflistung der COM-Add-Ins, die aktuell f&uuml;r den VBA-Editor registriert sind.<\/li>\n<li><b>CodePanes<\/b>: Auflistung aller <b>CodePane<\/b>-Elemente.<\/li>\n<li><b>CommandBars<\/b>: Auflistung aller <b>CommandBar<\/b>-Elemente, also aller Men&uuml;leisten des VBA-Editors.<\/li>\n<li><b>Events<\/b>: Auflistung aller <b>Event<\/b>-Auflistungen, enth&auml;lt die beiden Auflistungen <b>CommandBarEvents <\/b>und <b>ReferencesEvents<\/b>.<\/li>\n<li><b>MainWindow<\/b>: Verweis auf das Hauptfenster des VBA-Editors<\/li>\n<li><b>SelectedVBComponent<\/b>: Verweis auf die aktuell im Projekt-Explorer selektierte Komponente, also beispielsweise ein Modul<\/li>\n<li><b>VBProjects<\/b>: Auflistung aller VBA-Projekte, die aktuell im Projekt-Explorer angezeigt werden.<\/li>\n<li><b>Version<\/b>: Version von VBA, aktuell <b>7.01<\/b><\/li>\n<li><b>Windows<\/b>: Auflistung aller Fenster des VBA-Editors. Dabei werden auch einige nicht ge&ouml;ffnete Fenster aufgelistet.<\/li>\n<\/ul>\n<h2>Deklarieren und Referenzieren<\/h2>\n<p>Beim Deklarieren der Elemente der VB-Editor-Bibliothek k&ouml;nnen wir die &uuml;bergeordnete Klasse <b>VBIDE <\/b>verwenden. Damit erhalten wir dann alle Elemente dieser Bibliothek per IntelliSense:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objWindow<span style=\"color:blue;\"> As <\/span>VBIDE.Window<\/pre>\n<p>Bei Referenzieren nutzen wir hingegen einfach <b>VBE<\/b>, zum Beispiel:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> objWindow = VBE.ActiveWindow<\/pre>\n<h2>Fenster im VBA-Editor programmieren<\/h2>\n<p>Die Fenster im VBA-Editor k&ouml;nnen wir mit der <b>Windows<\/b>-Auflistung durchlaufen. Dabei verwenden wir als Laufvariable der <b>For Each<\/b>-Schleife eine Variable des Typs <b>Window<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FensterDurchlaufen()\r\n     <span style=\"color:blue;\">Dim <\/span>objWindow<span style=\"color:blue;\"> As <\/span>VBIDE.Window\r\n     For Each objWindow In VBE.Windows\r\n         <span style=\"color:blue;\">With<\/span> objWindow\r\n             <span style=\"color:blue;\">Debug.Print<\/span> .Type, .WindowState, .Caption\r\n         End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> objWindow\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier geben wir den Typ, den Fensterstatus und die Beschriftung aus, was bei einem ge&ouml;ffneten Modul wie in Bild 3 aussieht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_003.png\" alt=\"Ausgabe der Fenster mit einigen Eigenschaftswerten\" width=\"499.6267\" height=\"174.406\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Ausgabe der Fenster mit einigen Eigenschaftswerten<\/span><\/b><\/p>\n<p>Was die einzelnen Zahlen f&uuml;r die Eigenschaft <b>Type <\/b>bedeuten, k&ouml;nnen wir der Enumeration <b>vbext_WindowType <\/b>entnehmen, die wir im Objektkatalog finden. <b>0 <\/b>steht beispielsweise f&uuml;r <b>vbext_wt_CodeWindow<\/b>. Die anderen Werte stehen f&uuml;r die jeweiligen Fenstertypen wie Direktbereich, Projekt-Explorer und so weiter.<\/p>\n<p>Wenn wir einmal die Fenster und ihre Position steuern wollen, k&ouml;nnen wir diese und andere Eigenschaften der <b>Window<\/b>-Objekte nutzen. Diese liefern beispielsweise auch die Position und Gr&ouml;&szlig;e der Fenster.<\/p>\n<h2>VBA-Projekte<\/h2>\n<p>Der VBA-Editor kann durchaus einmal mehrere VBA-Projekte gleichzeitig im Projekt-Explorer anzeigen, beispielsweise wenn aktuell ein Add-In geladen ist.<\/p>\n<p>Diese k&ouml;nnen wir &uuml;ber die Auflistung <b>VBProjects <\/b>durchlaufen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ProjekteDurchlaufen()\r\n     <span style=\"color:blue;\">Dim <\/span>objVBProject<span style=\"color:blue;\"> As <\/span>VBIDE.VBProject\r\n     For Each objVBProject In VBE.VBProjects\r\n         <span style=\"color:blue;\">Debug.Print<\/span> objVBProject.Name\r\n     <span style=\"color:blue;\">Next<\/span> objVBProject\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Element <b>VBProject <\/b>liefert neben dem Namen noch einige weitere interessante Eigenschaften:<\/p>\n<ul>\n<li><b>Filename<\/b>: Liefert den Namen der Datei, in dem sich das VBA-Modul befindet. Das kann hilfreich sein, um das VBA-Modul zum aktuell ge&ouml;ffneten Dokument zu ermitteln.<\/li>\n<li><b>VBComponents<\/b>: Liefert eine Auflistung aller <b>VBComponent<\/b>-Elemente, also der VBA-Module.<\/li>\n<\/ul>\n<h2>Aktuelles VBA-Projekt ermitteln<\/h2>\n<p>Wenn mehrere VBA-Projekte geladen sind, liefert <b>ActiveVBProject <\/b>abh&auml;ngig von dem Ort, wo es ausgef&uuml;hrt wird, unterschiedliche Ergebnisse. Wenn wir es im Direktbereich aufrufen, erhalten wir einen Verweis auf das VBA-Projekt, das gerade im Projekt-Explorer den Fokus hat. Wenn wir es aus einem Modul heraus aufrufen, erhalten wir mit <b>ActiveVBProject<\/b> einen Verweis auf das VBA-Projekt, in dem sich das aufrufende Modul befindet.<\/p>\n<h2>VBA-Projekt zu einem bestimmten Dokument ermitteln<\/h2>\n<p>Manchmal kann es interessant sein, genau das VBA-Projekt zu ermitteln, das zu einem bestimmten Dokument oder einer Datenbank geh&ouml;rt. Voraussetzung daf&uuml;r ist, dass wir den Pfad des aktuellen Dokuments kennen. Dann k&ouml;nnen wir einfach die Liste der VBA-Projekte im VBA-Editor durchlaufen und pr&uuml;fen, ob der mit der Eigenschaft <b>Filename <\/b>gelieferte Pfad mit dem Pfad des Dokuments &uuml;bereinstimmt.<\/p>\n<h2>Die VBA-Komponten oder: VBComponents<\/h2>\n<p>Die Auflistung <b>VBComponents <\/b>des <b>VBProject<\/b>-Objekts liefert alle <b>VBComponent<\/b>-Elemente des VBA-Projekts. Im folgenden Beispiel durchlaufen wir alle Elemente und lassen uns den Namen und den Typ ausgeben:<\/p>\n<pre>&lt;b&gt;Public Sub KomponentenDurchlaufen()\r\n&lt;b&gt;    Dim objVBProject<span style=\"color:blue;\"> As <\/span>VBIDE.VBProject\r\n&lt;b&gt;    Dim objVBComponent<span style=\"color:blue;\"> As <\/span>VBIDE.VBComponent\r\n&lt;b&gt;    <span style=\"color:blue;\">Set<\/span> objVBProject = VBE.ActiveVBProject\r\n&lt;b&gt;    For Each objVBComponent In objVBProject.VBComponents\r\n&lt;b&gt;       <span style=\"color:blue;\">Debug.Print<\/span> objVBComponent.Name, objVBComponent.Type\r\n&lt;b&gt;    <span style=\"color:blue;\">Next<\/span> objVBComponent\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die verschiedenen Typen k&ouml;nnen wir der Enumeration <b>vbext_ComponentType <\/b>entnehmen. Hier finden wir:<\/p>\n<ul>\n<li><b>11<\/b>: <b>vbext_ct_ActiveXDesigner<\/b><\/li>\n<li><b>2<\/b>: <b>vbext_ct_ClassModule<\/b><\/li>\n<li><b>100<\/b>: <b>vbext_ct_Document<\/b><\/li>\n<li><b>3<\/b>: <b>vbext_ct_MSForm<\/b><\/li>\n<li><b>1<\/b>: <b>vbext_ct_StdModule<\/b><\/li>\n<\/ul>\n<h2>Neue VB-Komponente anlegen<\/h2>\n<p>F&uuml;r das Bearbeiten von VBA-Projekten kann es hilfreich sein, neue Module anzulegen.<\/p>\n<p>Module sind <b>VBComponent<\/b>-Objekt, also nutzen wir dazu die Methode <b>Add <\/b>der <b>VBComponents<\/b>-Auflistung.<\/p>\n<p>Dieser &uuml;bergeben wir f&uuml;r ein neues Standardmodul den Wert <b>vbext_ct_StdModule <\/b>als Parameter und referenzieren das neue Modul mit der Variablen <b>objVBComponent<\/b>. Diesem geben wir anschlie&szlig;end direkt einen neuen Namen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>NeuesModul()\r\n     <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBIDE.VBComponent\r\n     <span style=\"color:blue;\">Set<\/span> objVBComponent = VBE.ActiveVBProject. _\r\n         VBComponents.Add(vbext_ct_StdModule)\r\n     objVBComponent.Name = \"mdlNeuesModul\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>W&uuml;rden wir beispielsweise ein Klassenmodul erstellen wollen, ginge das mit folgender Anpassung:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> objVBComponent = VBE.ActiveVBProject. _\r\n     VBComponents.Add(vbext_ct_ClassModule)\r\nobjVBComponent.Name = \"clsNeueKlasse\"<\/pre>\n<h2>Von der Komponente zum Modul<\/h2>\n<p>Mit dem neuen <b>VBComponent<\/b>-Objekt k&ouml;nnen wir noch nicht allzu viel anfangen, wenn wir seinen Code anpassen wollen. Dazu m&uuml;ssen wir das <b>CodeModule<\/b>-Objekt referenzieren, dass sich hinter der gleichnamigen Eigenschaft des <b>VBComponent<\/b>-Elements verbirgt.<\/p>\n<h2>CodeModule referenzieren<\/h2>\n<p>Es gibt allerdings verschiedene Wege, ein <b>CodeModule<\/b>-Element zu referenzieren. Der erste ist der Weg &uuml;ber das <b>VBComponent<\/b>-Element, in dem sich das Modul befindet. Wenn wir den Namen des <b>VBComponent<\/b>-Elements kennen, gelingt das beispielsweise wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MitModulArbeiten()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>VBIDE.CodeModule\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = VBE.ActiveVBProject. _\r\n         VBComponents(\"mdlNeuesModul\").CodeModule\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objCodeModule.Lines(1, 10)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Um zu pr&uuml;fen, ob wir das richtige <b>CodeModule<\/b>-Element<b> <\/b>referenziert haben, geben wir die mit der <b>Line<\/b>-Methode ermittelten ersten zehn Zeilen des Moduls im Direktbereich des VBA-Editors aus.<\/p>\n<p>Wenn wir wissen, dass das <b>VBComponent<\/b>-Element mit dem gew&uuml;nschten <b>CodeModule <\/b>aktiviert ist, k&ouml;nnen wir noch schneller darauf zugreifen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MitMarkiertemModulArbeiten()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>VBIDE.CodeModule\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = VBE.ActiveCodePane.CodeModule\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objCodeModule.Lines(1, 10)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier nutzen wir ein Objekt, das wir noch nicht vorgestellt haben, auf das wir aber &uuml;ber die Eigenschaft <b>ActiveCodePane <\/b>zugreifen k&ouml;nnen &#8211; das <b>CodePane<\/b>-Objekt. Auf dieses Objekt kommen wir gleich im Anschluss zu sprechen.<\/p>\n<p>Wichtig ist, dass dieses genau wie <b>VBComponent <\/b>ebenfalls die Eigenschaft <b>CodeModule<\/b> bietet, mit der wir auf das <b>CodeModule<\/b>-Element zugreifen k&ouml;nnen.<\/p>\n<h2>Mit dem Code arbeiten<\/h2>\n<p>Die <b>CodeModule<\/b>-Klasse bietet uns den Gro&szlig;teil der M&ouml;glichkeiten, um mit dem Code zu arbeiten &#8211; einige weitere finden wir noch im <b>CodePane<\/b>-Element.<\/p>\n<p>Wir schauen uns nun zun&auml;chst die M&ouml;glichkeiten von <b>CodeModule <\/b>an und kommen dann auf <b>CodePane <\/b>zu sprechen.<\/p>\n<ul>\n<li><b>AddFromFile<\/b>: F&uuml;gt den Inhalt der als Parameter angegebenen Textdatei hinten an den bestehenden Code des Moduls an.<\/li>\n<li><b>AddFromString<\/b>: F&uuml;gt den als Parameter angegebenen Inhalt hinten an den bestehenden Code des Moduls an.<\/li>\n<li><b>CodePane<\/b>: Verweist auf das <b>CodePane<\/b>-Objekt, das zu diesem <b>CodeModule<\/b>-Element geh&ouml;rt.<\/li>\n<li><b>CountOfDeclarationLines<\/b>: Liefert die Anzahl der Deklarationszeilen des Moduls.<\/li>\n<li><b>CountOfLines<\/b>: Liefert die gesamte Anzahl der Zeilen des Moduls.<\/li>\n<li><b>CreateEventProc<\/b>: Erstellt eine Ereignisprozedur und erwartet den Namen des Ereignisses und des Objekts, f&uuml;r das die Prozedur angelegt werden soll.<\/li>\n<li><b>DeleteLines<\/b>: L&ouml;scht die mit dem zweiten Parameter angegebene Anzahl Zeilen von der mit dem ersten Parameter angegebenen Startzeile aus. <\/li>\n<li><b>Find<\/b>: Sucht in einem bestimmten Bereich des Codes nach einem Text.<\/li>\n<li><b>InsertLines<\/b>: F&uuml;gt in der mit dem ersten Parameter angegebenen Zeile den Text aus dem zweiten Parameter ein.<\/li>\n<li><b>Lines<\/b>: Liefert die mit dem zweiten Parameter angegebene Anzahl Zeilen beginnend mit der Zeile aus dem ersten Parameter zur&uuml;ck.<\/li>\n<li><b>ProcBodyLine<\/b>: Liefert die Zeile zur&uuml;ck, in welcher der Body der angegebenen Prozedur beginnt. Der erste Parameter erwartet den Prozedurnamen, der zweite den Prozedurtyp.<\/li>\n<li><b>ProcCountLines<\/b>: Liefert die Anzahl der Zeilen der angegebenen Prozedur zur&uuml;ck.<\/li>\n<li><b>ProcOfLine<\/b>: Liefert die Prozedur zur&uuml;ck, in der sich die Zeile mit der im Parameter angegebenen Zeilennummer befindet.<\/li>\n<li><b>ProcStartLine<\/b>: Gibt die Nummer der ersten Zeile der angegebenen Prozedur zur&uuml;ck.<\/li>\n<li><b>ReplaceLine<\/b>: Ersetzt die Zeile mit der Zeilennummer aus dem ersten Parameter mit der im zweiten Parameter angegebenen Zeile.<\/li>\n<\/ul>\n<h2>Ausprobieren der Eigenschaften und Methoden der CodeModule-Klasse<\/h2>\n<p>Wenn wir die Eigenschaften und Methoden der <b>CodeModule<\/b>-Klasse ausprobieren wollen, ben&ouml;tigen wir optimalerweise immer ein neues, leeres Modul. Damit wir den gleichen Code zum Erstellen dieses Moduls nicht immer wieder in die Beispielprozeduren schreiben m&uuml;ssen, haben wir zu diesem Zweck eine Funktion erstellt (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>NeuesLeeresModul(strModulname<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>VBComponent\r\n     <span style=\"color:blue;\">Dim <\/span>objVBProject<span style=\"color:blue;\"> As <\/span>VBIDE.VBProject\r\n     <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBIDE.VBComponent\r\n     <span style=\"color:blue;\">Set<\/span> objVBProject = VBE.ActiveVBProject\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objVBComponent = objVBProject.VBComponents(strModulname)\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objVBComponent Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         objVBProject.VBComponents.Remove objVBComponent\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objVBComponent = objVBProject.VBComponents.Add(vbext_ct_StdModule)\r\n     objVBComponent.Name = strModulname\r\n     <span style=\"color:blue;\">Set<\/span> NeuesLeeresModul = objVBComponent\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Die Funktion NeuesLeeresModul<\/span><\/b><\/p>\n<p>Die Prozedur nimmt den Namen des zu erstellenden Moduls mit dem Parameter <b>strModulname <\/b>entgegen. Sie deklariert ein <b>VBProject<\/b>&#8211; und ein <b>VBComponent<\/b>-Element. Das <b>VBProject<\/b>-Element <b>objVBProject <\/b>f&uuml;llt es mit einem Veweis auf das aktuelle VBA-Projekt.<\/p>\n<p>Dann deaktiviert es die eingebaute Fehlerbehandlung, um das eventuell bereits vorhandene <b>VBComponent<\/b>-Element mit dem Namen aus <b>strModulname <\/b>zu referenzieren.<\/p>\n<p>Ist ein solches vorhanden, ist <b>objVBComponent <\/b>anschlie&szlig;end mit einem Verweis auf das entsprechende Objekt gef&uuml;llt. Dies pr&uuml;fen wir durch den Vergleich mit <b>Is Nothing<\/b>. Ist <b>objVBComponent <\/b>nicht leer, entfernen wir es mit der <b>Remove<\/b>-Methode aus der Auflistung <b>VBComponents <\/b>des aktuellen Projekts.<\/p>\n<p>Dann legen wir das Modul mit der <b>Add<\/b>-Methode der <b>VBComponents<\/b>-Auflistung erneut an und weisen diesem den Namen aus <b>strModulname <\/b>zu. Schlie&szlig;lich geben wir den Verweis auf dieses <b>VBComponent<\/b>-Element an die aufrufende Routine zur&uuml;ck.<\/p>\n<h2>Modul anlegen<\/h2>\n<p>Mit der oben vorgestellten Funktion <b>NeuesLeeresModul <\/b>k&ouml;nnen wir mit zwei Zeilen ein neues Modul erstellen und mit einer <b>CodeModule<\/b>-Variablen referenzieren:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_LeeresModul()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>VBIDE.CodeModule\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = _\r\n         NeuesLeeresModul(\"mdlTest\"). _\r\n         CodeModule\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das neue Modul wird anschlie&szlig;end direkt ge&ouml;ffnet (siehe Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_005.png\" alt=\"Erstellen eines neuen, leeren Moduls mit zwei Zeilen\" width=\"549.6265\" height=\"270.4651\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Erstellen eines neuen, leeren Moduls mit zwei Zeilen<\/span><\/b><\/p>\n<h2>Code aus einer Datei hinzuf&uuml;gen<\/h2>\n<p>Die <b>CodeModule<\/b>-Klasse bietet zwei M&ouml;glichkeiten, schnell Code einzuf&uuml;gen. Die erste ist die <b>AddFromFile<\/b>-Methode.<\/p>\n<p>Sie f&uuml;gt den Inhalt der als Parameter angegebenen Textdatei hinten an den bestehenden Code des Moduls an, f&uuml;r dessen <b>CodeModule<\/b>-Objekt die Methode aufgerufen wurde. Zu Testzwecken haben wir die einfache Textdatei aus Bild 5 erstellt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_004.png\" alt=\"Textdatei mit Beispielcode zum Einlesen\" width=\"424.6267\" height=\"235.4603\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Textdatei mit Beispielcode zum Einlesen<\/span><\/b><\/p>\n<p>Dann rufen wir die folgende Prozedur auf:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_AddFromFile()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>VBIDE.CodeModule\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = _\r\n         NeuesLeeresModul(\"mdlTest\").CodeModule\r\n     objCodeModule.AddFromFile _\r\n         CurrentProject.Path & \"\\code.txt\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis sehen wir in Bild 6. Der Text wird also einfach hinten angef&uuml;gt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_006.png\" alt=\"Modul mit eingef&uuml;gtem Code aus einer Textdatei\" width=\"424.6267\" height=\"213.6106\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Modul mit eingef&uuml;gtem Code aus einer Textdatei<\/span><\/b><\/p>\n<h2>Code aus einem Literal oder einer Variablen hinzuf&uuml;gen<\/h2>\n<p>Die zweite M&ouml;glichkeit, Code einfach hinten an den bestehenden Code eines Moduls anzuf&uuml;gen, ist die Methode <b>AddFromString<\/b>. Sie erwartet ein Literal oder eine Variable, deren Inhalt zum Modul hinzugef&uuml;gt wird. Im einfachsten Fall geben wir den hinzuzuf&uuml;genden Code als Parameter an:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_AddFromString()\r\n     ...\r\n     objCodeModule.AddFromString \"Dim strTest<span style=\"color:blue;\"> As String<\/span>\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wir k&ouml;nnen den Code zuvor auch in einer Variablen zusammenstellen (siehe Listing 2). Wichtig sind hier zwei Faktoren:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_AddFromString_Variable()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>VBIDE.CodeModule\r\n     <span style=\"color:blue;\">Dim <\/span>strCode<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = NeuesLeeresModul(\"mdlTest\").CodeModule\r\n     strCode = \"Dim strTest<span style=\"color:blue;\"> As String<\/span>\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Sub Test()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    strTest = \"\"Beispieltext\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    <span style=\"color:blue;\">MsgBox<\/span> strTest\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\"\r\n     objCodeModule.AddFromString strCode\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Hinzuf&uuml;gen von Code aus einer Variablen<\/span><\/b><\/p>\n<ul>\n<li>Wenn man wie im Beispiel den Code zeilenweise zur Variable <b>strCode <\/b>hinzuf&uuml;gt muss man hinten immer einen Zeilenumbruch anf&uuml;gen, in diesem Fall mit der Konstanten <b>vbCrLf <\/b>&#8211; was den Zeichen <b>Chr(13) &#038; Chr(10) <\/b>entspricht.<\/li>\n<li>Der hinzuzuf&uuml;gende Text wird in Anf&uuml;hrungszeichen gesetzt. Wenn dieser wiederum Anf&uuml;hrungszeichen enth&auml;lt, muss man diese verdoppeln, damit VBA nicht innerhalb der Zeichenkette vom Ende des Literals ausgeht.<\/li>\n<\/ul>\n<p>Das Beispiel liefert das gleiche Modul wie das vorherige.<\/p>\n<h2>Zeilen z&auml;hlen<\/h2>\n<p>Es gibt verschiedene Funktionen, mit denen wir die Zeilen innerhalb des Moduls z&auml;hlen k&ouml;nnen. Zwei stellen wir hier vor, eine weitere z&auml;hlt die Zeilen einer Prozedur &#8211; diese schauen wir uns weiter unten an.<\/p>\n<p>Die Funktion <b>CountOfDeclarationLines<\/b> liefert die Anzahl der Deklarationszeilen des Moduls. Was bedeutet das genau? Und was sind die Deklarationszeilen?<\/p>\n<p>Die Deklarationszeilen sind alle Zeilen, die sich vor der ersten <b>Sub<\/b>-, <b>Function<\/b>&#8211; oder <b>Property<\/b>-Prozedur befunden oder, wenn keine solche Prozedur vorhanden ist, sind es alle Zeilen. Dabei geh&ouml;ren leere Zeilen zwischen der letzten Deklarationszeile und der ersten Zeile einer Prozedur zu der jeweiligen Prozedur. <\/p>\n<p>Zu Demonstrationszwecken haben wir in Bild 7 Zeilennummern zum Modul hinzugef&uuml;gt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_007.png\" alt=\"Modul mit Zeilennummern\" width=\"499.6267\" height=\"255.1909\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Modul mit Zeilennummern<\/span><\/b><\/p>\n<p>Wenn wir f&uuml;r dieses Modul den Wert von <b>CountOfDeclarationLines <\/b>im Direktbereich ausgeben wollen, nutzen wir folgenden Code:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_CountOfDeclarationLines()\r\n     ...\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objCodeModule.CountOfDeclarationLines\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das liefert in diesem Fall den Wert <b>4<\/b>.<\/p>\n<p>In Bild 8 sehen wir ein Beispiel f&uuml;r ein Modul, das gar keine Prozeduren enth&auml;lt &#8211; daf&uuml;r aber eine auskommentierte Prozedur und einige folgende Leerzeilen. Welche Zeile markiert hier das Ende des Deklarationsbereichs? Die letzte Zeile des Moduls, die Zeichen enth&auml;lt. Das ist nicht die Zeile <b>9<\/b>, sondern die vorletzte Zeile &#8211; in diesem Fall die zw&ouml;lfte Zeile &#8211; denn diese enth&auml;lt noch den Zeilenumbruch (<b>vbCrLf<\/b>). Wir k&ouml;nnen die Einf&uuml;gemarke auch noch in eine 13. Zeile bewegen, die aber nicht mehr als Zeile gewertet wird, weil sie keine Zeichen enth&auml;lt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_008.png\" alt=\"Alternatives Beispiel f&uuml;r die Ermittlung der Deklarationszeilen\" width=\"424.6267\" height=\"282.1346\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Alternatives Beispiel f&uuml;r die Ermittlung der Deklarationszeilen<\/span><\/b><\/p>\n<h2>Alle Zeilen z&auml;hlen<\/h2>\n<p>Die zweite Funktion zum Z&auml;hlen von Zeilen liefert die Gesamtzahl der Zeilen eines Moduls. Dabei wird wieder die letzte Zeile ber&uuml;cksichtigt, die mindestens ein Zeichen enth&auml;lt &#8211; und sei es nur ein Zeilenumbruch. F&uuml;r das vorherige Beispiel liefert <b>CountOfLines <\/b>also ebenfalls den Wert <b>12 <\/b>als Ergebnis.<\/p>\n<h2>Ereignisprozedur erstellen<\/h2>\n<p>Die Methode <b>CreateEventProc<\/b> erstellt eine Ereignisprozedur und erwartet den Namen des Ereignisses und des Objekts, f&uuml;r das die Prozedur angelegt werden soll. Das Anlegen von Ereignisprozeduren ist nur in Klassenmodulen m&ouml;glich. Zu Beispielzwecken haben wir daher eine Klasse namens <b>clsTest<\/b> erstellt. Dieser wollen wir einfach ein Ereignis namens <b>Event <\/b>f&uuml;r das Objekt <b>Object <\/b>hinzuf&uuml;gen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_CreateEventProc()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>VBIDE.CodeModule\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = VBE.ActiveVBProject. _\r\n         VBComponents(\"clsTest\").CodeModule\r\n     objCodeModule.CreateEventProc \"Event\", \"Object\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Dies l&ouml;st allerdings den Fehler aus Bild 9 aus. Der Grund ist: Wir k&ouml;nnen mit dieser Methode nur Ereignisprozeduren erstellen, die wir auch durch die Auswahl der Elemente der beiden Kombinationsfelder des Codefensters erstellen k&ouml;nnen. Im Fall unseres ansonsten leeren Klassenmoduls finden wir dort nur das Objekt <b>Class <\/b>mit den Ereignissen <b>Initialize <\/b>und <b>Terminate <\/b>vor, von denen wir nun bereits die erste angelegt haben (siehe Bild 10).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_009.png\" alt=\"Fehler beim Erstellen einer Ereignisprozedur\" width=\"674.627\" height=\"392.7983\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Fehler beim Erstellen einer Ereignisprozedur<\/span><\/b><\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_010.png\" alt=\"Erstellen einer Ereignisprozedur per Codefenster\" width=\"549.6265\" height=\"175.3195\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Erstellen einer Ereignisprozedur per Codefenster<\/span><\/b><\/p>\n<p>Also versuchen wir nun, mit der Methode <b>CreateEventProc <\/b>die zweite Ereignisprozedur des <b>Class<\/b>-Elements anzulegen:<\/p>\n<pre>objCodeModule.CreateEventProc \"Terminate\", \"Class\"<\/pre>\n<p>Das gelingt auch ohne Fehlermeldung. Wir ben&ouml;tigen also die Kenntnis des Namens der Klasse oder der Objektvariablen und des Ereignisses.<\/p>\n<p>Ein sch&ouml;ner Vorteil dieser Vorgehensweise ist, dass wir uns um die Parameter der Ereignisprozeduren keine Gedanken machen m&uuml;ssen: Diese werden automatisch mit angelegt. Zu Beispielzwecken haben wir ein Access-Formular erstellt, dessen Klassenname <b>Form_frmTest <\/b>lautet. Mit der folgenden Prozedur haben wir das Ereignis <b>Open <\/b>des <b>Form<\/b>-Objekts angelegt, von dem wir wissen, dass es einen Parameter namens <b>Cancel <\/b>enth&auml;lt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_CreateEventProc_InFormular()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>VBIDE.CodeModule\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = VBE.ActiveVBProject. _\r\n         VBComponents(\"Form_frmTest\").CodeModule\r\n     objCodeModule.CreateEventProc \"Open\", \"Form\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis ist die vollst&auml;ndige Ereignisprozedur mit dem gew&uuml;nschten Parameter (siehe Bild 11).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_011.png\" alt=\"Eine Ereignisprozedur mit automatisch hinzugef&uuml;gtem Parameter\" width=\"424.6267\" height=\"198.5152\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Eine Ereignisprozedur mit automatisch hinzugef&uuml;gtem Parameter<\/span><\/b><\/p>\n<h2>Andere Prozeduren anlegen<\/h2>\n<p>Um &uuml;bliche <b>Sub<\/b>-, <b>Function<\/b>&#8211; oder <b>Property<\/b>-Prozeduren zu einem Modul hinzuzuf&uuml;gen, k&ouml;nnen wir die Methode <b>CreateEventProc <\/b>allerdings nicht nutzen. Diese k&ouml;nnen wir, wenn sie an das Ende des Moduls angeh&auml;ngt werden sollen, mit einer der Methoden <b>AddFromFile <\/b>oder <b>AddFromString <\/b>hinzuf&uuml;gen. Oder wir nutzen die weiter unten vorgestellte Methode <b>InsertLines<\/b>.<\/p>\n<h2>Informationen &uuml;ber Prozeduren ermitteln<\/h2>\n<p>Die <b>CodeModule<\/b>-Klasse offeriert einige M&ouml;glichkeiten, Informationen &uuml;ber <b>Sub<\/b>-, <b>Function<\/b>&#8211; oder <b>Property<\/b>-Prozeduren zu ermitteln. Diese werden in den n&auml;chsten Abschnitten vorgestellt.<\/p>\n<h2>Startzeile einer Prozedur ermitteln<\/h2>\n<p>Die Funktion <b>ProcBodyLine<\/b> liefert die Nummer der Zeile zur&uuml;ck, in welcher der Body der angegebenen Prozedur beginnt. Der erste Parameter erwartet den Prozedurnamen, der zweite den Prozedurtyp.<\/p>\n<p>Im folgenden Beispiel erstellen wir zuerst ein Beispielmodul (hier nicht abgebildet, siehe Beispieldateien) und geben dann die Startzeile der Prozedur <b>Test <\/b>mit dem Typ <b>vbext_pk_Proc <\/b>zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_ProcBodyLine()\r\n     ...\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objCodeModule.ProcBodyLine(\"Test\", _\r\n         vbext_pk_Proc)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Dies liefert die Nummer der Zeile, in der sich die erste Zeile der Prozedur befindet, also die Zeile mit dem <b>Sub<\/b>-, <b>Function <\/b>oder <b>Property<\/b>-Schl&uuml;sselwort.<\/p>\n<h2>Anzahl der Zeilen einer Prozedur ermitteln<\/h2>\n<p>Die Funktion <b>ProcCountLines<\/b> liefert die Anzahl der Zeilen der angegebenen Prozedur zur&uuml;ck. Genau wie die Funktion <b>ProcBodyLine <\/b>erwartet sie den Namen und den Typ der zu untersuchenden <b>Sub<\/b>-, <b>Function<\/b>&#8211; oder <b>Property<\/b>-Prozedur.<\/p>\n<p>Dabei ist wichtig, dass leere Zeilen oberhalb der Zeile mit dem Schl&uuml;sselwort <b>Sub<\/b>, <b>Function <\/b>oder <b>Property <\/b>noch zu der Prozedur hinzugez&auml;hlt werden. Das wird am Beispiel aus Bild 12 deutlich. &Uuml;ber der oberen Prozedur befindet sich eine Leerzeile, die mit zur Prozedur gez&auml;hlt wird. Diese hat dadurch f&uuml;nf Zeilen. Die untere Prozedur beginnt unmittelbar nach der oberen Prozedur und belegt somit nur vier Zeilen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_012.png\" alt=\"Z&auml;hlen der Zeilen von Prozeduren\" width=\"499.6267\" height=\"300.1633\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Z&auml;hlen der Zeilen von Prozeduren<\/span><\/b><\/p>\n<h2>Prozedur ermitteln, die sich in einer bestimmten Zeile befindet<\/h2>\n<p>Die Funktion <b>ProcOfLine<\/b> liefert den Namen sowie den Typ der Prozedur zur&uuml;ck, in der sich die Zeile mit der im Parameter angegebenen Zeilennummer befindet. F&uuml;r den Typ der Prozedur gibt es vier m&ouml;gliche Zahlenwerte, die jeweils einer Konstanten entsprechen und die folgende Bedeutung haben:<\/p>\n<ul>\n<li><b>0 <\/b>(<b>vbext_pk_Proc<\/b>): <b>Sub<\/b>&#8211; oder <b>Function<\/b>-Prozedur<\/li>\n<li><b>1 <\/b>(<b>vbext_pk_Let<\/b>): <b>Property Let<\/b>-Prozedur <\/li>\n<li><b>2 <\/b>(<b>vbext_pk_Set<\/b>): <b>Property Set<\/b>-Prozedur<\/li>\n<li><b>3 <\/b>(<b>vbext_pk_Get<\/b>): <b>Property Get<\/b>-Prozedur<\/li>\n<\/ul>\n<p>Die folgende Prozedur durchl&auml;uft in einer <b>For&#8230;Next<\/b>-Schleife alle Zeilen von der Zeile <b>1 <\/b>bis zu der mit <b>CountOfLines <\/b>ermittelten letzten Zeile des Moduls. F&uuml;r die jeweilige Zeile gibt die Prozedur die Zeilennummer, den Namen der Prozedur sowie den Typ der Prozedur als Zahl aus. Dabei wird der Typ zuerst mit <b>ProcOfLine <\/b>ermittelt und in <b>lngProcKind <\/b>geschrieben, bevor der Wert mit <b>lngProcKind <\/b>ausgegeben wird.<\/p>\n<p>Au&szlig;erdem stellen wir <b>lngProcKind <\/b>vorher jeweils auf <b>-1 <\/b>ein, damit f&uuml;r Deklarationszeilen, die zu keiner Prozedur geh&ouml;ren, dieser Wert ausgegeben wird:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_ProcOfLine()\r\n     ...\r\n     <span style=\"color:blue;\">Dim <\/span>lngLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngProcKind<span style=\"color:blue;\"> As <\/span>vbext_ProcKind\r\n     For lngLine = 1 To objCodeModule.CountOfLines\r\n         lngProcKind = -1\r\n         <span style=\"color:blue;\">Debug.Print<\/span> lngLine, objCodeModule.ProcOfLine( _\r\n             lngLine, lngProcKind), lngProcKind\r\n     <span style=\"color:blue;\">Next<\/span> lngLine\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis aus dem Direktbereich haben wir in Bild 13 neben den untersuchten Code gestellt. Analog zu den Ergebnissen der Funktion <b>ProcCountLines <\/b>erkennt <b>ProcOfLine <\/b>die richtige Prozedur f&uuml;r jede Zeile.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_013.png\" alt=\"Ausgabe des Namens der Prozedur und des Prozedurtyps der aktuellen Zeile mit ProcOfLine\" width=\"549.6265\" height=\"291.1346\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 13: Ausgabe des Namens der Prozedur und des Prozedurtyps der aktuellen Zeile mit ProcOfLine<\/span><\/b><\/p>\n<h2>Nummer der ersten Zeile einer Prozedur ermitteln<\/h2>\n<p>Die Funktion <b>ProcStartLine<\/b> gibt die Nummer der ersten Zeile der angegebenen Prozedur zur&uuml;ck. Auch dieser Funktion erwartet nicht nur den Namen der zu untersuchenden Prozedur, sondern auch ihren Typ.<\/p>\n<p>Die folgenden Anweisungen geben die Startzeilen der jeweiligen Prozeduren zur&uuml;ck, wobei jeweils die leeren Zeilen vor einer Prozedur als Teil der Prozedur interpretiert werden:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_ProcStartLine()\r\n     ...\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Test: \" & objCodeModule. _\r\n         ProcStartLine(\"Test\", vbext_pk_Proc)\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Test1: \" & objCodeModule. _\r\n         ProcStartLine(\"Test1\", vbext_pk_Get)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Mit Zeilen arbeiten<\/h2>\n<p>Die <b>CodeModule<\/b>-Klasse bietet verschiedene M&ouml;glichkeiten, direkt mit den Zeilen eines Moduls zu arbeiten. Diese schauen wir uns in den n&auml;chsten Abschnitten an.<\/p>\n<h2>Zeilen entfernen<\/h2>\n<p>Die Methode <b>DeleteLines<\/b> l&ouml;scht die mit dem zweiten Parameter angegebene Anzahl Zeilen ausgehend von der mit dem ersten Parameter angegebenen Startzeile.  Wenn wir zum Beispiel die vier in Bild 14 markierten Zeilen l&ouml;schen wollen, ben&ouml;tigen wir den folgenden Aufruf:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_014.png\" alt=\"Diese Zeilen werden gel&ouml;scht.\" width=\"424.6267\" height=\"280.9898\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 14: Diese Zeilen werden gel&ouml;scht.<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_DeleteLines()\r\n     ...\r\n     objCodeModule.DeleteLines 6, 4\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Zeilen einf&uuml;gen<\/h2>\n<p>Die Methode <b>InsertLines<\/b> f&uuml;gt in der mit dem ersten Parameter angegebenen Zeile den Text aus dem zweiten Parameter ein. <\/p>\n<p>Um in das in den vorherigen Beispielen verwendete Modul eine Prozedur zwischen den beiden vorhandenen Prozeduren einzuf&uuml;gen, tragen wir zuerst den einzuf&uuml;genden Code in eine Variable namens <b>strLines <\/b>ein. Dann nutzen wir die <b>InsertLines<\/b>-Methode, um ab der zehnten Zeile den Inhalt von <b>strLines <\/b>einzuf&uuml;gen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_InsertLines()\r\n     ...\r\n     <span style=\"color:blue;\">Dim <\/span>strLines<span style=\"color:blue;\"> As String<\/span>\r\n     strLines = \"Public Sub NochEinTest\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strLines = strLines & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strLines = strLines & \"End Sub\"\r\n     objCodeModule.InsertLines 10, strLines\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis sieht wie in Bild 15 aus. Wenn wir hier noch eine f&uuml;hrende und\/oder folgende Leerzeile einf&uuml;gen wollten, k&ouml;nnten wir das mit entsprechenden Platzierungen der Konstanten <b>vbCrLf <\/b>erledigen &#8211; beispielsweise so:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_015.png\" alt=\"Einf&uuml;gen von Code mit InsertLines\" width=\"599.6265\" height=\"318.7889\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 15: Einf&uuml;gen von Code mit InsertLines<\/span><\/b><\/p>\n<pre>  strLines = <span style=\"color:blue;\">vbCrLf<\/span>\r\n   strLines = strLines & \"Public Sub NochEinTest\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n   strLines = strLines & <span style=\"color:blue;\">vbCrLf<\/span>\r\n   strLines = strLines & \"End Sub\"\r\n   strLines = strLines & <span style=\"color:blue;\">vbCrLf<\/span><\/pre>\n<h2>Zeile ersetzen<\/h2>\n<p>In die gleiche Richtung geht die Methode <b>ReplaceLine<\/b>: Sie ersetzt allerdings die Zeile mit der Zeilennummer aus dem ersten Parameter mit der im zweiten Parameter angegebenen Text. W&auml;hrend bei der Methode <b>InsertLines <\/b>die als Parameter angegebene Zeile nach unten verschoben wird, wird diese bei <b>ReplaceLine <\/b>durch den eingef&uuml;gten Inhalt ersetzt.<\/p>\n<p>Das ist hilfreich, wenn man zum Beispiel alle Zeilen durchl&auml;uft, um diesen Zeilennummern hinzuzuf&uuml;gen. Dann w&uuml;rde man einfach die aktuelle Zeile durch den Inhalt der aktuellen Zeile mit einer vorangestellten Zeilennummer ersetzen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_ReplaceLine()\r\n     ...\r\n     <span style=\"color:blue;\">Dim <\/span>lngLine<span style=\"color:blue;\"> As Long<\/span>\r\n     For lngLine = 1 To objCodeModule.CountOfLines\r\n         objCodeModule.ReplaceLine lngLine, lngLine & _\r\n         vbTab & objCodeModule.Lines(lngLine, 1)\r\n     <span style=\"color:blue;\">Next<\/span> lngLine\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier haben wir bereits auf die Funktion <b>Lines <\/b>vorgegriffen, die den Inhalt der angegebenen Zeilen liefert, um die aktuelle Zeile, die mit einer Zeilennummer versehen werden soll, zu ermitteln. Dass dies nur ein unvollst&auml;ndiges Beispiel ist, sieht man am Ergebnis aus Bild 16. Es d&uuml;rfen nicht alle Zeilen mit Zeilennummern versehen werden, was wir hier ignoriert haben. Neben den markierten Zeilen d&uuml;rfen wir generell nur Zeilen innerhalb von Prozeduren mit Zeilennummern versehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_426_016.png\" alt=\"Einf&uuml;gen von Zeilennummern\" width=\"424.6267\" height=\"268.4897\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 16: Einf&uuml;gen von Zeilennummern<\/span><\/b><\/p>\n<h2>Zeilen einlesen<\/h2>\n<p>Damit kommen zur bereits verwendeten <b>Lines<\/b>-Funktion. Diese liefert die mit dem zweiten Parameter angegebene Anzahl Zeilen beginnend mit der Zeile aus dem ersten Parameter zur&uuml;ck.<\/p>\n<p>Wir k&ouml;nnen so den Inhalt beliebiger Zeilen einlesen. Dazu ben&ouml;tigen wir nur die Nummer der ersten einzulesenden Zeile und die Anzahl der Zeilen. <\/p>\n<h2>Nach Text suchen<\/h2>\n<p>Die letzte Funktion hei&szlig;t <b>Find<\/b> und sucht in einem bestimmten Bereich des Codes nach einem Text.<\/p>\n<p>Die <b>Find<\/b>-Funktion bietet eine ganze Reihe Parameter:<\/p>\n<ul>\n<li><b>Target<\/b>: Gesuchter Ausdruck<\/li>\n<li><b>StartLine<\/b>: Erste zu durchsuchende Zeile<\/li>\n<li><b>StartColumn<\/b>: Erstes zu durchsuchendes Zeichen der mit <b>StartLine <\/b>angegebenen Zeile<\/li>\n<li><b>EndLine<\/b>: Letzte zu durchsuchende Zeile<\/li>\n<li><b>EndColumn<\/b>: Letztes zu durchsuchendes Zeichen der mit <b>EndLine <\/b>angegebenen Zeile.<\/li>\n<li><b>WholeWord<\/b>: Gibt an, ob nur ganze Ausdr&uuml;cke gesucht werden sollen.<\/li>\n<li><b>MatchCase<\/b>: Gibt an, ob Gro&szlig;-\/Kleinschreibung ber&uuml;cksichtigt werden soll.<\/li>\n<li><b>PatternSearch<\/b>: Gibt an, ob * und ? als Platzhalter f&uuml;r beliebig viele oder ein beliebiges Zeichen verwendet werden sollen.<\/li>\n<\/ul>\n<p>&Uuml;ber die <b>Find<\/b>-Methode und ihre Einsatzm&ouml;glichkeiten k&ouml;nnte man einen ganzen Artikel schreiben (vielleicht tun wir das). Ein kleines Beispiel haben wir jedoch vorbereitet. Die Prozedur aus Listing 3 zeigt, wie wir die Position aller Vorkommen des Textes <b>Test<\/b> ermitteln und im Direktbereich ausgeben k&ouml;nnen.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CodeModule_Find()\r\n     ...\r\n     <span style=\"color:blue;\">Dim <\/span>lngStartLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngStartColumn<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngEndLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngEndColumn<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolFound<span style=\"color:blue;\"> As Boolean<\/span>\r\n     bolFound = objCodeModule.Find(\"Test\", lngStartLine, lngStartColumn, lngEndLine, lngEndColumn)\r\n     <span style=\"color:blue;\">Do While<\/span> bolFound = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> lngStartLine, lngStartColumn, lngEndLine, lngEndColumn\r\n         lngStartColumn = lngStartColumn + 1\r\n         lngEndColumn = 0\r\n         lngEndLine = 0\r\n         bolFound = objCodeModule.Find(\"Test\", lngStartLine, lngStartColumn, lngEndLine, lngEndColumn)\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Suchen nach einem bestimmten Ausdruck<\/span><\/b><\/p>\n<p>Dazu deklarieren wir <b>Long<\/b>-Variablen f&uuml;r die Position und rufen zun&auml;chst einmalig die <b>Find<\/b>-Methode mit dem Suchbegriff und den Variablen f&uuml;r die Position auf. Liefert der Aufruf den Wert <b>True<\/b>, haben wir eine Fundstelle und k&ouml;nnen diese mit den Werten der Variablen <b>lngStartLine<\/b>, <b>lngStartColumn<\/b>, <b>lngEndLine <\/b>und <b>lngEndColumn <\/b>identifizieren. Ist das der Fall, steigen wir in eine <b>Do While<\/b>-Schleife ein, in der wir die Position der Fundstelle ausgeben.<\/p>\n<p>Dann stellen wir die Startposition mit <b>lngStartColumn <\/b>auf das Zeichen nach der Fundstelle, damit wir nicht nochmal das gleiche Ergebnis erhalten, wenn wir anschlie&szlig;end nochmals die <b>Find<\/b>-Funktion aufrufen. Damit durchlaufen wir alle Fundstellen und geben diese aus. Wird keine weitere Fundstelle entdeckt, liefert <b>Find <\/b>den Wert <b>False <\/b>und die Schleife wird verlassen.<\/p>\n<h2>CodePane-Objekt nutzen<\/h2>\n<p>Das <b>CodeModule<\/b>-Objekt liefert bereits alle Eigenschaften und Methoden, um den Code zu durchsuchen, zu analysieren und anzupassen.<\/p>\n<p>Es fehlen jedoch noch ein paar Werkzeuge, um diese Funktionen sinnvoll f&uuml;r den Benutzer der Entwicklungsumgebung bereitzustellen.<\/p>\n<p>In vielen F&auml;llen d&uuml;rfte es n&auml;mlich so sein, dass der Benutzer ein Element im Code markiert und auf diesem eine bestimmte Aktion ausf&uuml;hren m&ouml;chte &#8211; beispielsweise eine &ouml;ffentliche Variable in einer Klasse durch eine privat deklarierte Membervariable mit <b>Get<\/b>&#8211; und <b>Let<\/b>\/<b>Set<\/b>-Prozeduren zu ersetzen. Dann w&uuml;rde er die entsprechende Variable markieren und dann beispielsweise einen Befehl aus dem Men&uuml; oder Kontextmen&uuml; aufrufen, um diese &Auml;nderung durchzuf&uuml;hren.<\/p>\n<p>Wir m&uuml;ssten dann ermitteln, welchen Bereich des VBA-Editors der Benutzer markiert hat.<\/p>\n<p>Andersherum kann es sein, dass wir selbst eine Markierung im Code setzen wollen &#8211; beispielsweise um eine Fundstelle bei einer benutzerdefinierten Suchfunktion zu markieren.<\/p>\n<p>Beides l&auml;sst sich mit den Methoden des <b>CodePane<\/b>-Objekts realisieren, die wir mit der Eigenschaft <b>CodePane <\/b>der <b>CodeModule<\/b>-Klasse referenzieren k&ouml;nnen.<\/p>\n<p>Das <b>CodePane<\/b>-Objekt liefert die folgenden Elemente:<\/p>\n<ul>\n<li><b>CodeModule<\/b>: Verweis auf das zugeh&ouml;rige <b>CodeModule<\/b>-Objekt<\/li>\n<li><b>CodePaneView<\/b>: Ansicht des CodePanes. Liefert den Wert der Eigenschaft <b>Standardm&auml;&szlig;ig ganzes Modul anzeigen <\/b>aus den Optionen des VBA-Editors.<\/li>\n<li><b>Collection<\/b>: Auflistung aller ge&ouml;ffneten <b>CodePane<\/b>-Objekte<\/li>\n<li><b>CountOfVisibleLines<\/b>: Anzahl der sichtbaren Zeilen im Fenster<\/li>\n<li><b>GetSelection<\/b>: Liefert die Position der aktuellen Markierung.<\/li>\n<li><b>SetSelection<\/b>: Setzt die aktuelle Position.<\/li>\n<li><b>Show<\/b>: Aktiviert das <b>CodePane<\/b>-Element, f&uuml;r das diese Methode aufgerufen wurde.<\/li>\n<li><b>TopLine<\/b>: Gibt die Zeilennummer der obersten Zeile aus, die im Codefenster angezeigt wird.<\/li>\n<li><b>Window<\/b>: Verweis auf das &uuml;bergeordnete <b>Window<\/b>-Objekt.<\/li>\n<\/ul>\n<h2>Position der Markierung ermitteln<\/h2>\n<p>Die folgende Prozedur zeigt, wir die aktuelle Markierung im <b>CodePane<\/b>-Element ermitteln k&ouml;nnen. Dazu deklarieren wir vier <b>Long<\/b>-Variablen, die wir der Methode <b>GetSelection <\/b>als Parameter &uuml;bergeben. Durch den Aufruf werden diese gef&uuml;llt und anschlie&szlig;end im Direktbereich ausgegeben:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MarkierungAuslesen()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodePane<span style=\"color:blue;\"> As <\/span>VBIDE.CodePane\r\n     <span style=\"color:blue;\">Dim <\/span>lngStartLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngStartColumn<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngEndLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngEndColumn<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCodePane = VBE.ActiveCodePane\r\n     objCodePane.GetSelection lngStartLine, _\r\n         lngStartColumn, lngEndLine, lngEndColumn\r\n     <span style=\"color:blue;\">Debug.Print<\/span> lngStartLine, lngStartColumn, _\r\n         lngEndLine, lngEndColumn\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Position der Markierung setzen<\/h2>\n<p>Mit dem Befehl <b>SetSelection <\/b>k&ouml;nnen wir den markierten Bereich nach unseren W&uuml;nschen einstellen. Auch diese Methode erwartet die vier <b>Long<\/b>-Parameter f&uuml;r die Position der Markierung. Im folgenden Beispiel stellen wir den Start der Markierung auf das erste Zeichen der ersten Zeile ein und f&uuml;r das Ende der Markierung verwenden wir sehr gro&szlig;e Werte, damit das komplette Modul markiert wird:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MarkierungSetzen()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodePane<span style=\"color:blue;\"> As <\/span>VBIDE.CodePane\r\n     <span style=\"color:blue;\">Dim <\/span>lngStartLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngStartColumn<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngEndLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngEndColumn<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCodePane = VBE.ActiveCodePane\r\n     lngStartLine = 1\r\n     lngStartColumn = 1\r\n     lngEndLine = 65536\r\n     lngEndColumn = 65536\r\n     objCodePane.SetSelection lngStartLine, _\r\n         lngStartColumn, lngEndLine, lngEndColumn\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Die VBIDE-Klasse enth&auml;lt noch einige weitere Elemente, die aber nicht unbedingt f&uuml;r die Quellcode-Bearbeitung notwendig sind (<b>AddIn<\/b>, <b>AddIns<\/b>, <b>CommandBarEvents<\/b>, <b>Events<\/b>, <b>LinkedWindows<\/b>, <b>Properties<\/b>, <b>Property<\/b>, <b>Reference<\/b>, <b>References <\/b>und <b>ReferencesEvents<\/b>). Deshalb haben wir in diesem Artikel erst einmal alle Elemente vorgestellt, die direkt f&uuml;r die Quellcode-Bearbeitung notwendig sind. Wir k&ouml;nnen damit nun neue Module anlegen, vorhandene Module entfernen oder umbenennen, VBA-Code zu den Modulen hinzuf&uuml;gen, entfernen, ersetzen, suchen et cetera.<\/p>\n<p>Ich habe selbst schon recht viel mit dieser Bibliothek gearbeitet und immer wieder gedacht, dass man bestimmte Aufgaben nicht mit den wenigen Befehlen l&ouml;sen kann, aber letztlich habe ich immer noch einen Weg gefunden, die Methoden und Eigenschaften so zu kombinieren, dass ich mein Ziel erreicht habe.<\/p>\n<p>In weiteren Artikel schauen wir uns an, wie wir diese Methoden sinnvoll einsetzen k&ouml;nnen und wie wir diese im VBA-Editor der verschiedenen Office-Anwendungen bereitstellen k&ouml;nnen. Eine M&ouml;glichkeit ist die Programmierung eines COM-Add-Ins f&uuml;r den VBA-Editor, wie wir es in <b>twinBASIC: COM-Add-In f&uuml;r den VBA-Editor <\/b>(<b>www.vbentwickler.de\/421<\/b>) beschreiben.<\/p>\n<p>Ein erstes praktisches Beispiel findest Du im Artikel <b>VBA-Editor: Klasseneigenschaften per Mausklick <\/b>(<b>www.vbentwickler.de\/422<\/b>). Hier zeigen wir grunds&auml;tzlich, wie wir schnell &ouml;ffentliche Variablen in Klassen in private Member-Variablen plus <b>Get<\/b>&#8211; und <b>Set<\/b>\/<b>Let<\/b>-Prozeduren umwandeln k&ouml;nnen. Diese Funktion betten wir dann sp&auml;ter in ein COM-Add-In ein.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>VBEProgrammieren.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/5B17E8CE-4259-4187-BC00-5184DF37A932\/vbe_426.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Der VBA-Editor ist die Gemeinsamkeit der Office-Anwendungen wie Access, Excel, Outlook, PowerPoint und Word. Wer eine oder mehrere dieser Anwendungen programmiert, um dem Benutzer die Arbeit damit zu erleichtern, kennt sich mehr oder weniger mit VBA aus. In der Regel wird im Arbeitsalltag eines Entwicklers jede Codezeile von Hand neu programmiert. Gegebenenfalls kopiert man bestehenden Code und passt diesen an den jeweiligen Anwendungszweck an. Aber warum nicht einen Schritt weitergehen und VBA-Code zur Erstellung von VBA-Code selbst nutzen? Visual Basic bietet eigens zum Zweck der Programmierung der Elemente und des Codes im VBA-Editor eine eigene Bibliothek namens Microsoft Visual Basic for Applications Extensibility 5.3. Welche M&ouml;glichkeiten diese allgemein bietet und welche Elemente, Eigenschaften und Methoden sie bereitstellt, schauen wir uns in diesem Artikel an.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66022024,662024,44000037],"tags":[],"yst_prominent_words":[],"class_list":["post-55000426","post","type-post","status-publish","format-standard","hentry","category-66022024","category-662024","category-VBAEditor_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000426","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000426"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000426\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000426"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000426"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000426"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000426"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}