VBA-Editor: Klasseneigenschaften per Mausklick

Lies in den Artikel rein und unten bekommst Du ein unschlagbares Angebot!

Wenn wir im VBA-Editor benutzerdefinierte Klassen programmieren wollen, verwenden wir für Eigenschaften üblicherweise eine private Variable, die wir über eine öffentliche Property Set/Let-Prozedur mit einem Wert füllen und mit einer Property Get-Prozedur auslesen können. Das sind mindestens sieben Zeilen je Eigenschaft, was jede Menge Tipparbeit und Aufwand bedeutet und außerdem noch fehleranfällig ist. Selbst Copy und Paste macht diese Aufgabe nicht wesentlich angenehmer. Wohl dem, der weiß, wie er den VBA-Editor programmiert, sodass er solche Aufgaben mit wenigen Mausklicks automatisieren kann. Hier gibt es verschiedene Ansätze, die wir uns in diesem Artikel ansehen und auch umsetzen.

Die Programmierung von Office-Anwendungen mit VBA ist die eine Aufgabe. Diese wird üblicherweise durch die Anforderungen des Kunden oder des Benutzers gesteuert und einfach Schritt für Schritt abgearbeitet. Als Entwickler sollten wir jedoch immer darauf bedacht sein, Abkürzungen bei der Arbeit zu suchen, um schneller und zuverlässiger ans Ziel zu kommen.

Das gelingt unter Office anwendungsübergreifend im Bereich der VBA-Programmierung. Wir können uns auch die eine oder andere Prozedur bauen, um Aufgaben in Access, Excel, Outlook, PowerPoint oder Word zu automatisieren. Schließlich gibt es in einigen dieser Anwendungen dazu extra den Makro-Rekorder.

Unter VBA ist das jedoch noch ein wenig spannender, denn hier können wir für alle Office-Anwendungen gleichermaßen Vereinfachungen programmieren. Und so machen wir uns auch gleich ans Werk und schauen uns an, welche Möglichkeiten wir hier so haben.

Ziel: Private Member-Variable plus Get/Set/Let-Prozedur

Aber von welchen verschiedenen Ansätzen haben wir in der Einleitung gesprochen? Nun, es gibt verschiedene Ausgangssituationen. Wir schauen uns zuerst einmal an, was wir überhaupt haben wollen. Für eine vollwertige Eigenschaft, deren Wert gelesen und gesetzt werden kann, benötigen wir als Erstes eine private Member-Variable, die wir beispielsweise wie folgt deklarieren:

Private m_Firma As String

Damit wir von außen auf diese Variable zugreifen können, um ihren Wert einzustellen, nutzen wir eine öffentliche Property Let-Prozedur:

Public Property Get Firma() As String
     Firma = m_Firma
End Property 

Schließlich wollen wir eine Eigenschaft auch von außen setzen können, also fügen wir noch eine entsprechende Property Let-Prozedur hinzu:

Public Property Let Firma(str As String)
     m_Firma = str
End Property

Und wenn unsere Eigenschaft keine skalare Variable aufnimmt (also zum Beispiel Long oder String), sondern einen Objektverweis, müssen wir die Schreibweise ein wenig anpassen. Die Variable deklarieren wir dann etwa so:

Private m_Recordset As DAO.Recordset

Auch in der Get-Prozedur benötigen wir eine Änderung, denn für die Zuweisung von Objektverweisen ist das Schlüsselwort Set nötig:

Public Property Get Recordset() As DAO.Recordset
     Set Recordset = m_Recordset
End Property

Dieses Schlüsselwort benötigen wir auch beim Setzen des Objektverweises. Außerdem verwenden wir hier keine Property Let-Prozedur, sondern eine Property Set-Prozedur:

Public Property Set Recordset(rst As DAO.Recordset)
     Set m_Recordset = rst
End Property

Die nächste Vorgabe ist, dass die Property Let/Set/Get-Prozeduren im Modul frühestens nach der letzten Deklarationszeile hinzugefügt werden darf. Nach der ersten Prozedur darf keine alleinstehende Deklarationszeile mehr folgen.

Prozedur zum Ersetzen von öffentlichen Eigenschaften durch Get/Let/Set-Property

