Prozeduren: Unterschied zwischen den Versionen
Pwania (Diskussion | Beiträge) |
Pwania (Diskussion | Beiträge) |
||
Zeile 282: | Zeile 282: | ||
* Das ParamArray muss den Datentyp 'Variant' aufweisen | * Das ParamArray muss den Datentyp 'Variant' aufweisen | ||
* Vor 'ParamArray' darf weder 'ByVal' noch 'Byref' angegeben werden | |||
* Das ParamArray muss der einzige oder zuletzt angegebene Parameter sein | |||
* Die einzelnen Elemente können mit einer 'For Each'-Schleife durchlaufen werden | * Die einzelnen Elemente können mit einer 'For Each'-Schleife durchlaufen werden | ||
Beachten | ;Bitte Beachten | ||
* Auf diese Weise können keine benutzerdefinierten Datentypen ('Type') übergeben werden, da sich diese nicht in Variants umwandeln lassen! | |||
* Der Datentyp 'Variant' kann jeden beliebigen anderen Datentyp aufnehmen (außer benutzerdefinierten Datentypen 'Type'), also kann auch eine Mischung von Datentypen übergeben werden (Zahl, Text, Objekte etc.). Bitte bitte bitte tun Sie dies niemals, rechnen Sie jedoch immer damit!! | |||
;Beispiel: | |||
Eine Funktion soll das Ergebnis der Addition von beliebig vielen Summanden zurückgeben. | |||
<span style="Color:blue">Public Function </span>CalculateAddition<span style="Color:gray">(</span>ParamArray varTerms<span style="Color:gray">()</span><span style="Color:blue"> As Variant</span><span style="Color:gray">)</span><span style="Color:blue"> As Double</span> | |||
<span style="Color:blue"> Dim </span>dblResult<span style="Color:blue"> As Double</span> | |||
<span style="Color:blue"> Dim </span>varThisTerm<span style="Color:blue"> As Variant</span> | |||
<span style="Color:blue"> For Each </span>varThisTerm In varTerms | |||
<span style="Color:blue"> If </span>IsNumeric<span style="Color:gray">(</span>varThisTerm<span style="Color:gray">)</span> <span style="Color:gray">=</span><span style="Color:blue"> True Then </span> <span style="Color:green">' varThisTerm könnte auch Text oder ein Objekt sein und daher keine Zahl</span> | |||
dblResult <span style="Color:gray">=</span> dblResult <span style="Color:gray">+</span> varThisTerm | |||
<span style="Color:blue"> End If</span> | |||
<span style="Color:blue"> Next </span>varThisTerm | |||
CalculateAddition <span style="Color:gray">=</span> dblResult<span style="Color:blue"> | |||
End Function</span> | |||
<span style="Color:blue"> | |||
Private Sub </span>Test<span style="Color:gray">()</span> | |||
Debug<span style="Color:gray">.</span>Print CalculateAddition<span style="Color:gray">(1,</span> <span style="Color:gray">2,</span> <span style="Color:gray">3.4,</span> <span style="Color:gray">5,</span> <span style="Color:gray">-6,</span> <span style="Color:gray">7)</span> <span style="Color:green">' 12,4</span> | |||
Debug<span style="Color:gray">.</span>Print CalculateAddition<span style="Color:gray">(5)</span> <span style="Color:green">' 5</span> | |||
Debug<span style="Color:gray">.</span>Print CalculateAddition<span style="Color:gray">()</span> <span style="Color:green">' 0</span> | |||
<span style="Color:blue">End Sub</span> |
Version vom 19. November 2019, 14:32 Uhr
Sub-Prozeduren
Einfache Unterprozeduren
Der Rumpf einer Sub-Prozedur wird in der hier abgebildeten Form definiert:
Sub SubProcedureName() MsgBox "Hallo!" End Sub
Diese Prozedur kann nun direkt ausgeführt (F5 oder 'Ausführen' im VBA-Editor wählen) oder von einer anderen Prozedur aufgerufen werden:
Sub CallSubProcedureName() SubProcedureName ' Aufruf der Prozedur durch Angabe des Namens End Sub
Sub-Prozedur mit Übergabeparameter(n)
Wenn die Ausführung einer Prozedur zusätzliche Informationen erfordert, können diese in sogenannten Übergabeparametern (Argumenten) untergebracht werden.
- Übergabeparameter werden zu einem wichtigen Bestandteil der Prozedur
- Übergabeparameter gelten innerhalb der Prozedur als eigene Variablen und können als solche verwendet werden
- Die Namen der Übergabeparameter müssen nicht für den Aufruf aus einer anderen Prozedur verwendet werden, lediglich die Reihenfolge muss eingehalten werden
- Beispiel mit einem Übergabeparameter
Sub SubProcedureWithArgument(ByVal strArgument As String) ' Rumpf einer Sub-Prozedur mit einem Argument in den runden Klammern, ' welches als Zeichenkette erwartet wird. ' Dieses Argument ist ein wichtiger Bestandteil der Prozedur und wird in die Befehlskette ' integriert: ' Beispiel: Ein Dialog zeigt den übergebenen Text an MsgBox strArgument ' Eine Prozedur mit Übergabeparametern kann NICHT direkt ausgeführt werden, ' denn der VBA-Editor kann der Prozedur nicht die geforderten Informationen liefern. End Sub
Sub CallSubProcedureWithArgument() ' Aufruf der Prozedur: SubProcedureWithArgument "Hallo!" End Sub
- Beispiel mit mehreren Übergabeparametern
Sub SubProcedureWithArguments(ByVal strArgument As String, ByVal intSecondArgument As Integer) ' Wenn eine Prozedur mehrere Argumente benötigt, werden diese mit Kommata getrennt angegeben ' Beispiel: Ein Dialog zeigt den übergebenen Text an und das Ergebnis der quadierten Zahl MsgBox strArgument & vbNewLine & "Die Zahl " & intSecondArgument & " im Quadrat: " & intSecondArgument ^ 2 End Sub
Sub CallSubProcedureWithArguments() ' Aufruf der Prozedur: ' Beim Aufruf einer Prozedur mit Argumenten werden KEINE Klammern angegeben! SubProcedureWithArguments "Hallo", 27 End Sub
Funktionen
Funktionen sind spezielle Formen von Sub-Prozeduren, welche nach Erfüllung ihrer Aufgabe ein Ergebnis zurückliefern.
Deklaration
- Beispiel einer einfachen Funktion
Function FunctionName() As String ' Der Funktionsrumpf ist dem der Sub-Prozedur sehr ähnlich, erhält aber zusätzlich einen Datentyp ' Der Datentyp bestimmt, welche Art von Ergebnis zurückgegeben wird ' Der Name der Funktion wird innerhalb der Funktion als Variable verwendet und gibt so den ' gewünschten Wert zurück FunctionName = "Rückgabewert" End Function
- Beispiel einer Funktion mit Übergabeparameter(n)
Function FunctionWithArguments(ByVal strArgument As String, ByVal intSecondArgument As Integer) As String ' Die Erweiterung einer Funktion um Argumente erfolgt analog zur Sub-Prozedur mit Argumenten ' Beispiel: diese Funktion wiederholt den ersten Buchstaben des angegebenen Text so oft, ' wie im zweiten Argument angegeben ist FunctionWithArguments = String(intSecondArgument, strArgument) End Function
Aufruf (Klammersetzung)
Beim Aufruf von Funktionen müssen wir im VBA die besondere Klammersetzung beachten. Bitte sehen Sie sich hierzu folgende Prozedur mit all seinen Kommentaren an:
Sub UseFunctions() Dim strResult As String ' Aufruf der Funktion ohne Verwendung des Rückgabewertes wie eine Prozedur FunctionName ' Beispiel: MsgBox-Funktion wird sehr oft aufgerufen, ohne dass der Rückgabewert beachtet wird: ' WICHTIG: KEINE KLAMMERN!!! MsgBox "Hallo!" ' Mehrere Parameter werden wie gehabt durch Kommas getrennt MsgBox "Hallo!", vbOKOnly ' Aufruf mit Verwendung des Rückgabewertes: ' Der Name der Funktion wird wie eine Variable eingesetzt und verwendet strResult = FunctionName Debug.Print FunctionName If FunctionName = "EtwasAnderes" Then MsgBox "Meldung" End If ' Wenn links des Funktionsnamens weitere Anweisungen erscheinen, MÜSSEN Klammern gesetzt werden, ' wenn Übergabeparameter angegeben werden strResult = FunctionName strResult = FunctionName() ' Ohne Argument: Klammern optional strResult = FunctionWithArguments("y", 3) ' Mit Parameter: Klammern nötig! Debug.Print FunctionWithArguments("y", 3) If FunctionWithArguments("a", 3) = "aaa" Then MsgBox "Treffer!" End If ' Beispiel Messagebox: ' Zeigt Meldung an, der gedrückte Knopf zur Bestätigung interesseiert nicht MsgBox "Hallo!" ' Zeigt eine Abfrage an, die Bestätigung wird in der If-Abfrage ausgewertet If MsgBox("Bitte bestätigen", vbYesNo) = vbYes Then MsgBox "Prima!" End If ' Ebenfalls werden Klammern in folgenden Fällen gesetzt: ' Bei Eigenschaften: Cells(1, 2) = "Test" ' Nach dem Befehl mit Parametern erscheint ein '=' ' Bei näher spezifizierten Objekten Cells(1, 2).Select End Sub
Eigenschaften
' 'Property Get' verhält sich identisch zu einer Funktion Private Property Get FirstWord() As String If ActiveDocument.Words.Count > 0 Then FirstWord = ActiveDocument.Words.Item(1).Text End If End Property
' 'Property Let' übernimmt den gewünschten Wert als Parameter. ' Dieser Parameter muss den gleichen Datentyp haben wie ' die 'Property Get'-Funktion Private Property Let FirstWord(ByVal strWord As String) If ActiveDocument.Words.Count = 0 Then ActiveDocument.Range.Text = strWord Else ActiveDocument.Words.Item(1).Text = strWord End If End Property
' 'Property Get' mit Parameter zur Bestimmung des gewünschten Wertes Public Property Get BookmarkText(ByVal strName As String) As String If ActiveDocument.Bookmarks.Exists(strName) = False Then Exit Property BookmarkText = ActiveDocument.Bookmarks.Item(strName).Range.Text End Property
' Wenn Parameter verwendet werden, gilt der letzte Parameter als Übergabewert (Set Parameter). ' Die Anzahl der bestimmenden Parameter (alle Parameter außer dem letzten) ' müssen die gleiche Anzah der gleichen Datentypen der 'Property Get'-Funktion entsprechen! ' ACHTUNG: Die Namen der Parameter müssen ebenfalls übereinstimmen!!! Public Property Let BookmarkText(ByVal strName As String, ByVal strValue As String) Dim rngBookmark As Range If ActiveDocument.Bookmarks.Exists(strName) = False Then MsgBox "Die Textmarke '" & strName & "' kann nicht gefunden werden." Exit Property End If Set rngBookmark = ActiveDocument.Bookmarks.Item(strName).Range ' Die Textmarke wird in dem Moment, in dem der Text neu gesetzt wird, gelöscht. ' Der Bereich nimmt jedoch den neuen Text auf und enthält danach diesen neuen Bereich. rngBookmark.Text = strValue rngBookmark.Bookmarks.Add strName End Property
Private Sub TestFirstWord() Dim strWord As String ' Großer Vorteil von Properties: ' Unter dem gleichen Namen können anhand des Zusammenhangs das Abfragen und das Setzen ' eines Wertes untergebracht werden! strWord = FirstWord FirstWord = "Adresse" Debug.Print FirstWord ' Als Gegensatz mit Funktion und Prozedur: ' Unterschiedliche Benennung -> wie benenne ich die Prozeduren, damit die Intention klar ist? ' ReadValue, WriteValue, ChangeValue, LoadValue, ReturnValue ...? ' Übergabe des neuen Wertes als Parameter -> Nur aus dem Zusammenhang erkennt man, dass dies der neue Wert ist. ' SetBookmarkText "bkmEMail", "b.beispiel@muster.ag" ' strText = GetBookmarkText("bkmDepartment") End Sub
Public Sub SetAndReadBookmarks() Dim strValue As String BookmarkText("bkmAuth") = "Max Muster" BookmarkText("bkmAuthor") = "Berta Beispiel" BookmarkText("bkmDepartment") = "Neue Medien" BookmarkText("bkmPhone") = "+49 1234589" BookmarkText("bkmEMail") = "b.beispiel@muster.ag" strValue = BookmarkText("bkmDepartment") Debug.Print strValue Debug.Print BookmarkText("bkmAuthor") End Sub
Geltungsbereich
Der Geltungsbereich einer Prozedur kann eingeschränkt werden, indem man bei der Definition ein 'Private' voranstellt:
Private Sub SubProcedure() ' ... End Sub
Wenn kein 'Private' der Prozedur vorangestellt ist, wird die Prozedur automatisch als öffentlich ('Public') betrachtet.
Modulweite Prozeduren: 'Private'
Wenn eine Prozedur als 'Private' markiert wird, steht sie ausschließlich solchen Prozeduren zur Verfügung, die sich ebenfalls in diesem Modul befinden. Der Aufruf aus einem anderen Modul ist nicht möglich.
Projektweite Prozeduren: 'Public' in einem Modul
Wenn Sie die Funktionalität einer Prozedur immer und von allen anderen Modulen in Ihrem Projekt zur Verfügung stellen möchten, definieren Sie die Prozedur in einem Modul (nicht in einem Klassenmodul!) und stellen der Definition das 'Public' voran:
Public Sub StartDoingThings() ' ... End Sub
Besondere Regeln bei Klassenmodulen und UserFormen
Grundsätzlich gelten bei Prozeduren in Klassenmodulen die gleichen Regeln, allerdings steht der Inhalt einer Klasse erst dann zur Verfügung, wenn explizit mithilfe einer Variablen darauf zugegriffen wird.
Siehe Variablen: Besondere Geltungsbereiche in Klassen und UserFormen.
Übergabeparameter bzw. Parameter vertiefend betrachtet
Übergabe ByRef / ByVal
Optionale Parameter
Unbestimmte Anzahl von erwarteten Parametern: ParamArray
- Das ParamArray muss den Datentyp 'Variant' aufweisen
- Vor 'ParamArray' darf weder 'ByVal' noch 'Byref' angegeben werden
- Das ParamArray muss der einzige oder zuletzt angegebene Parameter sein
- Die einzelnen Elemente können mit einer 'For Each'-Schleife durchlaufen werden
- Bitte Beachten
- Auf diese Weise können keine benutzerdefinierten Datentypen ('Type') übergeben werden, da sich diese nicht in Variants umwandeln lassen!
- Der Datentyp 'Variant' kann jeden beliebigen anderen Datentyp aufnehmen (außer benutzerdefinierten Datentypen 'Type'), also kann auch eine Mischung von Datentypen übergeben werden (Zahl, Text, Objekte etc.). Bitte bitte bitte tun Sie dies niemals, rechnen Sie jedoch immer damit!!
- Beispiel
Eine Funktion soll das Ergebnis der Addition von beliebig vielen Summanden zurückgeben.
Public Function CalculateAddition(ParamArray varTerms() As Variant) As Double Dim dblResult As Double Dim varThisTerm As Variant For Each varThisTerm In varTerms If IsNumeric(varThisTerm) = True Then ' varThisTerm könnte auch Text oder ein Objekt sein und daher keine Zahl dblResult = dblResult + varThisTerm End If Next varThisTerm CalculateAddition = dblResult End Function Private Sub Test() Debug.Print CalculateAddition(1, 2, 3.4, 5, -6, 7) ' 12,4 Debug.Print CalculateAddition(5) ' 5 Debug.Print CalculateAddition() ' 0 End Sub