vbamania.pl
login:
hasło:
 
  *Rejestracja *Zapomniane hasło
 Dziś jest poniedziałek, 26 lipca 2021 roku.
Ustaw jako stronę startową Ulubione Napisz
Artykuły
Kurs VBA dla zielonych - cz. 3
zamieszczony: 5 listopada 2003
przez: admin
czytany 56571 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