Wir können mit den Methoden der Bibliothek Microsoft Visual Basic for Applications 5.3 Object Library auf die Elemente des VBA-Editors zugreifen und diese manipulieren. Dies nutzen wir in diesem Falle, um die gewünschten Änderungen in einem Klassenmodul vorzunehmen. Den benötigten Verweis auf diese Bibliothek setzen wir auf gewohnte Weise über den Verweise-Dialog.

Dann fügen wir die Prozedur VariableToProperty zu einem Standardmodul hinzu (siehe Listing 1).

Public Sub VariableToProperty()
     Dim objCodePane As CodePane, objCodeModule As CodeModule
     Dim lngStartline As Long, lngStartcolumn As Long
     Dim lngEndline As Long, lngEndcolumn As Long
     Dim lngLine As Long, strLine As String
     Dim strVariable As String, strDatatype As String
     Dim strVariables As String
     Dim strProperties As String
     Dim strPrefix As String
     Set objCodePane = VBE.ActiveCodePane
     objCodePane.GetSelection lngStartline, lngStartcolumn, lngEndline, lngEndcolumn
     Set objCodeModule = objCodePane.CodeModule
     For lngLine = lngStartline To lngEndline
         strLine = Trim(objCodeModule.Lines(lngLine, 1))
         If Not Len(strLine) = 0 Then
             strVariable = Split(strLine, " ")(1)
             strDatatype = Split(strLine, " ")(3)
             strPrefix = GetPrefix(strDatatype)
             strVariables = strVariables & "Private m_" & strVariable & " As " & strDatatype & vbCrLf
             Select Case strPrefix
                 Case "obj"
                     strProperties = strProperties & "Public Property Set " & strVariable & "(" & strPrefix & " As " _
                         & strDatatype & ")" & vbCrLf
                     strProperties = strProperties & "    Set m_" & strVariable & " = " & strPrefix & vbCrLf
                 Case Else
                     strProperties = strProperties & "Public Property Let " & strVariable & "(" & strPrefix & " As " _
                         & strDatatype & ")" & vbCrLf
                     strProperties = strProperties & "    m_" & strVariable & " = " & strPrefix & vbCrLf
             End Select
             strProperties = strProperties & "End Property" & vbCrLf & vbCrLf
             strProperties = strProperties & "Public Property Get " & strVariable & " As " & strDatatype & vbCrLf
             Select Case strPrefix
                 Case "obj"
                     strProperties = strProperties & "    Set " & strVariable & " = m_" & strVariable & vbCrLf
                 Case Else
                     strProperties = strProperties & "    " & strVariable & " = m_" & strVariable & vbCrLf
             End Select
             strProperties = strProperties & "End Property " & vbCrLf & vbCrLf
         End If
     Next lngLine
     strVariables = strVariables & vbCrLf
     objCodeModule.DeleteLines lngStartline, lngEndline - lngStartline + 1
     lngStartline = objCodeModule.CountOfDeclarationLines + 1
     objCodeModule.InsertLines lngStartline, strVariables & strProperties
     Call RemoveTripeCrLf(objCodeModule)
End Sub

Listing 1: Prozedur zum Erstellen von Property Get/Let/Set-Prozeduren für Variablen

Diese Prozedur deklariert zunächst einige Variablen und stellt dann die Variable objCodePane mit der Funktion ActiveCodePane auf das aktuelle CodePane-Objekt ein, was dem aktuellen Codefenster entspricht.

Wir gehen davon aus, dass der Benutzer eine oder mehrere Zeilen mit öffentlichen Variablen markiert hat und dass die Prozedur diese alle in private Variablen umwandeln soll, die über eine Get Property verfügbar gemacht und mit Set/Let Property gesetzt werden können sollen.

Davon ausgehend erfassen wir die aktuelle Markierung im Codefenster mit der GetSelection-Funktion des CodePane-Objekts. Diese liefert uns für die Variablen lngStartline, lngStartcolumn, lngEndline und lngEndcolumn die Koordinaten der aktuellen Markierung.

Damit ausgestattet durchlaufen wir die erste Zeile der Markierung (lngStartline) bis zur letzten Zeile (lngEndline) in einer For…Next-Schleife mit lngLine als Laufvariable.

