Kurs VBA – cz. 14 – Pętle

W poprzedniej części poznaliśmy metodę sterowania programem przy pomocy instrukcji warunkowych. Teraz do sterowania programem użyjemy konstrukcji zwanych pętlami.
Pozwalają one wykonywać ten sam fragment kodu kilka razy. Oczywiście ilością powtórzeń możemy sterować i może być inna przy każdym wykonaniu tego samego programu. Kod wewnątrz pętli może nawet wcale się nie wykonać.
Przerwaniem lub zakończeniem pętli nazywamy przejście od wykonywania kodu wewnątrz pętli do wykonywania instrukcji bezpośrednio po niej. Iteracja  jest jednorazowym wykonaniem pętli.


Do until / Do while

Ta pętla służy do wykonania fragmentu kodu pewną ilość razy. Najprostsza wersja składa się tylko z klamry Do…loop. Nie uruchamiaj tego kodu!

 

Jest to przykład tak zwanej nieskończone pętli, która będzie omówiona później. Jej działanie nigdy nie będzie przerwane. Kolejne przykłady można już bezpiecznie testować.

Do pętli możemy dodać warunki while lub until, które mogą przerwać wykonywanie.

 

Kluczowe są tutaj słowa zaznaczone na zielono. While można przetłumaczyć jako „dopóki warunek jest prawdziwy” (podczas gdy) a Until jako „dopóki warunek nie jest prawdziwy” (dopóki). Widać to w powyższym przykładzie. Wszystkie cztery pętle zostaną przerwane, kiedy klikniemy „Nie”.

Słowa kluczowa until i while możemy umieścić na początku i końcu pętli. Kiedy umieścimy je na początku, pętla może nie wykonać się ani razu, czyli nie zrealizować nawet jednej iteracji. Umieszczając warunek na końcu mamy zagwarantowane, że przed jego sprawdzenie kod pętli raz się wykona.

For … Loop

Pętla for pozwala nam wykonać kod określoną ilość razy. W najprostszej postaci wygląda tak:

 

Pętla ta wymaga dodatkowej zmiennej do przechowywania licznika pętli. Zmienna może mieć dowolną nazwę, musi być jednak typu liczbowego. Przed pierwszym wykonaniem przyjmuje on wartość zaznaczoną na niebiesko. Po każdym wykonaniu licznik zwiększany jest o jeden (instrukcja next). Pętla jest przerywana kiedy licznik jest większy od wartości czerwonej.

Pętlę można zmodyfikować o słowo kluczowe Next, które określa o ile ma zwiększać (lub zmniejszać) się licznik.

Dlaczego wywołanie drugiej pętli wywoła błąd?

For Each … Loop

Tą pętlę wykorzystuję najczęściej. Wykonuje ona zawarty w sobie kod dla każdego elementu określonej kolekcji. Tą kolekcją jest najczęściej zestaw komórek w zakresie, ale może też być kilka wykresów, arkuszy. Jeżeli kolekcja będzie pusta (np. kolekcja komentarzy w arkuszu) to pętla nie wykona się nawet raz.

Przed wykonaniem pętli musimy zadeklarować zmienną, która będzie przechowywać poszczególne elementy kolekcji. Obejrzyjmy kilka najczęstszych zastosowań tej pętli.

Na początek przeglądanie komórek w zakresie:

Teraz przeglądanie wierszy w zakresie:

 

Różne metody odwołania do komórek znajdziemy w poprzedniej części kursu.

Inną kolekcję używamy do przeglądania arkuszy:

Przy pomocy poniższej kolekcji usuniemy wszystkie komentarze.

 

Do prawidłowego wykorzystania tej pętli potrzebna jest znajomość modelu obiektowego Excela.

Exit Do / Exit  For

Przy pomocy powyższych instrukcji możliwe jest przerwanie działania pętli w dowolnym momencie bez sprawdzania odpowiednich warunków.

Powyższa pętla może się zakończyć mimo, że sama nie ma warunków while ani until.

W powyższym przypadku licznik nie osiągnie wartości końcowej 10, ponieważ pętla zostanie wcześniej przerwana.

Nieskończone pętle

Naturalnie w komputerach nie ma nic nieskończonego w sensie matematycznym. Każdy program kiedyś przerwie działanie. Skończy się prąd, pamięć lub komputer się po prostu zepsuje. Nieskończoną pętlą nazywamy taką, która nigdy nie pozwoli wykonać się kodowi po niej umieszczonemu. Czyli nie ma warunku przerwania tej pętli lub nigdy się nie spełni. np.:

Powyższe przykłady są dość oczywiste i pewnie nikt specjalnie takiego kodu nie napiszę. Tworzenie nieskończonych pętli jest jednak częstym błędem. Należy zawsze sprawdzać (przed uruchomieniem programu, czyli „na sucho”), czy nasz warunek przerwania pętli ma szansę się spełnić. np.:

CzyPrzerwać jest funkcją, należy sprawdzić, czy ma ona szansę zwrócić False.

