Lektionen/Workflow

Klassenmodule: eigene Objekte

Profi13 Min. Lesezeit

Bisher hast du Code vermutlich in Standardmodulen abgelegt: lose Sammlungen von Subs und Functions. Ein Klassenmodul ist etwas anderes — es ist der Bauplan für ein Objekt. Aus einer Klasse erzeugst du zur Laufzeit beliebig viele Instanzen, die jeweils ihre eigenen Daten mit sich tragen. Genau das, was du bei Recordset, Form oder TableDef schon benutzt, kannst du damit selbst bauen.

Standardmodul vs. Klassenmodul

StandardmodulKlassenmodul
ZweckSammlung von ProzedurenBauplan für Objekte
Instanzenkeine — existiert genau einmalbeliebig viele mit New
Eigener Zustandnur globale Variablenjede Instanz hat eigene Felder
AufrufMachWasobj.MachWas

Ein Klassenmodul legst du im VBA-Editor an über Einfügen → Klassenmodul. Den Namen vergibst du im Eigenschaftenfenster (F4) — üblich ist ein cls-Präfix, z. B. clsKunde.

Private Felder

Die Daten eines Objekts leben in privaten Modulvariablen. Sie sind von außen nicht direkt erreichbar — das ist gewollt und heißt Kapselung. Ein häufiges Muster ist das m_-Präfix für „member":

' === Klassenmodul: clsKunde ===
Option Compare Database
Option Explicit

Private m_KundenNr As Long
Private m_Name As String
Private m_Umsatz As Currency

Von außen kommt niemand an m_Name heran. Der Zugriff läuft ausschließlich über Property-Prozeduren — dort kannst du prüfen, umrechnen oder Fehler abfangen.

Property Get / Let / Set

Eigenschaften sind spezielle Prozeduren, die wie Variablen aussehen, aber Code ausführen:

  • Property Get — liefert einen Wert zurück (Lesen).
  • Property Let — nimmt einen Wert entgegen (Schreiben, für einfache Datentypen).
  • Property Set — wie Let, aber für Objekt-Referenzen.
' Lesen erlaubt, Schreiben nur mit Prüfung
Public Property Get Name() As String
    Name = m_Name
End Property

Public Property Let Name(ByVal wert As String)
    If Len(Trim$(wert)) = 0 Then
        Err.Raise vbObjectError + 1, "clsKunde", "Name darf nicht leer sein."
    End If
    m_Name = wert
End Property

Public Property Get KundenNr() As Long
    KundenNr = m_KundenNr
End Property

Public Property Let KundenNr(ByVal wert As Long)
    m_KundenNr = wert
End Property

Lässt du das Property Let weg, ist die Eigenschaft schreibgeschützt — perfekt für berechnete oder nur intern gesetzte Werte.

' Nur lesbar: keine Let-Prozedur vorhanden
Public Property Get IstStammkunde() As Boolean
    IstStammkunde = (m_Umsatz >= 10000)
End Property

Merke: Set verwendest du nur, wenn die Eigenschaft ein Objekt hält (z. B. ein Recordset oder eine andere Klasse). Für Zahlen, Text, Datum und Boolean nimmst du immer Let.

Methoden: Sub und Function

Verhalten fügst du als öffentliche Subs (ohne Rückgabe) und Functions (mit Rückgabe) hinzu. Sie arbeiten direkt auf den privaten Feldern:

Public Sub UmsatzErhoehen(ByVal betrag As Currency)
    If betrag < 0 Then
        Err.Raise vbObjectError + 2, "clsKunde", "Betrag muss positiv sein."
    End If
    m_Umsatz = m_Umsatz + betrag
End Sub

Public Function Rabattsatz() As Double
    ' Stammkunden bekommen 10 %, sonst 3 %
    If IstStammkunde Then
        Rabattsatz = 0.1
    Else
        Rabattsatz = 0.03
    End If
End Function

Class_Initialize und Class_Terminate

Jedes Klassenmodul kennt zwei eingebaute Ereignisse:

  • Class_Initialize läuft automatisch, sobald die Instanz erzeugt wird — ideal für Startwerte.
  • Class_Terminate läuft, wenn das Objekt zerstört wird (z. B. Set obj = Nothing oder beim Verlassen der Prozedur) — ideal zum Aufräumen, etwa ein Recordset schließen.
Private Sub Class_Initialize()
    m_Umsatz = 0
    Debug.Print "Neuer Kunde angelegt"
End Sub

Private Sub Class_Terminate()
    Debug.Print "Kunde " & m_Name & " freigegeben"
End Sub

Instanz mit New erzeugen

Im Standardmodul (oder hinter einem Formular) benutzt du die Klasse jetzt wie jedes andere Objekt:

Public Sub KundeTesten()
    Dim k As clsKunde
    Set k = New clsKunde        ' hier läuft Class_Initialize

    k.KundenNr = 4711
    k.Name = "Müller GmbH"
    k.UmsatzErhoehen 12500

    Debug.Print k.Name & " – Rabatt: " & Format(k.Rabattsatz, "0%")
    Debug.Print "Stammkunde? " & k.IstStammkunde   ' True

    Set k = Nothing             ' hier läuft Class_Terminate
End Sub

Tipp: Schreib nicht Dim k As New clsKunde in einer Zeile. Bei dieser „Auto-Instanziierung" erzeugt VBA das Objekt erst beim ersten Zugriff neu — auch nachdem du es auf Nothing gesetzt hast. Das führt zu schwer auffindbaren Fehlern. Trenne Dim und Set.

Warum sich das lohnt

  • Kapselung — die Daten sind geschützt, Regeln (leerer Name, negativer Betrag) stehen an genau einer Stelle und lassen sich nicht umgehen.
  • Wiederverwendung — dieselbe Klasse funktioniert in Formularen, Berichten und Standardmodulen, ohne Copy-Paste.
  • Lesbarkeitk.Rabattsatz sagt mehr als eine Funktion mit fünf Parametern.

Ausblick: eigene Collections

Ein häufiger nächster Schritt ist eine Klasse, die mehrere deiner Objekte verwaltet, z. B. clsKundenListe. Intern hält sie eine Collection und bietet Methoden wie Hinzufuegen und Anzahl:

' === Klassenmodul: clsKundenListe ===
Private m_Kunden As Collection

Private Sub Class_Initialize()
    Set m_Kunden = New Collection
End Sub

Public Sub Hinzufuegen(ByVal k As clsKunde)
    m_Kunden.Add k, CStr(k.KundenNr)   ' Schlüssel = KundenNr
End Sub

Public Property Get Anzahl() As Long
    Anzahl = m_Kunden.Count
End Property

So baust du dir Stück für Stück ein eigenes, sauber typisiertes Objektmodell — die Grundlage für größere, wartbare Access-Anwendungen.

Zusammengefasst

  • Ein Klassenmodul ist der Bauplan für Objekte; mit New erzeugst du beliebig viele Instanzen, die jeweils eigene Daten tragen.
  • Private Felder (m_...) speichern den Zustand, Property Get/Let/Set steuern den Zugriff und erlauben Prüfungen. Set nur für Objekte.
  • Öffentliche Subs und Functions sind die Methoden; ohne Let-Prozedur ist eine Eigenschaft schreibgeschützt.
  • Class_Initialize setzt Startwerte, Class_Terminate räumt auf.
  • Klassen bringen Kapselung und Wiederverwendung — und lassen sich zu eigenen Collections für ein komplettes Objektmodell ausbauen.
Nächste Lektion
Datenbank aufteilen: Frontend & Backend