Zahlen aus Text extrahieren
Gepostet am: May 03, 2011 1:30:7 PM
Kürzlich wurde in einem Office Forum die Frage gestellt, wie man aus einem Text die Zahlen extrahiert. Vorgebracht wurden komplizierte Matrix-Funktionen, die nicht zwangsweise das richtige Ergebnis lieferte. Meine Lösung dazu, war die Herangehensweise über Reguläre Ausdrücke:
Zahl aus Text extrahieren
Public Function FindeZahl(myRange As Range, minLaenge As Integer, maxLaenge As Integer, _ Optional iGroup As Integer = 1) As Long Dim objRegex As Object Dim objMatch As Object Set objRegex = CreateObject("VbScript.Regexp") With objRegex .Pattern = "\d{" & minLaenge & "," & maxLaenge & "}" .Global = True Set objMatch = .Execute(myRange.Value) FindeZahl = objMatch(iGroup - 1) End With Set objMatch = Nothing Set objRegex = Nothing End Function
Angenommen man möchte nun jede 9 stellige Zahl aus dem Text extrahieren, verwendet man die Formel folgendermaßen: =FindeZahl(Zellbezug; 9;9)
Wie man aber an nachfolgendem Beispiel sieht, stößt das ganze an Grenzen, wenn die Zahl im Text länger ist als die gesuchte Zahl.
Dafür kann man auch eine Lösung basteln und die oben genannte Funktion erweitern. Der folgende Screenshot aus dem RegexBuddy zeigt, wo das Problem liegt:
Erweitert man den regulären Ausdruck marginal auf "\D(\d{minZeichen;maxZeichen})\D" - also umschossen von NON DIGIT (keine Zahlen), bekommen wir das Ergebnis, das wir wollen.
Eine entsprechend angepasste Funktion, die zwischen den beiden Methoden umschaltet, würde dann beispielsweise so aussehen: (die ist schon um einiges Länger)
Finde Zahl
Public Function FindeZahl(myRange As Range, minLaenge As Integer, maxLaenge As Integer, _Optional iGroup As Integer = 1, Optional nichtLaenger As Boolean = True) As VariantDim tmpStr As String tmpStr = myRange.Value If IsNumeric(tmpStr) Then 'wenn es nur eine Zahl ist If nichtLaenger = False Then 'wenn die Zahl auch Länger sein darf If (Len(tmpStr) >= minLaenge) Then 'dann muss man nur auf die minimale Länge achten FindeZahl = CLng(Left(tmpStr, maxLaenge)) 'gib die ersten Zahlen bis zur maxLaenge zurück Else 'wenn die Zahl zu kurz ist FindeZahl = "" 'gib nix zurück End If Else 'wenn die Zahl nicht länger sein darf If (Len(tmpStr) >= minLaenge) And (Len(tmpStr) = maxLaenge) Then 'dann muss die Zahl genau die richtige Länge haben FindeZahl = CLng(tmpStr) Else 'sonst FindeZahl = "" 'gib nix zurück End If End If 'ende nichtLaengerElse 'wenn es nicht nur eine Zahl ist, sondern auch Text vorkommt 'dann werden reguläre Ausdrücke angewendet Dim objRegex As Object Dim objMatch As Object Set objRegex = CreateObject("VbScript.Regexp") With objRegex If nichtLaenger = False Then 'wenn die Zahl auch länger sein darf .Pattern = "\d{" & minLaenge & "," & maxLaenge & "}" 'benötigen wir nur die ersten X Nummern .Global = True Set objMatch = .Execute(tmpStr) If objMatch.Count >= 1 Then FindeZahl = objMatch(iGroup - 1) Else 'wenn nichts gefunden wird FindeZahl = "" End If Else 'wenn die Zahl nicht länger sein darf .Pattern = "\D(\d{" & minLaenge & "," & maxLaenge & "})\D" 'muss es sich um eine Zahl (\d) umschlossen von Nichtzahlen (\D) handeln .Global = True Set objMatch = .Execute(tmpStr) If objMatch.Count >= 1 Then FindeZahl = objMatch(iGroup - 1).SubMatches(0) Else 'wenn nichts gefunden wird FindeZahl = "" End If End If End With Set objMatch = Nothing Set objRegex = NothingEnd IfEnd Function
Das liefert genau das Ergebnis, das man haben will
Und zum Abschluss noch die Gegenüberstellung der beidem Methoden