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
| Standardmodul | Klassenmodul | |
|---|---|---|
| Zweck | Sammlung von Prozeduren | Bauplan für Objekte |
| Instanzen | keine — existiert genau einmal | beliebig viele mit New |
| Eigener Zustand | nur globale Variablen | jede Instanz hat eigene Felder |
| Aufruf | MachWas | obj.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— wieLet, 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:
Setverwendest du nur, wenn die Eigenschaft ein Objekt hält (z. B. einRecordsetoder eine andere Klasse). Für Zahlen, Text, Datum und Boolean nimmst du immerLet.
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_Initializeläuft automatisch, sobald die Instanz erzeugt wird — ideal für Startwerte.Class_Terminateläuft, wenn das Objekt zerstört wird (z. B.Set obj = Nothingoder beim Verlassen der Prozedur) — ideal zum Aufräumen, etwa einRecordsetschließ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 clsKundein einer Zeile. Bei dieser „Auto-Instanziierung" erzeugt VBA das Objekt erst beim ersten Zugriff neu — auch nachdem du es aufNothinggesetzt hast. Das führt zu schwer auffindbaren Fehlern. TrenneDimundSet.
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.
- Lesbarkeit —
k.Rabattsatzsagt 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
Newerzeugst du beliebig viele Instanzen, die jeweils eigene Daten tragen. - Private Felder (
m_...) speichern den Zustand,Property Get/Let/Setsteuern den Zugriff und erlauben Prüfungen.Setnur für Objekte. - Öffentliche
Subs undFunctions sind die Methoden; ohneLet-Prozedur ist eine Eigenschaft schreibgeschützt. Class_Initializesetzt Startwerte,Class_Terminateräumt auf.- Klassen bringen Kapselung und Wiederverwendung — und lassen sich zu eigenen Collections für ein komplettes Objektmodell ausbauen.