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!
1 2 3 4 |
Do Selection.Cells(1, 1) = "test" Selection.Offset(1, 0).Select Loop |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Do While MsgBox("Kontynuować?", vbYesNo) = vbYes Selection.Cells(1, 1) = "test" Selection.Offset(1, 0).Select Loop Do Selection.Cells(1, 1) = "test" Selection.Offset(1, 0).Select Loop While MsgBox("Kontynuować?", vbYesNo) = vbYes Do Until MsgBox("Kontynuować?", vbYesNo) = vbNo Selection.Cells(1, 1) = "test" Selection.Offset(1, 0).Select Loop Do Selection.Cells(1, 1) = "test" Selection.Offset(1, 0).Select Loop Until MsgBox("Kontynuować?", vbYesNo) = vbNo |
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:
1 2 3 4 5 |
Dim licznik As Integer For licznik = 1 To 10 Selection.Cells(licznik, 1) = "test " & licznik Next licznik |
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.
1 2 3 4 5 6 7 |
For licznik = 1 To 10 Step 2 Selection.Cells(licznik, 1) = "test " & licznik Next licznik For licznik = 1 To -10 Step -2 Selection.Cells(licznik, 1) = "test " & licznik Next 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:
1 2 3 4 5 |
Dim lr_RoboczaKomorka As Range For Each lr_RoboczaKomorka In Selection lr_RoboczaKomorka = "test" Next lr_RoboczaKomorka |
Różne metody odwołania do komórek znajdziemy w poprzedniej części kursu.
Inną kolekcję używamy do przeglądania arkuszy:
1 2 3 4 5 |
Dim lr_RoboczyArkusz As Worksheet For Each lr_RoboczyArkusz In Worksheets lr_RoboczyArkusz.Tab.Color = vbGreen Next lr_RoboczyArkusz |
Przy pomocy poniższej kolekcji usuniemy wszystkie komentarze.
1 2 3 4 5 |
Dim lr_RoboczyKomentarz As Comment For Each lr_RoboczyKomentarz In ActiveSheet.Comments lr_RoboczyKomentarz.Delete Next lr_RoboczyKomentarz |
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.
1 2 3 4 5 6 7 8 |
Do Selection.Cells(1, 1) = "test" Selection.Offset(1, 0).Select If MsgBox("Kontynuować?", vbYesNo) = vbNo Then Exit Do End If Loop |
Powyższa pętla może się zakończyć mimo, że sama nie ma warunków while ani until.
1 2 3 4 5 |
For i = 1 To 10 If i = 5 Then Exit For End If Next i |
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.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Do MsgBox "To się nigdy nie skończy, brak warunku." Loop Do While True MsgBox "To się nigdy nie skończy, warunek zawsze prawdziwy." Loop Do MsgBox "To się nigdy nie skończy, warunek zawsze fałszywy." Loop Until False For licznik = 1 To 10 Step -1 MsgBox "To się nigdy nie skończy, licznik nigdy nie będzie" & _ " większy niż 10." Next licznik |
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.:
1 2 3 |
Do While CzyPrzerwac MsgBox "Czy to się skończy?" Loop |
CzyPrzerwać jest funkcją, należy sprawdzić, czy ma ona szansę zwrócić False.
1 2 3 |
For i = 1 To 10 i = NowaWartosc_i Next i |
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.
1 2 3 4 5 6 7 8 |
Dim i As Integer Dim j As Integer For i = 1 To 10 For j = 1 To 10 Cells(i, j) = i * j Next j Next i |
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
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!
Author
Dzień dobry,
Proszę pokazać co Pani napisała. Postaram się coś doradzić.
Pozdrawiam
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
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:
Dziękuję bardzo za pomoc.
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 🙂
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
Author
Myślę, że najłatwiej na chwilę wyłączyć standardową obsługę błędów. On Error Resume Next .
http://www.123office.pl/2014/05/kurs-vba-cz-18-obsuga-bedow.html