Lektionen/Grundlagen

Sub, Function & Gültigkeitsbereich

Einsteiger9 Min. Lesezeit

Sobald dein Code wächst, zerlegst du ihn in kleine, benannte Bausteine: Prozeduren. Jede erledigt eine Aufgabe, hat einen sprechenden Namen und lässt sich von überall aufrufen. Das hält Code lesbar und vermeidet Wiederholung.

Sub oder Function?

Es gibt zwei Arten von Prozeduren, und der Unterschied ist einfach:

  • Eine Sub tut etwas — sie gibt keinen Wert zurück.
  • Eine Function berechnet etwas — sie gibt einen Wert zurück.
' Sub: erledigt eine Aktion
Public Sub ZeigeMeldung(ByVal text As String)
    MsgBox text, vbInformation, "Hinweis"
End Sub

' Function: liefert ein Ergebnis
Public Function Netto(ByVal brutto As Double, ByVal satz As Double) As Double
    Netto = brutto / (1 + satz)
End Function

Faustregel: Brauchst du ein Ergebnis, das du weiterverwendest, nimm eine Function. Willst du nur etwas auslösen (Meldung, Import, Speichern), reicht eine Sub.

Rückgabewerte

Eine Function gibt ihren Wert zurück, indem du dem Funktionsnamen etwas zuweist. Der Typ nach As legt fest, was zurückkommt:

Public Function Rabatt(ByVal betrag As Currency) As Currency
    If betrag > 100 Then
        Rabatt = betrag * 0.1
    Else
        Rabatt = 0
    End If
End Function

Der zuletzt zugewiesene Wert wird zurückgegeben. Weist du gar nichts zu, kommt der Standardwert des Typs zurück (0, "" oder Null).

Prozeduren aufrufen

Eine Sub rufst du einfach mit ihrem Namen auf, die Argumente folgen ohne Klammern:

ZeigeMeldung "Import abgeschlossen"

Eine Function nutzt du dort, wo ein Wert erwartet wird — dann mit Klammern:

Dim n As Double
n = Netto(119, 0.19)          ' 100
Debug.Print Netto(238, 0.19)  ' 200

Merke: Sobald du das Ergebnis einer Prozedur einer Variablen zuweist oder als Argument weiterreichst, brauchst du Klammern. Rufst du eine Sub freistehend auf, lässt du sie weg. (Das veraltete Call erzwingt immer Klammern.)

ByVal vs. ByRef

Wie ein Argument übergeben wird, entscheidet, ob die aufgerufene Prozedur den Originalwert verändern kann:

  • ByVal übergibt eine Kopie. Änderungen bleiben in der Prozedur.
  • ByRef übergibt einen Verweis auf das Original. Änderungen wirken zurück.
Public Sub MitKopie(ByVal x As Long)
    x = x * 2               ' ändert nur die Kopie
End Sub

Public Sub MitVerweis(ByRef x As Long)
    x = x * 2               ' ändert das Original beim Aufrufer
End Sub

Public Sub Test()
    Dim wert As Long
    wert = 10
    MitKopie wert
    Debug.Print wert        ' 10 – unverändert
    MitVerweis wert
    Debug.Print wert        ' 20 – verändert
End Sub

In VBA ist ByRef die Voreinstellung, wenn du nichts angibst. Das ist eine häufige Fehlerquelle: Eine Prozedur ändert versehentlich eine Variable des Aufrufers. Schreib deshalb standardmäßig ByVal davor, außer du willst den Wert bewusst zurückgeben.

Optionale Argumente

Mit Optional machst du ein Argument freiwillig. Gib ihm am besten einen Standardwert, der greift, wenn der Aufrufer nichts übergibt:

Public Function Begruessung(ByVal name As String, _
                            Optional ByVal anrede As String = "Hallo") As String
    Begruessung = anrede & " " & name & "!"
End Function

Public Sub Test2()
    Debug.Print Begruessung("Ante")            ' Hallo Ante!
    Debug.Print Begruessung("Ante", "Moin")    ' Moin Ante!
End Sub

Optionale Argumente müssen am Ende der Argumentliste stehen. Ohne Standardwert kannst du mit IsMissing prüfen, ob etwas übergeben wurde — das funktioniert allerdings nur bei Variant-Argumenten.

Gültigkeitsbereich: Public oder Private

Public und Private steuern, von wo eine Prozedur aufrufbar ist:

SchlüsselwortSichtbar inEinsatz
Publicim ganzen ProjektHilfsfunktionen, die überall gebraucht werden
Privatenur im eigenen Modulinterne Helfer, Ereignisprozeduren
' In Modul "modUtil"
Public Function Steuer(ByVal betrag As Double) As Double
    Steuer = betrag * 0.19
End Function

Private Sub NurHier()
    ' von außerhalb dieses Moduls nicht aufrufbar
End Sub

Ereignisprozeduren hinter Formularen (Private Sub cmdOK_Click()) sind fast immer Private — sie gehören nur zu diesem Formular.

Modul- vs. Prozedurebene

Auch wo du deklarierst, bestimmt die Reichweite:

  • Ein Dim innerhalb einer Prozedur gilt nur dort und ist nach dem Ende weg.
  • Ein Dim oder Private oben im Modul (vor der ersten Prozedur) gilt für alle Prozeduren des Moduls.
  • Ein Public oben in einem Standardmodul gilt im gesamten Projekt.
Option Explicit

Private mZaehler As Long        ' modulweit, überlebt Prozeduraufrufe

Public Sub HochZaehlen()
    Dim lokal As Long           ' nur hier gültig
    lokal = lokal + 1
    mZaehler = mZaehler + 1
    Debug.Print lokal, mZaehler
End Sub

Rufst du HochZaehlen dreimal auf, bleibt lokal immer 1, während mZaehler auf 3 steigt. Halte Variablen so lokal wie möglich — das macht Fehler leichter auffindbar.

Eigene Funktionen in Abfragen und Formularen

Ein großer Vorteil von Access: Public-Funktionen aus Standardmodulen kannst du direkt in Abfragen und Steuerelementen verwenden — als wären sie eingebaut. Beispiel-Funktion:

Public Function VollName(ByVal vorname As String, _
                         ByVal nachname As String) As String
    VollName = Trim(nachname & ", " & vorname)
End Function

In einer Abfrage als berechnetes Feld:

SELECT VollName([Vorname], [Nachname]) AS Anzeigename
FROM Kunden;

Oder als Steuerelementinhalt eines Textfelds im Formular:

=VollName([Vorname]; [Nachname])

Das klappt nur mit Public-Funktionen in Standardmodulen — nicht mit Funktionen, die in einem Formular- oder Berichtsmodul stehen. Lege wiederverwendbare Funktionen deshalb in einem eigenen Modul wie modFunktionen ab.

Zusammengefasst

  • Sub tut etwas, Function gibt einen Wert zurück (Zuweisung an den Funktionsnamen).
  • Aufruf: Sub freistehend ohne Klammern, Function mit Klammern, wo ein Wert erwartet wird.
  • ByVal übergibt eine Kopie, ByRef (Voreinstellung!) das Original — nimm im Zweifel ByVal.
  • Optional mit Standardwert macht Argumente freiwillig; sie stehen am Ende der Liste.
  • Public/Private und der Deklarationsort steuern den Gültigkeitsbereich; Public-Funktionen laufen auch in Abfragen und Formularen.
Nächste Lektion
Fehlerbehandlung mit On Error