VBA-Funktionen von A bis Z

VBA-Funktionen kann doch jeder programmieren. Funktionsname, Parameter, Rückgabewert – fertig! Es gibt jedoch eine ganze Menge Feinheiten, die man als Programmierer kennen sollte. Dazu gehört beispielsweise das Zurückgeben mehr als eines Ergebniswertes, das übergeben beliebig vieler Parameter oder auch optionale Parameter. Dieser Beitrag liefert alles, was Sie für den Umgang mit Funktionen wissen müssen.

Zur Programmierung von VBA-Funktionen muss man keine Raketentechnik studiert haben. Aber wie bereits in der Einleitung erwähnt, gibt es eine Menge verschiedener Techniken, die alle ihre Berechtigung haben. In diesem Beitrag wollen wir einmal einen überblick über die Möglichkeiten von VBA-Funktionen liefern.

Funktion oder Prozedur

Zunächst müssen wir klären, was genau der Unterschied zwischen einer Sub– und einer Function-Prozedur ist. Dieser liegt genau darin, dass eine Function ein Ergebnis zurückliefert, das über die Zuweisung des Funktionsaufrufs etwa an eine Variable, ein Steuerelement et cetera direkt weiterverarbeitet werden kann. Eine Besonderheit ergibt sich bei der Zuweisung dieses Wertes innerhalb der Funktion: Dieser wird nämlich einer Variablen zugewiesen, die den Namen der Funktion hat. Ein Beispiel sieht so aus:

Public Function NameDesAutors() As String
     NameDesAutors = "André Minhorst"
End Function

Rückgabewert verarbeiten

Diese Funktion weist ihrem Rückgabewert ein String-Literal zu, das beim Aufruf gleich verarbeitet werden kann – zum Beispiel durch die Ausgabe im Direktfenster:

Debug.Print NameDesAutors
André Minhorst

Auf die gleiche Weise können Sie den Rückgabewert der Funktion etwa in eine Variable schreiben und dann im Direktbereich ausgeben:

Public Sub Test_NameDesAutors()
     Dim strNameDesAutors As String
     strNameDesAutors = NameDesAutors
     Debug.Print strNameDesAutors
End Sub

Einfache Parameter

Nun liefern Funktionen, denen Sie keinen Parameter übergeben, nicht unbedingt immer den gleichen Wert zurück – Sie können ja von einer solchen Funktion auch etwa das aktuelle Datum oder die Uhrzeit ermitteln lassen oder Informationen wie den Datenbankpfad.

Allerdings erwarten die meisten Funktionen einen oder mehrere Parameter, auf deren Basis sie das Ergebnis der Funktion ermitteln. Die Parameter einer Funktion werden zunächst im Kopf der Funktion deklariert.

Dabei geben Sie standardmäßig den Datentyp an, da sonst der Datentyp Variant verwendet wird. Die folgende Funktion verkettet die beiden als Parameter übergebenen Zeichenketten:

Public Function Zeichenverkettung( str1 As String, str2 As String) As String
     Zeichenverkettung = str1 & str2
End Function

Der Aufruf und das Ergebnis der Funktion sehen etwa wie folgt aus:

  Zeichenverkettung("Mon","tag")
Montag

Optionale Parameter

Sie können die Parameter einer Abfrage als optionale Parameter definieren. Dazu verwenden Sie das Schlüsselwort Optional vor dem eigentlichen Namen des Parameters. Dabei gibt es einen wichtigen Punkt zu beachten: Hinter einem optionalen Parameter dürfen nur noch weitere optionale Parameter folgen. Anderenfalls löst bereits die Definition der Kopfzeile der Funktion einen Fehler aus (s. Bild 1).

Standardwerte

Wenn Sie sicherstellen wollen, dass der Parameter auch dann einen Wert liefert, wenn die aufrufende Routine keinen Wert für den Parameter übergeben hat, können Sie wie in Listing 1 einen Standardwert angeben. Diesen tragen Sie hinter dem Datentyp, sonst direkt hinter dem Namen des Parameters ein. Wenn Sie dem Parameter der Funktion beim Aufruf einen Wert übergeben, liefert sie das folgende Ergebnis:

Public Function EingabeGleichAusgabe(Optional str1 As String = "Kein Wert angegeben")
     EingabeGleichAusgabe = str1
End Function

Listing 1: Verwendung von Standardwerten für optionale Parameter

  EingabeGleichAusgabe("Wert angegeben")
Wert angegeben

Geben Sie keinen Wert für den Parameter an, verwendet die Funktion den Standardwert:

  EingabeGleichAusgabe
Kein Wert angegeben

Auf optionale Parameter prüfen

Wenn Sie optionale Parameter verwenden, können Sie von Haus aus nur für den Datentyp Variant prüfen, ob der Benutzer diese übergeben hat. Variablen vom Typ Variant können als einziges den Wert Null aufnehmen. Ob der Parameter übergeben wurde, prüfen Sie mit der IsMissing-Funktion. Diese liefert den Wert True zurück, wenn der Parameter leer ist.

übrigens ist IsMissing nicht gleichbedeutend mit IsNull. Dies können Sie mit der Funktion aus Listing 2 prüfen. Wenn Sie die Prozedur komplett ohne Parameter aufrufen, erhalten Sie folgende Ausgabe im Direktfenster:

Public Function OptionaleParameter(Optional str1 As String, Optional var1 As Variant)
     Debug.Print "Fehlt str1", IsMissing(str1), IsNull(str1)
     Debug.Print "Fehlt var1", IsMissing(var1), IsNull(var1)
