czwartek, 5 września 2013

Wyrażenia regularne RegExp raz jeszcze

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:

01Sub Pobieranie_nTego_Elementu()
02    Dim myText As String
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) & _
09            "Phone: 00112233"
10  
11    'wzorzec .Pattern ze względu na Name
12    Debug.Print GetItem(myText, "Name:\s+(.*)\s*", 1)
13    'wzorzec .Pattern ze względu na Phone
14    Debug.Print GetItem(myText, "Phone:\s+(.*)\s*", 2)
15End Sub

A teraz funkcja właściwa uwzględniająca przedstawione powyżej istotne elementy metody .Execute z dodatkowym komentarzem:
01Function GetItem(ByVal STR As String, Wzorzec As String, iNum As Long)
02 
03    Dim objRegExp As Object
04    Set objRegExp = CreateObject("vbscript.regexp")
05    
06    With objRegExp
07        .Global = True 'niezbędne ustawienie
08        .Pattern = Wzorzec
09         
10        'kluczowa konstrukcja metody i kolekcji SubMatches
11        GetItem = .Execute(STR)(iNum).SubMatches(0)
12        
13    End With
14End Function

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