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()
-
-
- Public Sub example()
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 !!!"
- End Sub
-
- Sub macro_test()
- If Range("A1") = "" Then
- warning
- End If
-
- End Sub
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"
- ElseIf Not IsNumeric(Range("A1")) Then
- warning "non-numerical value"
- End If
- End Sub
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)
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)
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:
-
- dialog_boxes last_name1
-
-
- dialog_boxes last_name1, first_name1
-
-
- dialog_boxes last_name1, , age1
-
-
- dialog_boxes last_name1, first_name1, age1
'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")
-
-
- dialog_boxes last_name1
-
-
- dialog_boxes last_name1, first_name1
-
-
- dialog_boxes last_name1, , age1
-
-
- 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
-
- If IsMissing(first_name) Then
-
- MsgBox last_name
- Else
- MsgBox last_name & " " & first_name
- End If
-
- Else
-
- If IsMissing(first_name) Then
-
- MsgBox last_name & ", " & age & " years old"
- Else
- MsgBox last_name & " " & first_name & ", " & age & " years old"
- End If
-
- End If
-
- End Sub
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)
-
- var_value = var_value * var_value
- End Sub
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
-
-
- calcul_square var_number
-
-
- Private Sub calcul_square(ByRef var_value As Integer)
-
-
-
- var_value = var_value * var_value
-
-
- End Sub
-
-
- MsgBox var_number
-
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
-
-
- calcul_square var_number
-
-
- Private Sub calcul_square(ByVal var_value As Integer)
-
-
- var_value = var_value * var_value
-
-
- End Sub
-
-
- MsgBox var_number
-
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
- End Function
-
- Sub macro_test()
- Dim result As Double
- result = square(9.876)
- MsgBox result
- End Sub
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: