przez:
admin
czytany 25916 razy.
Po długiej przerwie uzupełniam kurs VBA. W części trzeciej na
warsztat bierzemy pętle.
Musimy to jasno i wyraĽnie powiedzieć: Nie da się efektywnie programować
nie znając pętli.
Na szczęście zrozumienie koncepcji pętli jest łatwe.
No więc - co to są te pętle? Pętle to bardzo użyteczne struktury
programistyczne, umożliwiające wykonywanie powtarzających się operacji.
Np. jak wypisać na ekranie kody znaki o kodach ASCII liter od 65 do 75? Można
tak:
Sub WypiszKody1()
Dim strMsg As String
strMsg = Chr(65) & vbCrLf & _
Chr(65) & vbCrLf & _
Chr(66) & vbCrLf & _
Chr(67) & vbCrLf & _
Chr(68) & vbCrLf & _
Chr(69) & vbCrLf & _
Chr(70) & vbCrLf & _
Chr(71) & vbCrLf & _
Chr(72) & vbCrLf & _
Chr(73) & vbCrLf & _
Chr(74) & vbCrLf & _
Chr(75)
MsgBox strMsg
End Sub
Działa, choć mało to eleganckie. Pamiętajmy jednak, że w pewnych sytuacjach bez
pętli nie można się obyć.
Jeżeli zastosujemy pętlę kod będzie bardziej zwarty i zajmie mniej miejsca.
Sub WypiszKody2()
Dim strMsg As String
For i = 65 To 75
strMsg = strMsg & Chr(i) & vbCrLf
Next i
MsgBox strMsg
End Sub
Wykorzystaliśmy tu pętlę For
...Next. Działa ona w sposób następujący: wszelkie instrukcje
występujące pomiędzy słowami kluczowymi
For .... i Next
zostaną powtórzone tyle razy aż zmienna indeksująca (tutaj
i) osiągnie wartość występującą po słowie kluczowym
To.
Innym przykładem może być pętla liczącą z krokiem 2:
For i = 2 To 10
Step 2
...
Next i
albo wstecz:
For intLicznik = 10 To 1
Step -1
...
Next intLicznik
Słowo kluczowe Step
nie jest konieczne i jeżeli je pominiemy pętla liczy w górę z krokiem 1.
W każdej chwili, niezależnie od od stanu licznika możemy opuścić pętle poprzez
użycie instrukcji Exit For.
Pętla For ... Next
jest wygodna w zastosowaniu w przypadku gdy mamy ściśle określoną liczbę kroków
do wykonania.
Jeżeli liczba powtórzeń nie jest znana to wygodniej jest zastosować pętlę
Do...Loop. Składnia tej instrukcji jest następująca:
Do
...
Loop [Until {wyrażenie_logiczne}|While
{wyrażenie_logiczne}]
albo:
Do [Until {wyrażenie_logiczne}|While
{wyrażenie_logiczne}]
...
Loop
Wykonanie pętli Do...Loop
jest zależne od warunków logicznych występujących po słowach kluczowych
Until i While
(pamiętajmy o tym że w kodzie może pojawić się tylko jedno z nich).
Angielskiemu słowu until odpowiada polskie wyrażenie "aż do". Pętla z
tym słowem jest wykonywana aż wyrażenie logiczne osiągnie wartość logicznej
jedynki (True -
prawda).
Natomiast słowo while oznacza "dopóki" i taka pętla wykonywana jest
dopóki wyrażenie logiczne posiada wartość logiczną
True; gdy osiąga ono wartość
False wykonywanie instrukcji w pętli jest przerywane. Wszelkie
sytuacje jakie mogą wystąpić w programie można obsłużyć zarówno przy pomocy
słowa Until jak
i słowa While i
tylko od programisty zależy, które z nich wybierze.
Jeżeli sprawdzenie warunku logicznego występuje w linii ze słowem
Loop (pierwszy przykład), pętla wykona się co najmniej raz,
niezależnie od wartości wyrażenia logicznego.
W poniższym przykładzie komputer najpierw spyta się o liczbę. Jeżeli będzie ona
mniejsza od 1 lub większa od 10 pętla będzie wykonywana - czyli komputer
ponownie poprosi w wpisanie liczby.
Dim strInput as
String
Do
strDigit = InputBox("Podaj cyfrę od 1 do 10")
Loop While Val(strDigit) <
1 And Val(strDigit) > 10
Jeśli sprawdzamy wartość warunku logicznego w linii ze słowem
Do wykonanie pętli zależy od wartości wyrażenia logicznego.
Na poniższym przykładzie komputer poprosi o podanie liczby, która zapamięta w
zmiennej k. Jeżeli będzie ona większa od 2 pętla w której za liczbę k wstawiamy
iloraz k i 2 będzie się wykonywać do momentu, w którym k będzie mniejsze lub
równe 2.
Dim strInput As
String
Dim k As Double
strDigit = InputBox("Podaj dowolna liczbę")
k = Val(strDigit)
Do Until k =< 2
k = k/2
Loop
Wykonywanie pętli Do...Loop
może zostać przerwane w dowolnym momencie poprzez użycie instrukcji
Exit Do
.
Dim strInput as
String
Do
strInput = InputBox("Podaj imię")
If strInput = vbNullString Then
Exit Do
Msgbox "Witaj, " & strInput
Loop
Szczególnym rodzajem pętli jest pętla
For Each..., "przebiegająca" po wszystkich elementach kolekcji.
Jeżeli nie pamiętacie co to jest kolekcja - zaglądnijcie do poprzedniej lekcji.
. A oto przykład użycia tej pętli w którym wszystkie otwarte w Excelu
skoroszyty zostaną zamknięte, a ewentualne zmiany w nich - zapisane.
Dim oWbk As Workbook
For Each oWbk in
Workbooks
oWbk.Close SaveChanges: = True
Next oWbk
Innym przykładem może być pętla wypisująca nazwy wszystkich warstw w bieżącym
rysunku AutoCADa:
Dim oLayer As AcadLayer
Dim strWarstwy As
String
For Each oLayer
in ThisDrawing.Layers
strWarstwy = strWarstwy & oLayer.Name & vbCrLf
Next oLayer
MsgBox strWarstwy
Jak widać pojedynczy element kolekcji jest tutaj reprezentowany przez zmienną
obiektową (oWbk i
oLayer). Jest to bardzo wygodny sposób umożliwiający dostęp do
właściwości i metod grupy obiektów. Istotne jest to, że usuwanie elementów z
kolekcji może odbywać się tylko w pętli
For Each..., użycie do tego pętli np.
For ...Next
spowoduje wygenerowanie komunikatu o błędzie.
Istnieje jeszcze jeden rodzaj pętli w VBA, pętla
While...Wend, ale jest ona tożsama z pętla
Do While...Loop, więc nie będę jej omawiał.
Przykład
Obliczenie silni (!) liczby naturalnej.
Czy wiecie co to jest silnia? Nie? No to śpieszę z wyjaśnieniem: silnia liczby
naturalnej (czyli całkowitej i dodatniej) n - to iloczyn kolejnych liczb
naturalnych od 1 do n.
Dodatkowo przyjmujemy, że 0! = 1. Możemy to zapisać następująco:
n! = 1*2*...*(n-1)*n, n>0
0! = 1
No wiemy już wszystko! Kod programu wygląda następująco:
Option Explicit
Const strNazwaMakra As String
= "Obliczanie silni"
Sub Silnia()
'Deklaracje zmiennych lokalnych
Dim dblSilnia As
Double
Dim strLiczba As
String
Dim lngLiczba As
Long
Dim i As Long
'Pętla Do...Loop, wykonywana dopóty użytkownik poda prawidłowe
dane
Do
'Wyświetlenie okienka do pobrania danych.
strLiczba = InputBox("Podaj liczbę dodatnią, mniejszą od stu",
strNazwaMakra)
'Jeżeli użytkownik nie podał żadnego ciągu
'lub wcisnął przycisk "Cancel" kończymy pracę
programu.
If strLiczba = vbNullString
Then End
'Wychodzimy z pętli Do...Loop, jeżeli użytkownik
podał prawidłą liczbę
If Not IsNumeric(strLiczba)
Then
MsgBox "To nie jest liczba.",
vbInformation, strNazwaMakra
Else
If Val(strLiczba)
< 0 Or Val(strLiczba) > 100 Or
_
(Val(strLiczba) <>
CLng(Val(strLiczba))) Then _
MsgBox "Nieprawidłowa
liczba.", vbInformation, strNazwaMakra _
Else
Exit Do
End If
Loop
'Zamieniamy ciąg (typ String) na liczbę typu Long (całkowitą)
lngLiczba = CLng(Val(strLiczba))
'ustawienie wartości początkowej zmiennej dblSilnia
dblSilnia = 1
'Jeżeli liczba jest większa od zera, obliczamy silnię w pętli.
'Pytanie za sto punktów:
'Dlaczego napisałem pętlę For i = 2 ... a nie
'For i = 1 ..., tak jak jest w definicji silni?
If lngLiczba > 0 Then
For i = 2
To lngLiczba
dblSilnia =
dblSilnia * i
Next i
End If
'wyświetlenie wyniku.
MsgBox "Wynik: " & lngLiczba & "! = " & dblSilnia, vbInformation
End Sub
Trzy skrótowe lekcje to niezbędne minimum, które należy opanować, aby zacząć
programowanie w VBA.
Wielu następnych rzeczy możecie się nauczyć poprzez analizę zamieszczonych
przeze mnie makr i programów.
wstecz