Ein Unterformular zeigt die „Viele"-Seite einer Beziehung: Kunde oben, seine Bestellungen darunter. In VBA ist der Zugriff darauf die häufigste Stolperfalle überhaupt — weil ein Unterformular zwei Namen hat. Wenn du diesen einen Punkt verstanden hast, wird alles Weitere einfach.
Die Stolperfalle: zwei Namen
Wenn du ein Formular als Unterformular in ein anderes ziehst, entsteht ein Unterformular-Steuerelement (ein Container auf dem Hauptformular). Dieses Steuerelement hat einen Namen — und das darin angezeigte Formular hat ebenfalls einen Namen. Die beiden sind oft, aber nicht immer identisch.
Für VBA gilt: Du sprichst immer das Steuerelement an und hängst .Form an, um
zum eigentlichen Formular zu kommen:
Me!ctlUnterBestellungen.Form
ctlUnterBestellungen ist der Name des Steuerelements, nicht der des Formulars
frmBestellungen. Nimmst du versehentlich den Formularnamen, gibt es den Fehler
„Element nicht gefunden". Den Steuerelementnamen findest du im Eigenschaftenblatt
des markierten Unterformular-Rahmens unter Name.
Merksatz:
Me!Steuerelementname.Form— nie den Formularnamen direkt verwenden. Am saubersten benennst du das Steuerelement genauso wie das Formular, dann fällt die Verwechslung weg.
Steuerelemente im Unterformular lesen und setzen
Hast du .Form, greifst du auf dessen Steuerelemente ganz normal mit ! zu:
' Wert aus dem Unterformular lesen
Dim betrag As Currency
betrag = Me!ctlUnterBestellungen.Form!txtBetrag
' Wert im Unterformular setzen
Me!ctlUnterBestellungen.Form!txtStatus = "erledigt"
' Eigenschaft eines Steuerelements ändern
Me!ctlUnterBestellungen.Form!txtBetrag.Enabled = False
Das wird schnell lang. Wenn du mehrere Zugriffe hintereinander brauchst, setzt du eine Objektvariable auf das Unterformular:
Dim frmUF As Form
Set frmUF = Me!ctlUnterBestellungen.Form
frmUF!txtStatus = "erledigt"
frmUF!txtBetrag.Enabled = False
Debug.Print frmUF!txtBetrag
Das Unterformular aktualisieren mit Requery
Hat sich die zugrunde liegende Datenmenge geändert (z. B. neue Bestellung per
Aktionsabfrage angelegt), lädst du das Unterformular mit Requery neu:
Me!ctlUnterBestellungen.Form.Requery
Willst du nur ein einzelnes Kombinations- oder Listenfeld im Unterformular auffrischen, requery gezielt dieses Steuerelement — dann bleibt die Datensatzposition erhalten:
Me!ctlUnterBestellungen.Form!cboArtikel.Requery
Verknüpfung: LinkMasterFields und LinkChildFields
Damit Haupt- und Unterformular zusammenpassen, filtert Access das Unterformular automatisch nach dem aktuellen Hauptdatensatz. Das steuern zwei Eigenschaften am Unterformular-Steuerelement:
| Eigenschaft | Bedeutung |
|---|---|
LinkMasterFields | Feld(er) im Hauptformular (z. B. KundenID) |
LinkChildFields | passende Feld(er) im Unterformular |
Meist stellst du das im Entwurf ein. Du kannst es aber zur Laufzeit umsetzen — etwa um dieselbe Unterformular-Instanz je nach Kontext anders zu verknüpfen:
With Me!ctlUnterBestellungen
.LinkMasterFields = "KundenID"
.LinkChildFields = "KundenID"
End With
Beachte: Diese beiden Eigenschaften hängen am Steuerelement (Me!ctl...), nicht
am .Form. Sind sie gesetzt, filtert und aktualisiert Access das Unterformular
selbstständig bei jedem Datensatzwechsel im Hauptformular — ein Requery von Hand
brauchst du dann meist nicht.
Vom Unterformular aufs Hauptformular: Parent
Umgekehrt willst du aus dem Code hinter dem Unterformular auf das Hauptformular
zugreifen — etwa um dort eine Summe anzuzeigen. Dafür gibt es Me.Parent:
' Code hinter dem Unterformular frmBestellungen
Private Sub Form_AfterUpdate()
' Summe im Hauptformular aktualisieren
Me.Parent!txtGesamtsumme.Requery
End Sub
Me.Parent verweist auf das Hauptformular, in dem dieses Unterformular gerade
eingebettet ist. Ein Steuerelement des Hauptformulars sprichst du also mit
Me.Parent!Name an.
Hinweis:
Me.Parentfunktioniert nur, wenn das Formular tatsächlich als Unterformular angezeigt wird. Öffnest dufrmBestellungeneinzeln (Standalone), löstMe.Parenteinen Fehler aus. Prüfe im Zweifel mit einer eigenen Bedingung oderOn Error, ob ein Parent existiert.
Ereignisreihenfolge: erst füllt sich das Unterformular spät
Beim Öffnen wird das Hauptformular vor dem Unterformular vollständig geladen. Willst
du im Form_Load des Hauptformulars schon auf Werte des Unterformulars zugreifen,
kann es sein, dass diese noch nicht bereitstehen. Lege solche Logik besser ins
Form_Current oder reagiere direkt auf Ereignisse im Unterformular.
' Läuft bei jedem Datensatzwechsel im Hauptformular – Unterform ist dann bereit
Private Sub Form_Current()
If Not IsNull(Me!KundenID) Then
Me!ctlUnterBestellungen.Form.Requery
End If
End Sub
Zusammengefasst
- Ein Unterformular hat zwei Namen: das Steuerelement (Container) und das darin
angezeigte Formular. In VBA sprichst du immer das Steuerelement an:
Me!ctlName.Form. - Über
.Form!Steuerelementliest und setzt du die Inhalte; bei mehreren Zugriffen lohnt sich eineDim frmUF As Form-Objektvariable. .Form.Requerylädt das ganze Unterformular neu; ein gezieltesRequeryauf ein Kombifeld erhält die Position.LinkMasterFields/LinkChildFields(am Steuerelement) verknüpfen Haupt- und Unterformular und filtern automatisch.Me.Parentgreift aus dem Unterformular auf das Hauptformular zu — funktioniert nur, wenn das Formular wirklich eingebettet ist.