Darin lesen wir die aktuelle Zeile in die Variable strLine ein und entfernen mit der Trim-Funktion direkt führende und folgende Leerzeichen.

Wenn strLine nun keine leere Zeichenkette ist, teilen wir die Zeile mit der Split-Funktion an den Leerzeichen auf und ermitteln das zweite und das vierte Element (mit den Indexwerten 1 und 3 wegen des 0-basierten Indexes dieser Funktion). Wir gehen von einer Zeile wie der folgenden aus:

Public Field As DAO.Field

Dann landet der Variablenname Field in der Variablen strVariable und DAO.Field landet in strDatatype.

Bevor wir beginnen, den notwendigen Code zusammenzustellen, wollen wir noch den Datentyp der Variablen ermitteln und das dafür vorgesehene Präfix ermitteln. Das erledigen wir mit einem Aufruf der Funktion GetPrefix, die uns für den jeweiligen Datentyp das aus drei Buchstaben bestehenden Präfix liefert. Hier werden die Basisdatentypen wie Boolean, Integer oder String separat behandelt.

Für alle anderen Datentypen wird als Präfix obj angenommen. Ob wir es hier mit einem Object zu tun haben oder mit einem anderen Datentyp, wirkt sich auch darauf aus, ob wir eine Property Set (für Objekte) oder Property Let (für einfache Basistypen) anlegen müssen. Die Funktion GetPrefix sieht wie folgt aus und sie kann nach Bedarf erweitert werden:

Public Function GetPrefix(strDatatype As String) As String
     Select Case strDatatype
         Case "Boolean"
             GetPrefix = "bol"
         Case "Byte"
             GetPrefix = "byt"
         Case "Currency"
             GetPrefix = "cur"
         Case "Date"
             GetPrefix = "dat"
         Case "Decimal"
             GetPrefix = "dec"
         Case "Double"
             GetPrefix = "dbl"
         Case "Integer"
             GetPrefix = "int"
         Case "Long"
             GetPrefix = "lng"
         Case "Single"
             GetPrefix = "sng"
         Case "String"
             GetPrefix = "str"
         Case "Variant"
             GetPrefix = "var"
         Case Else
             GetPrefix = "obj"
     End Select
End Function

Zurück zur Prozedur VariableToProperty. Diese speichert das Präfix in der Variablen strPrefix. Dann fügt sie der Variablen strVariables eine Zeichenkette hinzu die aus Privat m_, dem Variablennamen, As, dem Datentyp und einem Zeilenumbruch besteht, in unserem Fall also beispielsweise:

Private m_Field As DAO.Field

Dass wir hier den Wert nicht einfach der Variablen strVariables zuweisen, sondern an diese anhängen, hängt damit zusammen, dass wir gegebenenfalls auch mehrere Variablen umwandeln wollen. Deshalb sammeln wir in strVariables alle Zeilen mit den Deklarationen der nun als privat deklarierten Variablen.

Danach prüft die Prozedur in einer Select Case-Bedingung, ob es sich bei dem Präfix um den Wert obj handelt oder um einen anderen Wert. Im Falle von obj setzt diese die Kopfzeile der Property-Prozedur mit dem Schlüsselwort Property Set zusammen, zum Beispiel so:

Public Property Set Field(obj As DAO.Field)

Anderenfalls wird das Schlüsselwort Let verwendet, zum Beispiel so:

Public Property Let Text(str As String)

Falls weitere Unterscheidungen gewünscht sind und individuelle Präfixe vergeben werden sollen, kann man diese in zusätzlichen Case-Zweigen unterbringen. Diese Kopfzeile wird hinten an die Variable strProperties angehängt.

Innerhalb der Schleife folgt auch noch die einzige Anweisung dieser Property Let/Set-Prozedur, die zusammengestellt wird aus Set m_, dem Variablennamen aus strVariable, dem Gleichheitszeichen und dem Präfix.

Für die Basisdatentypen wird die Anweisung auf die gleiche Weise zusammengestellt, allerdings kommt hier kein Set-Schlüsselwort zum Einsatz. Schließlich folgt in der folgenden Anweisung noch die Fußzeile, die für alle Eigenschaften End Property lautet.

 

Schreibe einen Kommentar