End Function

Listing 2: Prüfung von optionalen Parametern mit IsMissing

Fehlt str1   Falsch        Falsch
Fehlt var1   Wahr          Falsch

Das heißt, dass eine leere Variant-Variable zwar als fehlend eingestuft wird, aber nicht den Wert Null enthält. Dies können Sie nochmals testen, indem Sie den Wert Null für den Parameter var1 übergeben:

Debug.Print OptionaleParameter("", Null)

Das Ergebnis sieht so aus:

Fehlt str1   Falsch        Falsch
Fehlt var1   Falsch        Wahr

Die Variant-Variable mit dem Wert Null fehlt also nicht und wird mit IsNull korrekt als Null erkannt.

Wenn Sie einen anderen Datentyp als optionalen Parameter verwenden und prüfen wollen, ob die aufrufende Routine einen Wert für diesen übergeben hat, müssen Sie einen kleinen Trick anwenden. Das Werkzeug dafür haben Sie schon kennengelernt – den Standardwert. Geben Sie einfach einen Ausdruck als Standardwert an, der normalerweise nicht übergeben wird.

Wenn die Funktion dann aufgerufen wird, prüfen Sie, ob der Parameter den als Standardwert angegebenen Wert enthält oder einen anderen. Im ersten Fall können Sie dann davon ausgehen, dass kein Parameter übergeben wurde, anderenfalls liegt ein Wert für den Parameter vor.

Ein Beispiel für einen solchen Test zeigt die Funktion StringparameterVorhanden aus Listing 3. Sie verwendet die Zeichenkette **** als Standardwert. Der folgende Aufruf zeigt, wie die Funktion reagiert:

Public Function StringparameterVorhanden(Optional str1 As String = "****") As Boolean
     If Not str1 = "****" Then
         StringparameterVorhanden = True
     End If
End Function

Listing 3: Prüfung auf Vorhandensein eines Wertes für einen String-Parameter

  StringparameterVorhanden()
Falsch

übergeben Sie einen Wert, liefert die Funktion den Wert True zurück:

  StringparameterVorhanden("bla")
Wahr

Benannte Parameter

Wenn eine Funktion ein oder mehrere optionale Parameter enthält, können Sie diese auf verschiedene Arten angeben:

  • in der angegebenen Reihenfolge, durch Kommata getrennt und vollständig bis zum letzten übergebenen Parameter oder
  • mit vorangestelltem Parameternamen und durch := von diesem getrennt.

Im Detail bedeutet dies etwa folgende Varianten bezogen auf die Funktion aus Listing 4:

Public Function Benannt(Optional str1 As String, Optional str2 As String, Optional str3 As String)
     Debug.Print str1 + " " & str2 + " " & str3
End Function

Listing 4: Funktion zum Testen benannter Parameter

  Benannt("1", "2")
1 2 
  Benannt("1",,"3")
1  3

Oder Sie übergeben die Parameter in beliebiger Reihenfolge und mit vorangestelltem Parameternamen:

  Benannt(str3:="3", str1:="1")
1  3

Parameter als Variablen

Wie Sie oben gesehen haben, können Sie innerhalb der Funktion auf die Werte der Parameter zugreifen und diese als Grundlage für den Aufruf weiterer Funktionen verwenden oder diese auch als Teil von Ausdrücken verwenden. Sie können die Parameter aber auch wie herkömmliche Variablen weiterverwenden – zum Beispiel so:

Public Function Variable(str1 As String)
     Debug.Print "Vorher: " & str1
     str1 = "Nachher"
     Debug.Print "Nachher: " & str1
End Function

Ein Aufruf liefert die folgende Ausgabe:

Variable "Vorher"
Vorher: Vorher
Nachher: Nachher

ByVal und ByRef

Das vorherige Beispiel war nur die Vorbereitung für die folgenden Beispiele zur Anwendung von ByVal und ByRef.

Angenommen, Sie verwenden eine Funktion wie die Folgende:

Public Function ParameterAendern( str1 As String)
     str1 = "Nachher"
End Function

Wenn Sie dem Parameter str1 wie folgt die gefüllte Variable str0 übergeben, ändert die Funktion VariableAendern den in str1 enthalten Wert. Der Wert der übergebenen Variablen str0 wird an dieser Stelle ebenfalls geändert:

Public Sub Test_ParameterAendern()
     Dim str0 As String
     str0 = "Vorher"
     Debug.Print "Vorher: " & str0
     ParameterAendern str0
     Debug.Print "Nachher: " & str0
End Sub

Dies belegt der folgende Aufruf samt Ausgabe:

Test_VariableAendern
Vorher: Vorher
Nachher: Nachher

Wenn Sie sicher verhindern möchten, dass die in den übergebenen Variablen enthaltenen Werte auch in den Originalvariablen geändert werden, müssen Sie dem Parameter den Wert ByVal voranstellen:

Public Function ParameterNichtAendern( ByVal str1 As String)
     str1 = "Nachher"
End Function

Ein ähnlicher Aufruf wie im vorherigen Beispiel sorgt zwar dafür, dass die Funktion den Wert des Parameters intern ändert, aber die änderung wirkt sich nicht auf die beim Aufruf übergebene Variable aus. Das Verhalten beim Weglassen des Schlüsselworts ByVal entspricht der Verwendung des Schlüsselworts ByRef.

Parameterwerte nicht ändern

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar