Zeilennummern per VBA hinzufgen

Wer eine wirklich professionelle Fehlerbehandlung zu seiner Access-Anwendung hinzuf gen m chte, kommt nicht um das Anlegen von Zeilennummern herum. Wenn man Zeilennummern festgelegt hat, kann man diese im Falle eines Fehlers mit der nicht dokumentierten Erl-Funktion auslesen. Das hei t, dass wir neben der Fehlernummer und der Fehlerbeschreibung noch auf die Zeilennummer zur ckgreifen k nnen, um den Fehler zu lokalisieren. Dazu geh rt allerdings auch, dass wir in der Fehlermeldung Informationen ber das Modul und die Prozedur unterbringen, in denen der Fehler aufgetreten ist doch dies l sst sich einfach realisieren. Sehr aufw ndig ist es hingegen, alle Prozeduren von umfangreichen Anwendungen mit Zeilennummern zu versehen. Um dies zu realisieren, nutzen wir die Bibliothek Microsoft Visual Basic for Applications Extensibility 5.3, die alle M glichkeiten bietet, um auf die enthaltenen Module zuzugreifen und den Code automatisiert nach unseren W nschen anzupassen. Funktion zum Hinzuf gen von Zeilennummern Wichtig f r die Fehlerbehandlung sind auch die Zeilennummern. Diese f gen wir mit der Funktion AddLineNumbers zu einer Prozedur hinzu. Diese Prozedur geben wir mit den folgenden Parametern an: strModule: Name des Moduls, in dem sich die Prozedur befindet strProcedure: Name der Prozedur, die mit Zeilennummern versehen werden soll Die Prozedur aus Listing 1 referenziert als Erstes das aktuelle VBA-Projekt und die mit strModule angegebene Komponente. Dazu holt sie sich ber die CodeModule-Eigenschaft noch das passende CodeModule-Objekt, mit dem wir auf den Code zugreifen k nnen. Mit lngProcBodyLine speichern wir die Zeile, in der die Prozedur aus strProcedure beginnt. Wir wollen nur die eigentlichen Anweisungen der Prozedur mit Zeilennummern versehen, also ermitteln wir die Nummer der ersten Zeile hinter dem Prozedurkopf und die Nummer der letzten Zeile vor der End-Zeile der Prozedur. Dazu nutzen wir die beiden weiter hinten beschriebenen Funktionen GetFirstStatementLineNumber und GetLastStatementLineNumber. Public Sub AddLineNumbers(strModule As String, strProcedure As String) Dim objVBProject As VBIDE.VBProject Dim objVBComponent As VBIDE.VBComponent Dim objCodemodule As VBIDE.CodeModule Dim intProcType As vbext_ProcKind Dim lngProcBodyLine As Long Dim lngFirstStatementLineNumber As Long Dim lngLastStatementLineNumber As Long Dim lngLine As Long Dim bolNumbers As Boolean Dim strLine As String Set objVBProject = VBE.ActiveVBProject Set objVBComponent = objVBProject.VBComponents(strModule) Set objCodemodule = objVBComponent.CodeModule lngProcBodyLine = objCodemodule.ProcBodyLine(strProcedure, intProcType) lngFirstStatementLineNumber = GetFirstStatementLineNumber(objCodemodule, lngProcBodyLine) lngLastStatementLineNumber = GetLastStatementLineNumber(objCodemodule, lngProcBodyLine) For lngLine = lngFirstStatementLineNumber To lngLastStatementLineNumber strLine = left(objCodemodule.Lines(lngLine, 1), 6) Select Case True Case IsNumeric(strLine) bolNumbers = True Exit For End Select Next lngLine If bolNumbers = False Then For lngLine = lngFirstStatementLineNumber To lngLastStatementLineNumber Select Case True Case left(LTrim(objCodemodule.Lines(lngLine, 1)), 5) = "Case " objCodemodule.ReplaceLine lngLine, Space(6) objCodemodule.Lines(lngLine, 1) Case IsLabel(objCodemodule.Lines(lngLine, 1)) Case Else objCodemodule.ReplaceLine lngLine, Format(lngLine, "00000") " " objCodemodule.Lines(lngLine, 1) End Select Next lngLine Else MsgBox "Die Prozedur ''" strProcedure "'' aus Modul ''" strModule _ "'' scheint bereits Zeilennummern zu enthalten.", vbOKOnly + vbInformation, "Zeilennummern vorhanden" End If End Sub Listing 1: Prozedur zum Hinzuf gen von Zeilennummern zu einer Prozedur Die Prozedur durchl uft nun in einer ersten ForNext-Schleife alle Zeilen der Prozedur, um eventuell bereits mit Zeilennummern versehene Prozeduren zu erkennen. Findet sie w hrend dieses Durchlauf in irgendeiner Zeile einen numerischen Wert in den ersten sechs Zeichen, wird die Variable bolNumbers auf True eingestellt und die Schleife verlassen. In diesem Fall legt die Prozedur keine neuen Zeilennummern an, sondern gibt eine entsprechende Meldung aus. Anderenfalls durchl uft die Prozedur alle Zeilen von der ersten Anweisung bis zur letzten Anweisung der mit Zeilennummern zu versehenden Routine. Dies geschieht in einer ForNext-Schleife mit der Laufvariablen lngLine. Innerhalb der Schleife pr fen wir in einer Select Case-Bedingung, ob verschiedene Bedingungen den Wert True haben. Dazu weisen wir der Select Case-Anweisung das Kriterium True zu. Der erste der folgenden Case-Zweige, der den Wert True liefert, wird demzufolge angesteuert. Die erste Bedingung pr ft, ob die um f hrende und folgende Leerzeichen erleichterte aktuelle Zeile mit Case beginnt. Case-Zeilen sind eine der wenigen Zeilen, die nicht mit einer Zeilennummer versehen werden k nnen. Eine Case-Zeile soll genau wie die nummerierten Zeilen um sechs Zeichen nach rechts einger ckt werden, auch wenn diese nicht nummeriert wird. Auf diese Weise bleibt die Einr ckung gegen ber den nummerierten Zeilen erhalten. Um die Zeile um sechs Zeichen einzur cken, verwenden wir die ReplaceLine-Anweisung des CodeModule-Objekts. Diese erwartet als ersten Parameter die Nummer der zu ersetzenden Zeile und als zweiten Parameter den neuen Inhalt der Zeile. Diesen stellen wir aus sechs mit der Space-Funktion ermittelten Leerzeichen und der vorherigen Zeile zusammen. Der zweite Case-Fall untersucht, ob es sich bei der Zeile um eine Sprungmarke handelt. Dazu verwendet sie die IsLabel-Funktion, welche die bergebene Zeile untersucht. Diese Funktion stellen wir sp ter vor. Liefert IsLabel den Wert True, geschieht nichts weiter mit dieser Zeile. Sprungmarken sollten weder nummeriert noch einger ckt werden (letzteres wird ohnehin wieder r ckg ngig gemacht). Der Case Else-Zweig tritt f r alle weiteren F lle ein. Dieser sorgt daf r, dass die aktuelle Zeile durch eine neue Zeile ersetzt wird, die aus der aktuellen Zeilennummer im Format 00000, einem Leerzeichen und der urspr nglichen Zeile besteht. Warum als Format 00000? Weil wir davon ausgehen, dass wir keine Module mit mehr als 99.999 Zeilen verwenden (falls doch, k nnen Sie das Format und die Einr ckungen so anpassen, dass diese mehr Stellen abdecken). Wenn wir die Zeilenzahl 123 mit dem Format 00000 einf gen, wird darauf 123 plus zwei folgende Leerzeichen. Aus 1 wird 1 plus vier folgende Leerzeichen. Es erfolgt also unabh ngig von der Stellenzahl der Zeilennummer eine konstante Einr ckung. Auf diese Weise durchlaufen wir alle Zeilen von der ersten bis zur letzten Anweisung der angebenen Prozedur. Funktion zum Hinzuf gen von Zeilennummern aufrufen Um die Funktion AddLineNumbers aufzurufen, verwenden wir beispielsweise den folgenden Befehl: Call AddLineNumbers("mdlTest", "Test") Damit f gen wir genau einer Prozedur Zeilennummern hinzu. Zeilennummern zu allen Prozeduren eines Moduls hinzuf gen Gegegebenenfalls wollen wir jedoch nicht nur einer, sondern allen Prozeduren eines Moduls Zeilennummern hinzuf gen oder vielleicht sogar allen Modulen des VBA-Projekts. Dazu bauen wir uns schnell ein paar Routinen. Die erste soll den Namen des Moduls entgegennehmen, deren Prozeduren mit Zeilennummerierungen versehen werden sollen (siehe Listing 2). Public Sub AddLineNumbersToModule(strModule As String) Dim objVBProject As VBIDE.VBProject Dim objVBComponent As VBIDE.VBComponent Dim objCodemodule As VBIDE.CodeModule Dim intProcType As vbext_ProcKind Dim lngCountOfLines As Long Dim lngLine As Long Dim strProcedure As String Set objVBProject = VBE.ActiveVBProject Set objVBComponent = objVBProject.VBComponents(strModule) Set objCodemodule = objVBComponent.CodeModule lngCountOfLines = objCodemodule.CountOfLines For lngLine = 1 To lngCountOfLines If Not strProcedure = objCodemodule.ProcOfLine(lngLine, intProcType) Then strProcedure = objCodemodule.ProcOfLine(lngLine, intProcType) Call AddLineNumbers(strModule, strProcedure) End If Next lngLine End Sub Listing 2: Prozedur zum Hinzuf gen von Zeilennummern zu allen Prozeduren eines Moduls Sie referenziert ber das VBProject-Objekt das VBComponents-Objekt f r das Modul und verwendet dann das CodeModule dieses Objekts. Sie ermittelt die Anzahl der Zeilen des Moduls und durchl uft dann alle Zeilen des Moduls. Dabei vergleicht sie jeweils den Namen der Prozedur der aktuellen Zeile mit dem in strProcedure gespeicherten Namen. Diese ist zun chst leer. Sobald die Prozedur auf die erste Prozedur st t, wird der Name der Prozedur in strProcedure geschrieben und die Prozedur AddLineNumber wird f r dieses Modul und diese Prozedur aufgerufen. Auf diese Weise durchl uft die Prozedur AddLineNumbersToModule alle Prozeduren des Moduls: Zeilennummern zu allen Prozeduren des VBA-Projekts hinzuf gen Schlie lich schauen wir uns noch an, wie wir allen Prozeduren in allen Modulen eines VBA-Projekts Zeilennummern hinzuf gen k nnen. Dazu schreiben wir eine weitere Prozedur, welche wiederum die Prozedur AddLineNumbersToModule aufruft: Public Sub AddLineNumbersToActiveVBProject() Dim objVBProject As VBIDE.VBProject Dim objVBComponent As VBIDE.VBComponent Set objVBProject = VBE.ActiveVBProject For Each objVBComponent In objVBProject.VBComponents Call AddLineNumbersToModule(objVBComponent.Name) Next objVBComponent End Sub Die Prozedur referenziert das aktive VBA-Projekt und durchl uft alle Elemente der VBComponents-Auflistung, die sie dabei mit der Variablen objVBComponent referenziert. Sie ruft f r jeden Schleifendurchlauf die Prozedur AddLineNumbersToModule mit dem Namen des aktuellen VBComponent-Objekts auf. Funktion zum Entfernen von Zeilennummern aus einer Prozedur Gegebenenfalls m chte man auch einmal die Zeilennummern wieder entfernen. Beispielsweise dann, wenn man Zeilen zum Code hinzuf gen oder entfernen will und nicht die Nummerierung von Hand anpassen m chte.Dazu k nnen wir die Prozedur RemoveLineNumbers aus Listing 3 nutzen. Public Sub RemoveLineNumbers(strModule As String, strProcedure As String) Dim objVBProject As VBIDE.VBProject Dim objVBComponent As VBIDE.VBComponent Dim objCodemodule As VBIDE.CodeModule Dim lngCountOfLines As Long Dim intProcType As vbext_ProcKind Dim lngProcBodyLine As Long Dim lngFirstStatementLineNumber As Long Dim lngLastStatementLineNumber As Long Dim lngLine As Long Dim strLine As String Dim bolNumbers As Boolean Set objVBProject = VBE.ActiveVBProject Set objVBComponent = objVBProject.VBComponents(strModule) Set objCodemodule = objVBComponent.CodeModule lngCountOfLines = objCodemodule.CountOfLines lngProcBodyLine = objCodemodule.ProcBodyLine(strProcedure, intProcType) lngFirstStatementLineNumber = GetFirstStatementLineNumber(objCodemodule, lngProcBodyLine) lngLastStatementLineNumber = GetLastStatementLineNumber(objCodemodule, lngProcBodyLine) For lngLine = lngFirstStatementLineNumber To lngLastStatementLineNumber strLine = left(objCodemodule.Lines(lngLine, 1), 6) Select Case True Case IsNumeric(strLine) bolNumbers = True Exit For End Select Next lngLine If bolNumbers = True Then For lngLine = lngFirstStatementLineNumber To lngLastStatementLineNumber strLine = left(objCodemodule.Lines(lngLine, 1), 6) Select Case True Case IsNumeric(strLine), Trim(strLine) = "" objCodemodule.ReplaceLine lngLine, Mid(objCodemodule.Lines(lngLine, 1), 7) End Select Next lngLine End If End Sub Listing 3: Prozedur zum Entfernen von Zeilennummern einer Prozedur Achtung: Die Prozedur geht davon aus, dass die Prozedur, aus der die Zeilennummern entfernt werden sollen, mit der weiter oben beschriebenen Prozedur AddLineNumbers mit Zeilennummern versehen wurde. Die Prozedur erwartet die folgenden Parameter: strModule: Name des Moduls, in dem sich die Prozedur befindet strProcedure: Name der Prozedur, die mit Zeilennummern versehen werden soll Sie referenziert das aktuelle VBA-Projekt und dann mit objVBComponent die mit strModule bergebene Komponente. Mit objCodeModule referenzieren wir das CodeModule-Element, das wir anschlie end nutzen, um mit ProcBodyLine die erste Zeile der Prozedur aus strProcedure zu ermitteln. Mit dieser k nnen wir nun die beiden Funktionen GetFirstStatementLineNumber und GetLastStatementLineNumber aufrufen, um die Nummern der ersten und der letzten Zeile innerhalb der Prozedur zu ermitteln. Die so ermittelten Werte verwenden wir als Bereich von zun chst einer ForNext-Schleife. In dieser ermitteln wir die ersten sechs Zeichen der Zeile. Enthalten diese einen numerischen Wert, ist die Prozedur offensichtlich mit einer Zeilenummerierung ausgestattet. Sobald wir einen numerischen Wert in den ersten sechs Zeichen einer Zeile ermittelt haben, stellen wir daher die Variable bolNumbers auf True ein und verlassen die erste ForNext-Schleife. Hat bolNumbers danach den Wert True, steigen wir in die n chste ForNext-Schleife ein. In dieser ermitteln wir zun chst die ersten sechs Zeichen einer jeden Zeile. Diese untersuchen wir im Anschluss. Ist der Inhalt der ersten sechs Zeichen numerisch, handelt es sich offensichtlich um Zeilennummern. Ist der Inhalt hingegen eine leere Zeichenkette, so ist es eine Zeile, die zuvor einger ckt wurde, ohne dass eine Zeilennummer hinzugef gt wurde. In beiden F llen werden einfach die ersten sechs Zeichen von vorn entfernt. Funktion zum Entfernen von Zeilennummern aus einem vollst ndigen Modul Da wir diese Prozedur nicht f r jede Prozedur einzeln aufrufen wollen, verwenden wir eine weitere Prozedur namens RemoveLineNumbersFromModule (siehe Listing 4), um alle Prozeduren eines Moduls zu durchlaufen und f r jede Prozedur die Routine RemoveLineNumbers aufzurufen. Public Sub RemoveLineNumbersFromModule(strModule As String) Dim objVBProject As VBIDE.VBProject Dim objVBComponent As VBIDE.VBComponent Dim objCodemodule As VBIDE.CodeModule Dim intProcType As vbext_ProcKind Dim lngCountOfLines As Long Dim lngLine As Long Dim strProcedure As String Set objVBProject = VBE.ActiveVBProject Set objVBComponent = objVBProject.VBComponents(strModule) Set objCodemodule = objVBComponent.CodeModule lngCountOfLines = objCodemodule.CountOfLines For lngLine = 1 To lngCountOfLines If Not strProcedure = objCodemodule.ProcOfLine(lngLine, intProcType) Then strProcedure = objCodemodule.ProcOfLine(lngLine, intProcType) Call RemoveLineNumbers(strModule, strProcedure) End If Next lngLine End Sub Listing 4: Prozedur zum Entfernen von Zeilennummern eines Moduls Dazu referenzieren wir das aktuelle VBA-Projekt und das bergebene Modul mit der Variablen objCodeModule. Wir durchlaufen alle Zeilen des Moduls und pr fen, zu welcher Prozedur die aktuelle Zeile geh rt. Beim Auffinden einer jeden neuen Prozedur rufen wir einmal die Prozedur RemoveLineNumbers f r diese Prozedur auf. Dies f hren wir solange durch, bis wir alle Zeilen des Moduls durchlaufen haben. Funktion zum Entfernen von Zeilennummern aus dem vollst ndigen VBA-Modul Schlie lich verwenden wir noch eine Prozedur namens RemoveLineNumbersFromActiveVBProject, um alle Module des aktuellen VBA-Projekts zu durchlaufen und f r jedes Modul einmal die Prozedur RemoveLineNumbersFromModule aufzurufen. Damit k nnen wir alle Nummerierungen aus den Modulen des Projekts entfernen: Public Sub RemoveLineNumbersFromActiveVBProject() Dim objVBProject As VBIDE.VBProject Dim objVBComponent As VBIDE.VBComponent Set objVBProject = VBE.ActiveVBProject For Each objVBComponent In objVBProject.VBComponents Call RemoveLineNumbersFromModule(objVBComponent.Name) Next objVBComponent End Sub Hilfsfunktion zum Ermitteln der Zeilennummer der ersten Anweisung einer Prozedur Die Hilfsfunktion GetFirstStatementLineNumber ermittelt die Nummer der ersten Anweisung in einer Prozedur. Damit ist tats chlich die erste Anweisung genannt, die auf die Kopfzeile folgt auch, wenn diese mehr als eine Zeile umfasst. Diese Funktion aus Listing 4 erwartet die folgenden Parameter: Public Function GetFirstStatementLineNumber(objCodemodule As VBIDE.CodeModule, lngProcBodyLine As Long) As Long Dim strLine As String Dim lngFirstStatementLineNumber As Long lngFirstStatementLineNumber = lngProcBodyLine strLine = objCodemodule.Lines(lngFirstStatementLineNumber, 1) strLine = Trim(strLine) Do While right(strLine, 1) = "_" lngFirstStatementLineNumber = lngFirstStatementLineNumber + 1 strLine = objCodemodule.Lines(lngFirstStatementLineNumber, 1) strLine = Trim(strLine) Loop GetFirstStatementLineNumber = lngFirstStatementLineNumber + 1 End Function Listing 5: Prozedur zum Einlesen der Nummer der Zeile der ersten Anweisung in einer Prozedur objCodemodule: Verweis auf das CodeModule-Objekt, in dem sich die Prozedur befindet lngProcBodyLine: Nummer der Kopfzeile der zu untersuchenden Prozedur Die mit lngProcBodyLine gelieferte Zeilennummer verwenden wir als Ausgangspunkt f r die Suche nach der ersten Zeile hinter der Kopfzeile. Die Funktion GetFirstStatementLineNumber schreibt zuerst den Wert aus lngProcBodyLine in die Variable lngFirstStatementLineNumber. Nun pr ft die Funktion, ob die Kopfzeile der Prozedur am Ende einen Unterstrich enth lt, was darauf hindeuten w rde, dass die Kopfzeile noch mindestens eine weitere Zeile enth lt. Ist das nicht der Fall, ist die erste Zeile nach der Kopfzeile die erste Zeile mit einer Anweisung. Wir brauchen also nur lngFirstStatementLineNumber um 1 zu erh hen und zur ckzugeben. Anderenfalls springt die Prozedur solange eine Zeile weiter, bis sie die letzte Zeile der Kopfzeile erreicht. Anschlie end wird ebenfalls 1 zu lngFirstStatementLineNumber hinzugez hlt und der Wert zur ckgegeben. Hilfsfunktion zum Ermitteln der Zeilennummer der letzten Anweisung einer Prozedur Auf hnliche Weise ermitteln wir die Zeile mit der letzten Anweisung. Die dazu verwendete Funktion GetLastStatementLineNumber aus Listing 5 ist lediglich etwas umfangreicher und verwendet die gleichen Parameter wie GetFirstStatementLineNumber. Das liegt daran, dass sie zuerst die erste Zeile mit einer Anweisung ermittelt und sich von dort bis zur letzten Anweisung der Prozedur durcharbeitet. Public Function GetLastStatementLineNumber(objCodemodule As VBIDE.CodeModule, lngProcBodyLine As Long) As Long Dim lngFirstStatementLineNumber As Long Dim lngLastStatementLineNumber As Long Dim lngLine As Long Dim strCurrentLine As String lngFirstStatementLineNumber = GetFirstStatementLineNumber(objCodemodule, lngProcBodyLine) For lngLine = lngFirstStatementLineNumber To objCodemodule.CountOfLines strCurrentLine = objCodemodule.Lines(lngLine, 1) strCurrentLine = LTrim(strCurrentLine) Select Case True Case left(strCurrentLine, 7) = "End Sub", left(strCurrentLine, 12) = "End Function", _ left(strCurrentLine, 12) = "End Property" lngLastStatementLineNumber = lngLine - 1 Exit For End Select Next lngLine GetLastStatementLineNumber = lngLastStatementLineNumber End Function Listing 6: Prozedur zum Ermitteln der Nummer der Zeile mit der letzten Anweisung einer Prozedur Dazu durchlaufen wir alle Zeilen von der Zeile mit der ersten Anweisung bis zum Ende des aktuellen Moduls allerdings nur solange, bis wir auf eine Zeile sto en, die mit End Sub, End Function oder End Property endet. In diesem Fall ist die vorherige Zeile die letzte Zeile der aktuellen Prozedur und wir geben den Wert der Laufvariablen lngLine 1 als Funktionsergebnis zur ck. Hilfsfunktion zum Identifizieren einer Zeile als Sprungmarke Sprungmarken wie die folgende sollen nicht mit einer Zeilennummer versehen werden: Errorhandling: Es kann auch sein, dass auf die Sprungmarke noch ein Kommentar folgt: Errorhandling: ''Hier beginnt die Fehlerbehandlung Beide F lle m ssen wir ber cksichtigen. Dazu nutzen wir die Funktion IsLabel, die lediglich die Zeile als Parameter erwartet (siehe Listing 6). Public Function IsLabel(strLine As String) As Boolean If LTrim(strLine) = strLine Then If InStr(1, Trim(strLine), " ") = 0 Then If right(Trim(strLine), 1) = ":" Then IsLabel = True Else IsLabel = False End If Else If InStr(1, strLine, ":") = 0 Then IsLabel = False Else If InStr(1, strLine, ":") < InStr(1, strLine, " ") Then IsLabel = True Else IsLabel = False End If End If End If Else IsLabel = False End If End Function Listing 7: Prozedur zum Pr fen, ob eine Zeile eine Sprungmarke ist Sie pr ft zun chst, ob der um f hrende Leerzeichen mit LTrim erleichterte Inhalt von strLine gleich dem unbearbeiteten Inhalt von strLine entspricht. Wenn das nicht der Fall ist, bedeutet dies, dass der Text der Zeile nicht ganz links beginnt dann kann es sich nicht um eine Sprungmarke handeln. Ist das hingegen der Fall, sind weitere Untersuchungen n tig. Die erste pr ft mit der InStr-Funktion, ob die Zeile ein Leerzeichen enth lt. Ist das nicht der Fall, pr ft sie noch, ob das ganz rechte Zeichen der um Leerzeichen erleichterten Zeile ein Doppelpunkt. In diesem Fall handelt es sich ebenfalls um eine Sprungmarke. Den Fall mit dem Leerzeichen untersuchen wir im Else-Zweig. Hier pr fen wir zuerst, ob die Zeile dennoch einen Doppelpunkt enth lt. Falls nein, ist es keine Sprungmarke. Falls ja, m ssen wir noch pr fen, ob der Doppelpunkt vor dem Leerzeichen steht. Ist das der Fall, handelt es sich vermutlich um eine Sprungmarke mit einem Kommentar. Anderenfalls ist es keine Sprungmarke. Hilfsfunktion zum Ermitteln der Kopfzeile der Prozedur in einer Zeile Es kann sein, dass der Entwickler die Kopfzeile der Prozedur ber mehrere Zeilen erstreckt hat, weil diese wegen vieler Parameter sehr lang ist. F r verschiedene Anwendungszwecke ben tigen wir jedoch die Kopfzeile ohne Zeilenumbr che. Deshalb haben wir die Funktion GetProcBodyLine entwickelt, der wir die folgenden Parameter bergeben: objCodeModule: Verweis auf das CodeModule-Objekt, in dem sich die zu untersuchende Prozedur befindet lngProcBodyLine: Zeile, in der die Kopfzeile der Prozedur beginnt Die Prozedur aus Listing 7 tr gt zun cht den Wert des Parameters lngProcBodyLine in die Variable lngCurrentLine ein. Dann ermittelt sie mit der Lines-Funktion des CodeModule-Objekts den Text der Zeile mit der Nummer aus lngCurrentLine und speichert diese in der Variablen strLine. Vorher wird sie noch mit der Trim-Funktion behandelt, um f hrende und folgende Leerzeichen zu entfernen. Public Function GetProcBodyLine(objCodemodule As VBIDE.CodeModule, lngProcBodyLine) As String Dim strLine As String Dim lngCurrentLine As Long lngCurrentLine = lngProcBodyLine strLine = Trim(objCodemodule.Lines(lngCurrentLine, 1)) Do While right(strLine, 1) = "_" lngCurrentLine = lngCurrentLine + 1 strLine = left(strLine, Len(strLine) - 2) strLine = strLine " " Trim(objCodemodule.Lines(lngCurrentLine, 1)) Loop GetProcBodyLine = strLine End Function Listing 8: Prozedur zum Ermitteln der kompletten Kopfzeile ohne Zeilenumbr che Damit steigt sie in einer Do While-Schleife ein, die untersucht, ob das erste Zeichen von rechts ein Unterstrich ist (_), was bedeuten w rde, dass die Kopfzeile zumindest noch eine weitere Zeile enth lt. In diesem Fall wird lngCurrentLine um 1 erh ht und die Prozedur schneidet den Unterstrich und das vorherige Leerzeichen ab. Dann h ngt es den Inhalt der aktuell mit lngCurrentLine bezeichneten Zeile an die Variable strLine an. Dies geschieht solange, bis die mit lngCurrentLine bezeichnete Zeile keinen Unterstrich mehr als letztes Zeichen enth lt. Dann wir der aktuelle Inhalt von strLine als Wert der Funktion GetProcBodyLine zur ckgegeben. Hilfsfunktion zum Ermitteln des Prozedurtyps F r verschiedene Aktionen m ssen wir wissen, ob es sich bei der Prozedur um eine Sub-, Function oder Property-Prozedur handelt. Um dies herauszufinden, schicken wir die erste Zeile einer Prozedur an eine Hilfsfunktion namens GetProcType. Diese erwartet die folgenden beiden Parameter: strProcedure: Name der Prozedur strProcBodyLine: Kopfzeile der Prozedur Die Funktion finden wir in Listing 8. Sie ermittelt als Erstes die Position in der Kopfzeile der Prozedur, in welcher der Prozedurname zum ersten Mal auftaucht. Nur der Teil bis zu dieser Position interessiert uns alles inklusive des Prozedurnamens und der Parameter k nnen wir erst einmal abschneiden. Also ermittelt die Funktion diese Position mit der InStr-Funktion, der wir als zu suchenden Begriff nicht nur den Prozedurnamen bergeben, sondern auch noch ein f hrendes Leerzeichen. Dann schneidet die Prozedur den Teil, der hinter diesem Zeichen liegt, ab, indem sie mit der Left-Funktion nur den Teil bis zu dieser Position zur ckliefert. Das Ergebnis behandeln wir noch mit der Trim-Funktion, um f hrende und folgende Leerzeichen abzuschneiden. Schlie lich wandlet die Prozedur den Inhalt im Falle der Werte Get, Let oder Set noch in Property um. Angenommen, wir starten mit der folgenden Anweisung: Public Function GetProcType(strProcedure As String, strProcBodyLine As String) As String Dim lngPos As Long Dim strProcType As String lngPos = InStr(1, strProcBodyLine, " " strProcedure) strProcType = Trim(left(strProcBodyLine, lngPos)) lngPos = InStrRev(strProcType, " ") strProcType = Trim(Mid(strProcType, lngPos)) Select Case strProcType Case "Get", "Let", "Set" strProcType = "Property" End Select GetProcType = strProcType End Function Listing 9: Ermitteln des Typs einer Prozedur Public Sub Beispielprozedur(strBeispiel As String) Nach diesen ersten Schritten bleibt noch diese Zeichenkette brig: Public Sub Davon ben tigen wir nur noch den hinteren Teil, also Sub. Dazu ermitteln wir mit der InStrRev-Funktion die Position des ersten Leerzeichens von hinten, also des Leerzeichens vor Sub. Mit der Mid-Funktion ermitteln wir nun nur noch die Zeichenkette von dieser Position bis zum Ende der Zeichenkette, also Sub, und speichern das Ergebnis in der Variablen strProcType. Dessen Inhalt gibt die Funktion schlie lich als Ergebnis zur ck. Zusammenfassung und Ausblick In diesem Beitrag haben wir Techniken vorgestellt, mit denen wir Zeilennummern zu einzelnen Prozeduren, Modulen oder sogar zu vollst ndigen VBA-Projekten hinzuf gen k nnen. Diese setzen wir beispielsweise im Beitrag Fehler in der Runtime von Access finden (www.access-im-unternehmen.de/1513) praktisch ein. Dort nutzen wir auch den Beitrag Fehlerbehandlung per VBA hinzuf gen (www.access-im-unternehmen.de/1514). The post Zeilennummern per VBA hinzuf gen appeared first on Access im Unternehmen.

zum Artikel gehen

Lexikoneintrag: You Ain't Gonna Need It (YAGNI)

Das Prinzip You Aint Gonna Need It (YAGNI) in der Softwareentwicklung besagt, dass Sie keinen Code oder Funktionen hinzufgen sollten, die Sie aktuell nicht bentigen, um zuknftige Anforderungen vorwegzunehmen. Stattdessen sollten Sie sich auf die aktuell

zum Artikel gehen

Schulung: Moderne Web-Anwendungen mit TypeScript und Angular

- berlebens-Kit fr den Umgang mit Node.js und NPM (notwendig, da alle Tools rund um Angular auf Node.js aufbauen) - Kurzeinfhrung in TypeScript mit Wiederholung der wichtigsten JavaScript-Konzepte (Annahme: Alle Teilnehmerinnen und Teilnehmer haben Java

zum Artikel gehen

DA ICH IMMER WIEDER DANACH GEFRAGT WERDE, HIER MEIN HUMMUS-REZEPT FÜR EUCH!

// 250g Kichererbsen ber Nacht einweichen, dann Wasser abgieen und Kichererbsen absplen, anschlieend mit einem TL Backpulver weich kochen. Das Kochwasser abgieen und die Kichererbsen mit dem Prierstab (oder ein

zum Artikel gehen

Fehlerbehandlung per VBA hinzufgen

Eine Fehlerbehandlung ist Teil einer professionellen Datenbankanwendung auf Basis von Microsoft Access. Sobald wir eine Datenbank an einen Kunden oder Mitarbeiter weitergeben, also an einen anderen Benutzer als uns selbst, ist dies praktisch ein Pflichtpr

zum Artikel gehen

Walter Who 2017

Weihnachten ist die Zeit des Jahres zu der man garantiert einige Freunde zu Gesicht bekommt. Umgeben von freudiger Atmosphre stt man mit ihnen das eine oder andere Mal sachte oder auch ausgelassen an. Der alljhrliche Walter Who-Rumble Ende Ja

zum Artikel gehen