TOP

VBA-Lekcja 9. Procedury i funkcje

W każdym języku programowania istnieją takie pojęcia jak procedury i funkcje. Zostały one również uwzględnione we wbudowanym języku programowania VBA dla Excel.

  • Funkcja to procedura zwracająca wynik. Wywołanie funkcji jest wyrażeniem i może być użyte w innych wyrażeniach lub po prawej stronie instrukcji przypisania (oznaczone w VBA jako "Function");
  • Procedura to dowolna procedura, która nie jest funkcją. Oznaczone w VBA jako „Sub” (od słowa „podprogram”).

  • Procedury (Public - Private)

    W tym momencie wszystkie utworzone przez nas procedury są typu Public, co oznacza, że są dostępne z dowolnego modułu.

     Sub example()
     
     'Identyczne z:
     Public Sub example()
    

    Aby procedura była dostępna tylko w określonym module, stosuje się słowo kluczowe Private:

    Private Sub example()
    

    Uruchamianie procedury ze środka innej procedury

    Aby wykonać procedurę z poziomu innej procedury, wystarczy wpisać jej nazwę.

    Oto bardzo prosty przykład:

    Private Sub warning()
        MsgBox "Caution !!!" '"OSTRZEŻENIE!"
    End Sub
    
    Sub macro_test()
        If Range("A1") = "" Then
            warning '=> wykonaj procedurę „warning”
        End If
        'itp...
    End Sub
    

    Argumenty

    Argumenty umożliwiają wykorzystanie wartości z procedury w podprocedurze (pamiętaj, że domyślnie zmienne są dostępne tylko z procedury, w której zostały zadeklarowane).

    Private Sub warning(var_text As String)
        MsgBox "Caution : " & var_text & " !"
    End Sub
    
    Sub macro_test()
        If Range("A1") = "" Then
            warning "empty cell"               '„pusta komórka”
        ElseIf Not IsNumeric(Range("A1")) Then
            warning "non-numerical value"      '„wartość nienumeryczna”
        End If
    End Sub
    

    Do procedury „warning” dodano argument, w tym przypadku jest to zmienna „var_text” typu „String” (wstążka):

    Private Sub warning(var_text As String)
    

    Ta procedura przyjmuje argument, więc aby ją wykonać, musimy umieścić wartość po „warning”:

    warning "empty cell"
    

    Gdy chcemy napisać kilka argumentów, wówczas należy je oddzielić przecinkami.

    Opcjonalne argumenty

    Domyślnie, jeśli procedura posiada argumenty, to należy je podać, a jeśli nie zostaną podane, to procedura nie zostanie wykonana.

    Opcjonalny argument można dodać po obowiązkowym, używając słowa kluczowego Opcjonalne. Przykład:

    Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
    

    Tę procedurę można teraz wykonać z opcjonalnym argumentem lub bez niego, jak tutaj:

     'Przykład 1: wyświetl nazwisko:
     dialog_boxes last_name1
       
     'Przykład 2: wyświetlamy nazwisko i imię:
     dialog_boxes last_name1, first_name1
       
     'Przykład 3: wyświetl nazwisko i wiek:
     dialog_boxes last_name1, , age1
       
     'Przykład 4: wyświetl nazwisko, imię i wiek:
     dialog_boxes last_name1, first_name1, age1
    

    Argumenty należy wprowadzić we właściwej kolejności.

    Aby sprawdzić, czy w procedurze występuje opcjonalny argument, używamy funkcji IsMissing. Ta funkcja jest kompatybilna tylko z niektórymi typami funkcji (typu Variant) i jest to krytyczne, ponieważ nie zadeklarowano typu opcjonalnych argumentów (niezadeklarowany typ = Variant).

    Oto przykład wykorzystujący dwa fragmenty kodu omówione powyżej:

    Sub macro_test()
    
        Dim last_name1 As String, first_name1 As String, age1 As Integer
       
        last_name1 = Range("A1")
        first_name1 = Range("B1")
        age1 = Range("C1")
    
        'Przykład 1: wyświetl nazwisko:
        dialog_boxes last_name1
       
        'Przykład 2: wyświetlamy nazwisko i imię:
        dialog_boxes last_name1, first_name1
       
        'Przykład 3: wyświetl nazwisko i wiek:
        dialog_boxes last_name1, , age1
       
        'Przykład 4: wyświetl nazwisko, imię i wiek:
        dialog_boxes last_name1, first_name1, age1
    
    End Sub
    
    Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
       
        If IsMissing(age) Then 'Jeśli brakuje zmiennej wieku...
           
            If IsMissing(first_name) Then 'Jeśli brakuje zmiennej imię_imię, to
            							  'zostanie wyświetlone tylko nazwisko
               MsgBox last_name
            Else 'W przeciwnym razie zostanie wyświetlone nazwisko i imię
               MsgBox last_name & " " & first_name
            End If
           
        Else 'Jeśli zmienna wieku jest obecna...
    
            If IsMissing(first_name) Then 'Jeśli brakuje zmiennej imię_imię, to
                                          'wyświetli się nazwisko i wiek
               MsgBox last_name & ", " & age & " years old"
            Else 'W przeciwnym razie zostanie wyświetlone nazwisko, imię i wiek
               MsgBox last_name & " " & first_name & ", " & age & " years old"
            End If
       
        End If
           
    End Sub
    

    Widzieć zdjęcie poniżej (przykład 1):

    ByRef - ByVal

    Domyślnie argumenty są typu ByRef, co oznacza, że jeśli zmienna zostanie przekazana jako argument, zostanie również przekazane odwołanie do niej. Innymi słowy, jeśli zmienna została zmieniona przez inną podprocedurę, zostanie ona również zmieniona w procedurze zewnętrznej, która wywołuje tę podprocedurę.

    Przykład:

    Sub macro_test()
        Dim var_number As Integer
        
        var_number = 30
        calcul_square var_number
       
        MsgBox var_number
    End Sub
    
    Private Sub calcul_square(ByRef var_value As Integer) 'ByRef jest opcjonalne
                                                          '(jest wartością domyślną)
        var_value = var_value * var_value
    End Sub
    

    Aby było jasne, poniżej znajduje się przykład tego, co się stanie, jeśli makro zostanie uruchomione:

     var_number = 30
     'Początkowa wartość zmiennej „var_number” wynosi 30
    
     calcul_square var_number
     'Podprocedura jest uruchamiana z argumentem „var_number”.
    
     Private Sub calcul_square(ByRef var_value As Integer)
     'Zmienna „var_value” służy w pewnym stopniu do szybkiego dostępu do zmiennej „var_number”,
     'co oznacza, że jeśli zmienna „var_value” zostanie zmieniona, zmienna „var_number” również zostanie zmieniona
     '(i nie muszą mieć tej samej nazwy)
     var_value = var_value * var_value
     'Zmienia się wartość zmiennej „var_value” (a więc jednocześnie zmienia się także „var_number”)
    
     End Sub
     'Koniec podprocedury
    
     MsgBox var_number
     'Zmienna „var_number” została zmieniona i w oknie dialogowym będzie teraz wyświetlana liczba 900
    

    Drugą metodą jest użycie ByVal.

    W przeciwieństwie do ByRef, które przekazuje referencję (etykietę), ByVal przekazuje wartość, co oznacza, że wartość przekazana jako argument nie została zmodyfikowana.

    Poniżej możesz zobaczyć, jak działa poprzedni kod i ByVal:

     var_number = 30
     'Początkowa wartość zmiennej „var_number” wynosi 30
    
     calcul_square var_number
     'Podprocedura jest uruchamiana z argumentem „var_number”.
    
     Private Sub calcul_square(ByVal var_value As Integer)
     'Zmienna „var_value” kopiuje wartość zmiennej „var_number” (obie zmienne nie są ze sobą powiązane)
    
     var_value = var_value * var_value
     'Wartość zmiennej „var_value” uległa zmianie
    
     End Sub
     'Koniec podprocedury (w tym przykładzie podprocedura nie ma na nic wpływu)
    
     MsgBox var_number
     'Zmienna „var_number” nie została zmieniona, dlatego w oknie dialogowym zostanie wyświetlona liczba 30
    

    O czym musisz pamiętać: Użyj ByVal, gdy zmienna nie powinna być zmieniana.

    Funkcje

    Główna różnica między procedurą a funkcją polega na tym, że funkcja zwraca wartość.

    Oto prosty przykład:

    Function square(var_number)
        square = var_number ^ 2 'Funkcja „kwadrat” zwraca wartość „pierwiastka kwadratowego”.
    End Function
    
    Sub macro_test()
        Dim result As Double
        result = square(9.876) 'Zmiennej wynikowej przypisuje się wartość obliczoną przez funkcję
        MsgBox result 'Wyświetlany jest wynik (w tym przypadku kwadrat 9,876)
    End Sub
    

    Funkcji można używać w arkuszu, tak jak każdej innej funkcji w Excel.

    Na przykład, aby uzyskać kwadrat wartości wprowadzonej w komórce A1: