środa, 3 lipca 2013

Testowanie zgodności ciągów tekstowych- podstawy- 1/2

Niniejsze zagadnienie ma swoje szerokie zastosowanie w całym środowisku VBA i nie dotyczy tylko Excela i Worda lecz wszystkich aplikacji MS Office. Mało tego, spokojnie można stwierdzić, że temat ten jest powszechnym zagadnieniem we wszystkich językach programowania. My spojrzymy jednak na to wyłącznie przez pryzmat VBA.

Ogólnie rzecz ujmując temat na najbliższych kilka postów to poszukiwanie odpowiedzi na pytanie: jak sprawdzić, czy określony ciąg tekstowy spełnia wskazane kryteria? Postaram się przedstawić dostępne techniki lecz nie sposób będzie zaprezentować wszystkich możliwych rozwiązań, schematów czy parametrów. Jest to temat wyjątkowo szeroki i zależny od indywidualnych problemów z jakimi mierzy się każdy programista. Spojrzymy na zagadnienie przez pryzmat rozwiązań prostych (2 posty) oraz możliwość zastosowania `wyrażeń regularnych RegExp` (kilka kolejnych wpisów).

Zaczynamy od rozwiązań najprostszych. Przyjmijmy założenie, że nasz tekst bazowy to:
A = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit."

1. Czy w tekście A znajduje się tekst B? 
W tym wariancie wystarczy wykorzystać funkcję InStr
1B = "sit"
2Debug.Print InStr(1, A, B) > 0                  'wynik TRUE

Należy jednak pamiętać, że porównania tekstowe standardowo dokonywane są binarnie, a więc uwzględniają wielkość liter. Aby pominąć tą niedogodność sięgnijmy po jedno z dwóch poniższych rozwiązań:
1B = "Sit"
2Debug.Print InStr(1, A, B) > 0                  'wynik FALSE
3Debug.Print InStr(1, UCase(A), UCase(B)) > 0    'wynik TRUE
4Debug.Print InStr(1, A, B, vbTextCompare) > 0   'wynik TRUE

2. Czy tekst A zaczyna się od tekstu B?
Tu wystarczy sięgnąć po funkcję Left pamiętając ponownie, że porównanie odbywa się w binarnie.
1B = "lorem"
2Debug.Print Left(A, Len(B)) = B                 'wynik FALSE
3Debug.Print UCase(Left(A, Len(B))) = UCase(B)   'wynik TRUE

3. Czy tekst A kończy się tekstem B?
Rozwiązanie będzie podobne jak w punkcie 2 przy czym zastosujemy funkcję Right.
1B = "Elit."
2Debug.Print Right(A, Len(B)) = B                 'wynik FALSE
3Debug.Print UCase(Right(A, Len(B))) = UCase(B)   'wynik TRUE

4. Czy określony tekst B znajduje się na określonej pozycji w tekście A?
Poniższy przykład prezentuje rozwiązanie, w którym sprawdzamy czy tekst B znajduje się w tekście A począwszy od 13 litery.
1B = "dolor"
2tmpVar = 13
3Debug.Print InStr(tmpVar, A, B, vbTextCompare) = tmpVar 'wynik TRUE

2 komentarze:

  1. Jako, że VBA jest case sensitive. Jest jeszcze jeden sposób na obejście problemu wielkości liter. Na początku modułu należy wkleić "Option Compare Text". Wtedy "A" Like "a" daje True.

    OdpowiedzUsuń
    Odpowiedzi
    1. Panie Michale, owszem, technika oparta o 'Option Compare Text' jest alternatywą, ale jest jednocześnie złą praktyką programistyczną. Powoduje, że w całym module (!) wszystkie porównania odbywają się w trybie tekstowym a nie binarnym, a tryb ten jest nieefektywny. Stąd też powszechnie stosowane są rozwiązania oparte o UCase in vbTextCompare. Nie zalecam stosowania 'Option Compare Text'.

      Usuń