Postanowiłem raz jeszcze wrócić do zagadnienia związanego z wyrażeniami regularnymi. Tym razem poszerzę temat o dwa obszary- pobieranie określonego fragmentu n-tego elementu spełniającego kryterium wyszukiwania oraz włączenie RegExp do własnej funkcji użytkownika (UDF).
Spójrzmy na początek na poniższy przykładowy tekst:
Questionnaire results from company web.
Name: John Smith
Phone: 1234567
Name: Jan Kowalski
Phone: 9876545321
Name: Johan Schmitt
Phone: 00112233
Z pomocą RegExp i VBA spróbujemy przygotować rozwiązanie, które umożliwi pobranie np. drugiego imienia i nazwiska (
Jan Kowalski) czy też trzeciego numeru telefonu (
00112233) z naszego przykładowego tekstu.
Trudność pierwsza- musimy odnaleźć fragment tekstu, który zaczyna się od Name. W tym celu nasz wzorzec będzie miał postać:
1 | .Pattern = "Name:\s*(.*)\s* |
W wyniku czego jesteśmy w stanie otrzymać kolekcję składającą się z elementów:
Name: John Smith
Name: Jan Kowalski
Name: Johan Schmitt
Trudność druga- jak pobrać samo imię i nazwisko i pominąć początkowy fragment z wyników wyszukiwania? W tym celu będziemy musieli sięgnąć głębiej w metodę
.Execute. Samo wywołanie tej metody tworzy kolekcję zawierającą wszystkie wystąpienia spełniające kryterium
.Pattern. Istnieje jednak możliwość pobrania określonego fragmentu n-tego elementu sięgając do kolekcji
.SubMatches. Elementami należącymi do tej kolekcji będą wszystkie fragmenty, które zostały ujęte w nawiasach w naszym wzorcu
.Pattern.
Ogólna składnia metody
.Execute wyglądałaby następująco:
1 | .Execute(tekst)(nteWystąpienie).SubMatches(ntyFragment) |
Proponuję zebrać w całość nasz kod. Na początek testowa procedura wywołująca z dodatkowymi komentarzami wewnątrz kodu:
01 | Sub Pobieranie_nTego_Elementu() |
03 | myText = "Questionnaire results from company web." & Chr(13) & _ |
04 | "Name: John Smith" & Chr(10) & _ |
05 | "Phone: 1234567" & Chr(10) & _ |
06 | "Name: Jan Kowalski" & Chr(10) & _ |
07 | "Phone: 9876545321" & Chr(10) & _ |
08 | "Name: Johan Schmitt" & Chr(10) & _ |
12 | Debug.Print GetItem(myText, "Name:\s+(.*)\s*" , 1) |
14 | Debug.Print GetItem(myText, "Phone:\s+(.*)\s*" , 2) |
A teraz funkcja właściwa uwzględniająca przedstawione powyżej istotne elementy metody
.Execute z dodatkowym komentarzem:
01 | Function GetItem( ByVal STR As String , Wzorzec As String , iNum As Long ) |
03 | Dim objRegExp As Object |
04 | Set objRegExp = CreateObject( "vbscript.regexp" ) |
11 | GetItem = .Execute(STR)(iNum).SubMatches(0) |
Po wywołaniu procedury
Pobieranie_nTego_elementu() uzyskamy w oknie immediate dokładnie to czego szukaliśmy, a więc odpowiednio:
Jan Kowalski
00112233
Brak komentarzy:
Prześlij komentarz