Licznik jest modyfikowany nie tylko przez instrukcję Next, ale i wewnątrz pętli przez funkcję. Może nigdy nie będzie większy niż 10, co jest warunkiem przerwania działania.

Pętla w pętli

Jeżeli czytałeś poprzednie części kursu, na pewno nie zaskoczy Cię, że jedną pętlę można umieścić w drugiej. Poniżej prosty przykład tworzący tabliczkę mnożenia.

Oczywiście można w ten sposób stworzyć kilka poziomów i mieszać różne rodzaje pętli.

<< cz. 13 – Instrukcje warunkowe | Spis treści | cz. 15 – Funkcje wbudowane >>Subskrybuj RSS, lub polub blog na Facebooku aby otrzymywać najnowsze informacje o rozwoju kursu.

Zapraszam do zadawania pytań w komentarzach.

Comments 8

  1. Dzień dobry, mam problem. Staram się napisać makro, które będzie działało w następujący sposób:

    Makro ma liczyć średnią liczb podanych przez użytkownika (najchętniej poprzez InputBox,dowolna ilość liczb). Podczas dodania ilości liczb poniżej 5 ma normalnie dodawać i pokazywać komunikat z wynikiem. Gdy dodawana ma być 5 liczba to powinien pokazać się komunikat w stylu „czy na pewno chcesz dalej dodawać?” Tak- pobieranie kolejnej/kolejnych liczb/y od użytkownika i dodawane do sumy poprzednich, Nie- pokazuje komunikat ze średnią podanych liczb przed komunikatem.

    Głównie używałam pętli For (raz jednej,raz dwóch) i instrukcji warunkowych, trochę prób z pętlą Do…Loop i zawsze jednak działa w którymś momencie źle. Raz bliżej, raz dalej zamierzonego celu, ale nigdy dobrze :).

    Z góry dziękuję za pomoc!

    1. Post
      Author
      1. W sumie wersji było dużo, wiele niezapisanych. Ostatnia zapisana to ta:
        (działa mniej więcej tak jak chce, ale źle liczy wynik, a nie mam pomysłu przez co podzielic sumę w ostatnim MsgBox, bo przez licznik nie mogę (chyba))

        Sub srednia()
        Dim licznik As Byte
        Dim x As Single
        Dim suma As Single
        Dim n As Byte
        Dim n1 As Byte
        suma = 0
        n = InputBox(„Ile wprowadzisz liczb całkotwitych?”, „Średnia liczb całkowitych”, „n to…”)
        For licznik = 1 To n
        If licznik 5 Then
        x = InputBox(„Podaj x” & licznik, „Średnia liczb naturalnych”, „liczba…”)
        suma = x + suma
        Else
        If MsgBox(„Czy chcesz podawać dalej liczby?”, vbYesNo, „Średnia”) = vbNo Then
        MsgBox „Średnia arytmetyczna = ” & suma / n
        Else
        n1 = InputBox(„Ile podasz nastepnych?”)
        x = InputBox(„Podaj x” & licznik, „Średnia liczb naturalnych”, „liczba…”)
        suma = x + suma
        End If
        End If
        Next
        MsgBox „Średnia arytmetyczna = ” & suma / (n1+n)
        End Sub

        1. Post
          Author

          Ciesze się, że spróbowała Pani sama rozwiązać zadania. Rzeczywiście może być zawiłe pod względem algorytmu. Ja bym je rozwiązał tak:

  2. Witam!

    W części o nieskończonych pętlach zabrakło – moim zdaniem – bardzo cennej rady. Jeśli już uruchomi się taką pętlę, działanie makra można przerwać kombinacją klawiszy Ctrl+Break.

    Pozdrawiam 🙂

  3. Witam,

    Generuję dokładnie te same raporty codziennie. W tabeli przestawnej mam tak skonstruowany filtr jak poniżej. Problem polega na tym, że te nazwy nie występują w każdym tygodniu i w tym momencie Makro pokazuję błąd. Potrzebował bym zmienić ten kod aby w pierwszej kolejności, kod był sprawdzany czy istnieje czy nie – w przypadku gdy nie to ignoruje, a w przypadku gdy istnieje to go odznacza w filtrze. Wydaje mi się, że mogę to zrobić przy pomocy If.. Else, ale do końca nie wiem jak. Proszę o pomoc.

    ActiveSheet.PivotTables(„Tabela_przestawna_QR4_1”).PivotFields( _
    „dept_short_desc”).CurrentPage = „(All)”
    With ActiveSheet.PivotTables(„Tabela_przestawna_QR4_1”).PivotFields( _
    „dept_short_desc”)
    .PivotItems(„Dyehouse”).Visible = False
    .PivotItems(„Knitting-Alfreton”).Visible = False
    .PivotItems(„Stenters”).Visible = False
    .PivotItems(„Weaving”).Visible = False
    End With
    ActiveSheet.PivotTables(„Tabela_przestawna_QR4_1”).PivotFields( _
    „dept_short_desc”).EnableMultiplePageItems = True

    1. Post
      Author

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *