Reguläre Ausdrücke dienen mitunter nicht nur der Mustererkennung, sondern leisten hervorragende Dienste beim Ersetzen bestimmter Zeichenfolgen. Damit Sie unter VBA von regulären Ausdrücken profitieren können, lernen Sie in diesem Beitrag die grundlegenden Techniken kennen und erfahren, wie Sie beinahe beliebige Ausdrücke in Zeichenketten erkennen und ersetzen können. Schließlich liefert der Betrag ein Beispiel zum Erkennen der VBA-Schlüsselwörter in Codemodulen.
Reguläre Ausdrücke (Regular Expressions, kurz RegExp) dienen zum Suchen und Ersetzen von Textelementen.
Reguläre Ausdrücke sind kein Bestandteil von VBA, sondern müssen über das Setzen eines Verweises auf die Bibliothek Microsoft VBScript Regular Expressions 5.5 verfügbar gemacht werden.
Im Code erzeugen Sie dann eine Instanz des Objekts RegExp und speichern den Verweis darauf in einer entsprechenden Objektvariablen:
Dim objRegExp As RegExp Set objRegExp = New RegExp
Das RegExp-Objekt hat einige wenige Eigenschaften, die folgende Aufgabe haben:
- IgnoreCase: Legt fest, ob Groß-/Kleinschreibung beachtet werden soll.
- Global: Sollen nur das erste (Standard, False) oder alle Fundstellen (True) zurückgegeben werden
- Pattern: Legt das Muster fest, nach dem gesucht werden soll.
- Multiline: Gibt an, ob durch Zeilenumbrüche getrennte Teile einer Zeichenkette als neuer Ausdruck untersucht werden sollen. Dies erlaubt beispielsweise das Verwenden des Zeilenbeginn- und Zeilenende-Zeichens in Ausdrücken.
Aktionen
Prinzipiell können Sie mit RegExp suchen oder suchen und ersetzen. Wenn Sie einfach nur prüfen möchten, ob ein Ausdruck in einem anderen Ausdruck vorkommt, geben Sie das Pattern an und prüfen den zu durchsuchenden Ausdruck mit der Test-Funktion. Diese liefert True oder False zurück.
Wenn Sie den gefundenen Ausdruck gleich ersetzen möchten, verwenden Sie statt Test die Replace-Methode. Diese erwartet entsprechend gleich zwei Parameter, nämlich den zu durchsuchenden String sowie die Zeichenkette, die statt des in Pattern angegebenen Ausdrucks verwendet werden soll.
Einfache Suche
Die einfachste Suche realisieren die folgenden Codezeilen. Die Funktion prüft schlicht, ob sich der mit strSuchbegriff übergebene Ausdruck in strOriginal befindet und gibt entweder True oder False zurück:
Public Function EinfacheSuche( _ strOriginal As String, _ strSuchbegriff As String) As Boolean Dim objRegExp As RegExp Set objRegExp = New RegExp With objRegExp .Pattern = strSuchbegriff EinfacheSuche = .Test(strOriginal) End With Set objRegExp = Nothing End Function
Der folgende Ausdruck würde im Direktfenster also beispielsweise den Wert True zurückliefern:
EinfacheSuche("cd", "abcdef")
Einfaches Suchen und Ersetzen
Die einfachste Suchen- und Ersetzen-Funktion bildet (fast) die Replace-Funktion von VBA ab. Sie erwartet die gleichen Parameter, also den Originalausdruck, den zu ersetzenden Ausdruck und den Ersatzausdruck.
Der Unterschied ist jedoch, dass hier nur das erste Auftreten des gesuchten Begriffs ersetzt wird. Der Grundaufbau ist wie beim reinen Suchen, allerdings kommt hier nicht die Test-Funktion, sondern die Replace-Funktion zum Einsatz.
Diese erwartet zusätzlich den Ersatzbegriff als Parameter und liefert auch keinen Boolean-Wert zurück, sondern gleich die geänderte Zeichenkette:
Public Function SuchenUndErsetzen( _ strOriginal As String, _ strSuchbegriff As String, _ strErsatzbegriff As String) As String Dim objRegExp As RegExp Set objRegExp = New RegExp With objRegExp .Pattern = strSuchbegriff SuchenUndErsetzen = _ .Replace(strOriginal, strErsatzbegriff) End With Set objRegExp = Nothing End Function
Ein einfacher Aufruf sieht wie folgt aus und liefert das entsprechende Ergebnis zurück:
EinfachesSuchenUndErsetzen("abcdef", "cd", "xx") abxxef
Es kann auch sein, dass der Suchbegriff gleich mehrfach im Originalausdruck vorkommt. Um die Replace-Funktion von VBA vollwertig abzubilden, müssen wir den Suchbegriff an allen vorkommenden Stellen ersetzen. Dazu brauchen Sie einfach noch die Eigenschaft Global von objRegExp auf True einzustellen.
Alle Fundstellen einzeln betrachten
Gegebenenfalls sollen nicht alle Suchergebnisse über einen Kamm geschert werden, sondern Sie möchten diese einzeln behandeln.
Dann sind das MatchCollection– und das Match-Objekt interessant. Sie müssen für beide eine Objektvariable deklarieren:
Dim objMatchCollection As MatchCollection Dim objMatch As Match
Danach übergeben Sie das Ergebnis der Execute-Methode im MatchCollection-Objekt und durchlaufen alle darin enthaltenen Match-Objekte und geben einige Information pro Fundstelle aus:
Set objRegExp = New RegExp With objRegExp .Pattern = strSuchbegriff .Global = True Set objMatchCollection = _ .Execute(strOriginal) For Each objMatch In objMatchCollection Debug.Print "Position: " _ & objMatch.FirstIndex, "Wert: " _ & objMatch.Value, "Länge: " _ & objMatch.Length Next objMatch End With
Ein Beispielaufruf sieht etwa so aus:
SuchergebnisseEinzelnBearbeiten "abcdefcd", "cd" Position: 2 Wert: cd Länge: 2 Position: 6 Wert: cd Länge: 2
Das Match-Objekt liefert nützliche Informationen. Im obigen Beispiel geben wir die folgenden drei je Fundstelle aus:
- FirstIndex: Position, an welcher der Suchbegriff befindet. Achtung: 0-basiert!
- Value: Wert des gefundenen Ausdrucks. Im einfachen Beispiel von oben entspricht dieser natürlich immer dem Suchausdruck. Aber da dieser auch mit Platzhaltern angegeben werden kann, kann durchaus jeder Treffer anders aussehen.
- Length: Hier gilt das Gleiche wie für den Treffer selbst: Seine Länge kann ja nach Formulierung des Suchbegriffs durchaus variieren. Beispiele folgen!
Ausdrücke zusammenstellen
Nachdem Sie wichtige Grundtechniken für den Einsatz regulärer Ausdrücke kennengelernt haben, schauen wir uns nun die Ausdrücke beziehungsweise die sogenannten Pattern selbst an.
Die einfachste Möglichkeit ist natürlich die Angabe einer konkreten Zeichenkette. Sicher kennen Sie das Sternchen und das Fragezeichen als Platzhalter für beliebig viele beziehungsweise ein einziges Zeichen in Access-SQL-Bedingungen.
Reguläre Ausdrücke bieten hier wesentlich aufgefeiltere Möglichkeiten:
- Punkt (.): Beliebiges Zeichen außer Zeilenumbruch. a. findet also etwa ab, ac oder a1.
- Sternchen (*): Keine, eine oder mehrere Wiederholungen des vorhergehenden Zeichens. abc* würde also beispielsweise ab, abc, abcc oder abccc finden.
- Fragezeichen (): Kein oder ein Vorkommen des vorhergehenden Zeichens. abc findet also etwa ab oder abc.
- Pluszeichen (+): Ein oder mehrere Vorkommen des vorhergehenden Zeichens. abc+ findet also etwa abc, abcc oder abccc.
- Geschweifte Klammern ({}): In den Klammern können ein oder zwei durch Komma getrennte Zahlen stehen, die eine Information über die Anzahl des Vorkommens des vorhergehenden Zeichens enthalten. Eine einzige Zahl gibt die genaue Anzahl an, a{3} ist somit Platzhalter für aaa. Zwei durch Komma getrennte Zahlen geben kleinste und größte Anzahl des vorherigen Zeichens an, a{1,3} ist also Platzhalter für a, aa und aaa. Fehlt die Zahl vor dem Komma, wird dort der Wert 0 angenommen. ab{,2} ist also Platzhalter für a, ab und abb. Fehlt die Zahl nach dem Komma, kann die maximale Anzahl beliebig groß sein. ab{1,} steht also für ab, abb, abbb und so weiter.
- Eckige Klammern ([]) definieren Zeichenklassen. [abc] repräsentiert eines der Zeichen a, b oder c. [a-z] entspricht allen Buchstaben von a bis z.
- Eckige Klammern können auch auszuschließende Zeichen angeben. Dazu enthält die Klammer als erstes das Caret-Zeichen (^). [^abc] entspricht allen Zeichen außer a, b und c.
- Eckige Klammern können auch nicht zusammenhängende Zeichen oder Bereiche enthalten. [abd-f] ist beispielsweise Platzhalter für die Buchstaben a, b, d, e und f.
- Spezielle Platzhalter sind \d (alle Zahlen), \D (keine Zahl), \w (Buchstabe, Zahl oder Unterstrich), \W (alles außer Buchstaben, Zahlen oder Unterstrich), \s (Leerzeichen, Tabulator, Zeilenumbruch) oder \S (alles außer Leerzeichen, Tabulator, Zeilenumbruch).
- Alternativen werden in Klammern und durch das Pipe-Zeichen (|) getrennt angegeben. (abc|efg) steht so für eine der Zeichenfolgen abc oder efg.
- Caret-Zeichen (^): Steht für den Zeilen- beziehungsweise Zeichenkettenbeginn. ^Sub liefert also alle Fundstellen, bei den Sub am Zeilenanfang steht. Das Caret-Zeichen steht normalerweise nur stellvertretend für den Beginn der kompletten Zeichenkette, unabhängig davon, ob diese noch Zeilenumbrüche enthält. Wenn eine neue Zeile ebenfalls mit dem Caret-Zeichen erkannt werden soll, müssen Sie zuvor die Eigenschaft Multiline auf True einstellen.
- Dollar-Zeichen ($): Steht für das Zeilen- beziehungsweise Zeichenkettenende. Sub$ liefert also solche Fundstellen, bei denen Sub am Ende steht. Gut, um beispielsweise Prozedurenden zu finden. Bezüglich Zeilenumbrüche gilt hier das Gleiche wie beim Caret-Zeichen: Sie müssen die Eigenschaft Multiline auf True einstellen, damit jedes Zeilenende und nicht nur das Ende des kompletten Ausdrucks über das Dollar-Zeichen erkannt werden soll.
- Backslash (\): Möglicherweise möchten Sie in Texten auch nach Sonderzeichen suchen, die eine spezielle Funktion in regulären Ausdrücken haben. In diesem Fall stellen Sie dem Zeichen einen Backslash voran. Mit abc\$ suchen Sie also dann schlicht nach der Zeichenkette abc$ und nicht etwa nach einem Vorkommen von abc am Zeilenende oder am Ende der Zeichenkette.
- Wagenrücklauf (\r): entspricht vbCr
- Zeilenvorschub (\n): entspricht vbLf
- Wagenrücklauf und Zeilenvorschub (\r\n): entspricht vbCrLf
- Tabulator (\t): entspricht vbTab