{"id":55000422,"date":"2024-06-01T00:00:00","date_gmt":"2024-08-09T09:55:57","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=422"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"VBAEditor_Klasseneigenschaften_per_Mausklick","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/VBAEditor_Klasseneigenschaften_per_Mausklick\/","title":{"rendered":"VBA-Editor: Klasseneigenschaften per Mausklick"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/ebe7ec9118ee4a15b92bf91fb661b7ff\" width=\"1\" height=\"1\" alt=\"\"><b>Wenn wir im VBA-Editor benutzerdefinierte Klassen programmieren wollen, verwenden wir f&uuml;r Eigenschaften &uuml;blicherweise eine private Variable, die wir &uuml;ber eine &ouml;ffentliche Property Set\/Let-Prozedur mit einem Wert f&uuml;llen und mit einer Property Get-Prozedur auslesen k&ouml;nnen. Das sind mindestens sieben Zeilen je Eigenschaft, was jede Menge Tipparbeit und Aufwand bedeutet und au&szlig;erdem noch fehleranf&auml;llig ist. Selbst Copy und Paste macht diese Aufgabe nicht wesentlich angenehmer. Wohl dem, der wei&szlig;, wie er den VBA-Editor programmiert, sodass er solche Aufgaben mit wenigen Mausklicks automatisieren kann. Hier gibt es verschiedene Ans&auml;tze, die wir uns in diesem Artikel ansehen und auch umsetzen.<\/b><\/p>\n<p>Die Programmierung von Office-Anwendungen mit VBA ist die eine Aufgabe. Diese wird &uuml;blicherweise durch die Anforderungen des Kunden oder des Benutzers gesteuert und einfach Schritt f&uuml;r Schritt abgearbeitet. Als Entwickler sollten wir jedoch immer darauf bedacht sein, Abk&uuml;rzungen bei der Arbeit zu suchen, um schneller und zuverl&auml;ssiger ans Ziel zu kommen.<\/p>\n<p>Das gelingt unter Office anwendungs&uuml;bergreifend im Bereich der VBA-Programmierung. Wir k&ouml;nnen uns auch die eine oder andere Prozedur bauen, um Aufgaben in Access, Excel, Outlook, PowerPoint oder Word zu automatisieren. Schlie&szlig;lich gibt es in einigen dieser Anwendungen dazu extra den Makro-Rekorder.<\/p>\n<p>Unter VBA ist das jedoch noch ein wenig spannender, denn hier k&ouml;nnen wir f&uuml;r alle Office-Anwendungen gleicherma&szlig;en Vereinfachungen programmieren. Und so machen wir uns auch gleich ans Werk und schauen uns an, welche M&ouml;glichkeiten wir hier so haben.<\/p>\n<h2>Ziel: Private Member-Variable plus Get\/Set\/Let-Prozedur<\/h2>\n<p>Aber von welchen verschiedenen Ans&auml;tzen haben wir in der Einleitung gesprochen? Nun, es gibt verschiedene Ausgangssituationen. Wir schauen uns zuerst einmal an, was wir &uuml;berhaupt haben wollen. F&uuml;r eine vollwertige Eigenschaft, deren Wert gelesen und gesetzt werden kann, ben&ouml;tigen wir als Erstes eine private Member-Variable, die wir beispielsweise wie folgt deklarieren:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Firma<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Damit wir von au&szlig;en auf diese Variable zugreifen k&ouml;nnen, um ihren Wert einzustellen, nutzen wir eine &ouml;ffentliche <b>Property Let<\/b>-Prozedur:<\/p>\n<pre><span style=\"color:blue;\">Public Property Get <\/span>Firma()<span style=\"color:blue;\"> As String<\/span>\r\n     Firma = m_Firma\r\n<span style=\"color:blue;\">End Property<\/span> <\/pre>\n<p>Schlie&szlig;lich wollen wir eine Eigenschaft auch von au&szlig;en setzen k&ouml;nnen, also f&uuml;gen wir noch eine entsprechende <b>Property Let<\/b>-Prozedur hinzu:<\/p>\n<pre><span style=\"color:blue;\">Public Property Let <\/span>Firma(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Firma = str\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Und wenn unsere Eigenschaft keine skalare Variable aufnimmt (also zum Beispiel <b>Long <\/b>oder <b>String<\/b>), sondern einen Objektverweis, m&uuml;ssen wir die Schreibweise ein wenig anpassen. Die Variable deklarieren wir dann etwa so:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Recordset<span style=\"color:blue;\"> As <\/span>DAO.Recordset<\/pre>\n<p>Auch in der <b>Get<\/b>-Prozedur ben&ouml;tigen wir eine &Auml;nderung, denn f&uuml;r die Zuweisung von Objektverweisen ist das Schl&uuml;sselwort <b>Set <\/b>n&ouml;tig:<\/p>\n<pre><span style=\"color:blue;\">Public Property Get <\/span>Recordset()<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> Recordset = m_Recordset\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Dieses Schl&uuml;sselwort ben&ouml;tigen wir auch beim Setzen des Objektverweises. Au&szlig;erdem verwenden wir hier keine <b>Property Let<\/b>-Prozedur, sondern eine <b>Property Set<\/b>-Prozedur:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Recordset(rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset)\r\n     <span style=\"color:blue;\">Set<\/span> m_Recordset = rst\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Die n&auml;chste Vorgabe ist, dass die <b>Property Let<\/b>\/<b>Set<\/b>\/<b>Get<\/b>-Prozeduren im Modul fr&uuml;hestens nach der letzten Deklarationszeile hinzugef&uuml;gt werden darf. Nach der ersten Prozedur darf keine alleinstehende Deklarationszeile mehr folgen.<\/p>\n<h2>Prozedur zum Ersetzen von &ouml;ffentlichen Eigenschaften durch Get\/Let\/Set-Property<\/h2>\n<p>Wir k&ouml;nnen mit den Methoden der Bibliothek <b>Microsoft Visual Basic for Applications 5.3 Object Library <\/b>auf die Elemente des VBA-Editors zugreifen und diese manipulieren. Dies nutzen wir in diesem Falle, um die gew&uuml;nschten &Auml;nderungen in einem Klassenmodul vorzunehmen. Den ben&ouml;tigten Verweis auf diese Bibliothek setzen wir auf gewohnte Weise &uuml;ber den <b>Verweise<\/b>-Dialog.<\/p>\n<p>Dann f&uuml;gen wir die Prozedur <b>VariableToProperty <\/b>zu einem Standardmodul hinzu (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>VariableToProperty()\r\n     <span style=\"color:blue;\">Dim <\/span>objCodePane<span style=\"color:blue;\"> As <\/span>CodePane, objCodeModule<span style=\"color:blue;\"> As <\/span>CodeModule\r\n     <span style=\"color:blue;\">Dim <\/span>lngStartline<span style=\"color:blue;\"> As Long<\/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>, lngEndcolumn<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngLine<span style=\"color:blue;\"> As Long<\/span>, strLine<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strVariable<span style=\"color:blue;\"> As String<\/span>, strDatatype<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strVariables<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strProperties<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strPrefix<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCodePane = VBE.ActiveCodePane\r\n     objCodePane.GetSelection lngStartline, lngStartcolumn, lngEndline, lngEndcolumn\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = objCodePane.CodeModule\r\n     For lngLine = lngStartline To lngEndline\r\n         strLine = <span style=\"color:blue;\">Trim<\/span>(objCodeModule.Lines(lngLine, 1))\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strLine) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             strVariable = <span style=\"color:blue;\">Split<\/span>(strLine, \" \")(1)\r\n             strDatatype = <span style=\"color:blue;\">Split<\/span>(strLine, \" \")(3)\r\n             strPrefix = GetPrefix(strDatatype)\r\n             strVariables = strVariables & \"Private m_\" & strVariable & \"<span style=\"color:blue;\"> As <\/span>\" & strDatatype & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             Select Case strPrefix\r\n                 <span style=\"color:blue;\">Case <\/span>\"obj\"\r\n                     strProperties = strProperties & \"Public Property <span style=\"color:blue;\">Set<\/span> \" & strVariable & \"(\" & strPrefix & \"<span style=\"color:blue;\"> As <\/span>\" _\r\n                         & strDatatype & \")\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n                     strProperties = strProperties & \"    <span style=\"color:blue;\">Set<\/span> m_\" & strVariable & \" = \" & strPrefix & <span style=\"color:blue;\">vbCrLf<\/span>\r\n                 <span style=\"color:blue;\">Case Else<\/span>\r\n                     strProperties = strProperties & \"Public Property Let \" & strVariable & \"(\" & strPrefix & \"<span style=\"color:blue;\"> As <\/span>\" _\r\n                         & strDatatype & \")\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n                     strProperties = strProperties & \"    m_\" & strVariable & \" = \" & strPrefix & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n             strProperties = strProperties & \"End Property\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             strProperties = strProperties & \"Public Property Get \" & strVariable & \"<span style=\"color:blue;\"> As <\/span>\" & strDatatype & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             Select Case strPrefix\r\n                 <span style=\"color:blue;\">Case <\/span>\"obj\"\r\n                     strProperties = strProperties & \"    <span style=\"color:blue;\">Set<\/span> \" & strVariable & \" = m_\" & strVariable & <span style=\"color:blue;\">vbCrLf<\/span>\r\n                 <span style=\"color:blue;\">Case Else<\/span>\r\n                     strProperties = strProperties & \"    \" & strVariable & \" = m_\" & strVariable & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n             strProperties = strProperties & \"End Property \" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> lngLine\r\n     strVariables = strVariables & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     objCodeModule.DeleteLines lngStartline, lngEndline - lngStartline + 1\r\n     lngStartline = objCodeModule.CountOfDeclarationLines + 1\r\n     objCodeModule.InsertLines lngStartline, strVariables & strProperties\r\n     <span style=\"color:blue;\">Call<\/span> RemoveTripeCrLf(objCodeModule)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Prozedur zum Erstellen von Property Get\/Let\/Set-Prozeduren f&uuml;r Variablen<\/span><\/b><\/p>\n<p>Diese Prozedur deklariert zun&auml;chst einige Variablen und stellt dann die Variable <b>objCodePane <\/b>mit der Funktion <b>ActiveCodePane <\/b>auf das aktuelle <b>CodePane<\/b>-Objekt ein, was dem aktuellen Codefenster entspricht.<\/p>\n<p>Wir gehen davon aus, dass der Benutzer eine oder mehrere Zeilen mit &ouml;ffentlichen Variablen markiert hat und dass die Prozedur diese alle in private Variablen umwandeln soll, die &uuml;ber eine <b>Get Property <\/b>verf&uuml;gbar gemacht und mit <b>Set<\/b>\/<b>Let Property <\/b>gesetzt werden k&ouml;nnen sollen.<\/p>\n<p>Davon ausgehend erfassen wir die aktuelle Markierung im Codefenster mit der <b>GetSelection<\/b>-Funktion des <b>CodePane<\/b>-Objekts. Diese liefert uns f&uuml;r die Variablen <b>lngStartline<\/b>, <b>lngStartcolumn<\/b>, <b>lngEndline <\/b>und <b>lngEndcolumn <\/b>die Koordinaten der aktuellen Markierung.<\/p>\n<p>Damit ausgestattet durchlaufen wir die erste Zeile der Markierung (<b>lngStartline<\/b>) bis zur letzten Zeile (<b>lngEndline<\/b>) in einer <b>For&#8230;Next<\/b>-Schleife mit <b>lngLine <\/b>als Laufvariable.<\/p>\n<p>Darin lesen wir die aktuelle Zeile in die Variable <b>strLine <\/b>ein und entfernen mit der <b>Trim<\/b>-Funktion direkt f&uuml;hrende und folgende Leerzeichen.<\/p>\n<p>Wenn <b>strLine<\/b> nun keine leere Zeichenkette ist, teilen wir die Zeile mit der <b>Split<\/b>-Funktion an den Leerzeichen auf und ermitteln das zweite und das vierte Element (mit den Indexwerten <b>1 <\/b>und <b>3 <\/b>wegen des <b>0<\/b>-basierten Indexes dieser Funktion). Wir gehen von einer Zeile wie der folgenden aus:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Field<span style=\"color:blue;\"> As <\/span>DAO.Field<\/pre>\n<p>Dann landet der Variablenname <b>Field <\/b>in der Variablen <b>strVariable <\/b>und <b>DAO.Field <\/b>landet in <b>strDatatype<\/b>.<\/p>\n<p>Bevor wir beginnen, den notwendigen Code zusammenzustellen, wollen wir noch den Datentyp der Variablen ermitteln und das daf&uuml;r vorgesehene Pr&auml;fix ermitteln. Das erledigen wir mit einem Aufruf der Funktion <b>GetPrefix<\/b>, die uns f&uuml;r den jeweiligen Datentyp das aus drei Buchstaben bestehenden Pr&auml;fix liefert. Hier werden die Basisdatentypen wie <b>Boolean<\/b>, <b>Integer <\/b>oder <b>String <\/b>separat behandelt.<\/p>\n<p>F&uuml;r alle anderen Datentypen wird als Pr&auml;fix <b>obj <\/b>angenommen. Ob wir es hier mit einem <b>Object <\/b>zu tun haben oder mit einem anderen Datentyp, wirkt sich auch darauf aus, ob wir eine <b>Property Set <\/b>(f&uuml;r Objekte) oder <b>Property Let <\/b>(f&uuml;r einfache Basistypen) anlegen m&uuml;ssen. Die Funktion <b>GetPrefix <\/b>sieht wie folgt aus und sie kann nach Bedarf erweitert werden:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetPrefix(strDatatype<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     Select Case strDatatype\r\n         <span style=\"color:blue;\">Case <\/span>\"Boolean\"\r\n             GetPrefix = \"bol\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Byte\"\r\n             GetPrefix = \"byt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Currency\"\r\n             GetPrefix = \"cur\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Date\"\r\n             GetPrefix = \"dat\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Decimal\"\r\n             GetPrefix = \"dec\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Double\"\r\n             GetPrefix = \"dbl\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Integer\"\r\n             GetPrefix = \"int\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Long\"\r\n             GetPrefix = \"lng\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Single\"\r\n             GetPrefix = \"sng\"\r\n         <span style=\"color:blue;\">Case <\/span>\"String\"\r\n             GetPrefix = \"str\"\r\n         <span style=\"color:blue;\">Case <\/span>\"Variant\"\r\n             GetPrefix = \"var\"\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             GetPrefix = \"obj\"\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Zur&uuml;ck zur Prozedur <b>VariableToProperty<\/b>. Diese speichert das Pr&auml;fix in der Variablen <b>strPrefix<\/b>. Dann f&uuml;gt sie der Variablen <b>strVariables <\/b>eine Zeichenkette hinzu die aus <b>Privat m_<\/b>, dem Variablennamen, <b>As<\/b>, dem Datentyp und einem Zeilenumbruch besteht, in unserem Fall also beispielsweise:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Field<span style=\"color:blue;\"> As <\/span>DAO.Field<\/pre>\n<p>Dass wir hier den Wert nicht einfach der Variablen <b>strVariables <\/b>zuweisen, sondern an diese anh&auml;ngen, h&auml;ngt damit zusammen, dass wir gegebenenfalls auch mehrere Variablen umwandeln wollen. Deshalb sammeln wir in <b>strVariables<\/b> alle Zeilen mit den Deklarationen der nun als privat deklarierten Variablen.<\/p>\n<p>Danach pr&uuml;ft die Prozedur in einer <b>Select Case<\/b>-Bedingung, ob es sich bei dem Pr&auml;fix um den Wert <b>obj <\/b>handelt oder um einen anderen Wert. Im Falle von <b>obj <\/b>setzt diese die Kopfzeile der <b>Property<\/b>-Prozedur mit dem Schl&uuml;sselwort <b>Property Set <\/b>zusammen, zum Beispiel so:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Field(obj<span style=\"color:blue;\"> As <\/span>DAO.Field)<\/pre>\n<p>Anderenfalls wird das Schl&uuml;sselwort <b>Let<\/b> verwendet, zum Beispiel so:<\/p>\n<pre><span style=\"color:blue;\">Public Property Let <\/span>Text(str<span style=\"color:blue;\"> As String<\/span>)<\/pre>\n<p>Falls weitere Unterscheidungen gew&uuml;nscht sind und individuelle Pr&auml;fixe vergeben werden sollen, kann man diese in zus&auml;tzlichen <b>Case<\/b>-Zweigen unterbringen. Diese Kopfzeile wird hinten an die Variable <b>strProperties <\/b>angeh&auml;ngt.<\/p>\n<p>Innerhalb der Schleife folgt auch noch die einzige Anweisung dieser <b>Property Let<\/b>\/<b>Set<\/b>-Prozedur, die zusammengestellt wird aus <b>Set m_<\/b>, dem Variablennamen aus <b>strVariable<\/b>, dem Gleichheitszeichen und dem Pr&auml;fix.<\/p>\n<p>F&uuml;r die Basisdatentypen wird die Anweisung auf die gleiche Weise zusammengestellt, allerdings kommt hier kein <b>Set<\/b>-Schl&uuml;sselwort zum Einsatz. Schlie&szlig;lich folgt in der folgenden Anweisung noch die Fu&szlig;zeile, die f&uuml;r alle Eigenschaften <b>End Property <\/b>lautet.<\/p>\n<p>Dann stellt die Prozedur die <b>Property Get<\/b>-Prozedur zusammen, die wieder f&uuml;r Basisdatentypen und Objektdatentypen einen Unterschied bereith&auml;lt. F&uuml;r Basisdatentypen sieht sie beispielsweise wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Property Get <\/span>Field()<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     Field = m_Field\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>F&uuml;r Objektdatentypen m&uuml;ssen wir noch das Set-Schl&uuml;sselwort hinzuf&uuml;gen:<\/p>\n<pre>    <span style=\"color:blue;\">Set<\/span> Field = m_Field<\/pre>\n<p>Auf diese Weise werden in der Variablen <b>strVariables <\/b>die Variablen zusammengestellt und in der Variablen <b>strProperties <\/b>die <b>Property<\/b>-Prozeduren. Den Variablen wird noch ein Zeilenumbruch hinzugef&uuml;gt. Danach l&ouml;scht die Prozedur die bisher verwendete Deklaration der Variablen mit der <b>DeleteLines<\/b>-Methode f&uuml;r die zuvor mit <b>lngStartline <\/b>und <b>lngEndline <\/b>ermittelten Zeilen.<\/p>\n<p>Schlie&szlig;lich ermittelt die Prozedur einen neuen Wert f&uuml;r <b>lngStartline<\/b>, n&auml;mlich die erste Zeile hinter dem Deklarationsbereich des Moduls. Dahinter sollen nun die Deklarationen der nun privaten Variablen angeh&auml;ngt werden und direkt im Anschluss die <b>Property<\/b>-Prozeduren.<\/p>\n<p>Letzteres erledigt die Prozedur mit der <b>InsertLines<\/b>-Methode, welche an der Position der Zeile aus <b>lngStartline <\/b>die Inhalte der Variablen <b>strVariables <\/b>und <b>strProperties <\/b>hinterlegt.<\/p>\n<h2>Testen der Prozedur VariableToProperty<\/h2>\n<p>Wie aber k&ouml;nnen wir die Prozedur ausprobieren, wenn dazu der umzuwandelnde Inhalt im Klassenmodul markiert sein muss?<\/p>\n<p>Wir k&ouml;nnen dann nicht zum Modul mit der Prozedur <b>VariableToProperty <\/b>wechseln, um diese zu markieren und mit <b>F5 <\/b>auszuf&uuml;hren.<\/p>\n<p>Das ist auch nicht n&ouml;tig: Wir k&ouml;nnen auch einfach den Namen der Prozedur im Direktbereich des VBA-Editors eingeben. Die zu bearbeitende Zeile beh&auml;lt dann ihre Markierung, auch wenn diese nicht mehr angezeigt wird (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_03\/pic_422_001.png\" alt=\"Vor der &Auml;nderung\" width=\"424,6267\" height=\"311,3353\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Vor der &Auml;nderung<\/span><\/b><\/p>\n<p>Rufen wir die Prozedur nun auf, ersetzt diese die markierte Zeile durch die Zeilen, die wir in Bild 2 sehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_03\/pic_422_002.png\" alt=\"Nach der &Auml;nderung\" width=\"424,6267\" height=\"362,9288\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Nach der &Auml;nderung<\/span><\/b><\/p>\n<p>Auf diese Weise k&ouml;nnen brauchen wir zum Erstellen eines Satzes bestehend aus einer privaten Variablen und jeweils einer <b>Property Let\/Set<\/b>&#8211; und einer <b>Property Get<\/b>-Prozedur nur die private Variable zu markieren und dann die Prozedur aufzurufen.<\/p>\n<h2>Sch&ouml;nheitskorrektur<\/h2>\n<p>Es kann sein, dass sich hinter der letzten hinzugef&uuml;gten Prozedur und der ersten bereits vorhandenen Prozedur nun mehr als eine Leerzeile befindet. F&uuml;r diesen Fall f&uuml;gen wir noch eine kleine Erweiterung an.<\/p>\n<p>Dazu nutzen wir die Prozedur <b>RemoveTripeCrLf<\/b>. Sie nimmt ein <b>CodeModule<\/b>-Objekt entgegen und schreibt zun&auml;chst den vollst&auml;ndigen Code des Moduls in eine <b>String<\/b>-Variable.<\/p>\n<p>Dann pr&uuml;ft sie in einer <b>Do While<\/b>-Schleife, ob die <b>String<\/b>-Variable drei aufeinanderfolgende Zeilenumbr&uuml;che (<b>vbCrLf<\/b>) enth&auml;lt. In diesem Fall ersetzt sie die dreifachen Zeilenumbr&uuml;che durch doppelte Zeilenumbr&uuml;che. Dies geschieht so lange, bis es nur noch maximal zwei Zeilenbr&uuml;che in Folge gibt (siehe Listing 2).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>RemoveTripeCrLf (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     strCode = objCodeModule.Lines(1, objCodeModule.CountOfLines)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">InStr<\/span>(1, strCode, <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span>)\r\n         strCode = <span style=\"color:blue;\">Replace<\/span>(strCode, <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span>, <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span>)\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     objCodeModule.DeleteLines 1, objCodeModule.CountOfLines\r\n     objCodeModule.InsertLines 1, strCode\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Prozedur zum Entfernen von mehr als einer Leerzeile aus einem Modul<\/span><\/b><\/p>\n<p>Diese Prozedur k&ouml;nnen wir am Ende der Prozedur <b>VariableToProperty <\/b>mit der folgenden Anweisung aufrufen:<\/p>\n<pre><span style=\"color:blue;\">Call<\/span> RemoveTripeCrLf(objCodeModule)<\/pre>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Artikel zeigt, wir wie eine Prozedur programmieren, die uns viel Schreibarbeit abnehmen kann, wenn wir mit Klassen programmieren.<\/p>\n<p>Allerdings fehlt noch ein klein wenig Komfort. Bisher m&uuml;ssten wir die Prozedur <b>VariableToProperty<\/b> immer in die Zielanwendung schreiben und diese dort durch die Eingabe des Prozedurnamens in das Direktfenster aufrufen.<\/p>\n<p>Sch&ouml;ner w&auml;re es, wenn wir diese Prozedur &uuml;ber einen Men&uuml;eintrag im VBA-Editor aufrufen k&ouml;nnten oder sogar &uuml;ber das Kontextmen&uuml;.<\/p>\n<p>In einem weiteren Artikel namens <b>Klassenprogrammierung mit COM-Add-In vereinfachen <\/b>(<b>www.vbentwickler.de\/433<\/b>) schauen wir uns an, wir dies mithilfe eines COM-Add-Ins f&uuml;r den VBA-Editor realisieren k&ouml;nnen.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>VBEProgrammieren_Klasseneigenschaften.accdb<\/p>\n<p>mdlVBE.bas<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/436607C2-3AB6-4A29-ABD2-9F0A0A609254\/vbe_422.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn wir im VBA-Editor benutzerdefinierte Klassen programmieren wollen, verwenden wir f&uuml;r Eigenschaften &uuml;blicherweise eine private Variable, die wir &uuml;ber eine &ouml;ffentliche Property Set\/Let-Prozedur mit einem Wert f&uuml;llen und mit einer Property Get-Prozedur auslesen k&ouml;nnen. Das sind mindestens sieben Zeilen je Eigenschaft, was jede Menge Tipparbeit und Aufwand bedeutet und au&szlig;erdem noch fehleranf&auml;llig ist. Selbst Copy und Paste macht diese Aufgabe nicht wesentlich angenehmer. Wohl dem, der wei&szlig;, wie er den VBA-Editor programmiert, sodass er solche Aufgaben mit wenigen Mausklicks automatisieren kann. Hier gibt es verschiedene Ans&auml;tze, die wir uns in diesem Artikel ansehen und auch umsetzen.<\/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":[662024,66032024,44000027,44000037],"tags":[],"yst_prominent_words":[],"class_list":["post-55000422","post","type-post","status-publish","format-standard","hentry","category-662024","category-66032024","category-Excel_programmieren","category-VBAEditor_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000422","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=55000422"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000422\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000422"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000422"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000422"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000422"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}