Lektionen/Formulare & Berichte

Unterformulare steuern

Fortgeschritten10 Min. Lesezeit

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:

EigenschaftBedeutung
LinkMasterFieldsFeld(er) im Hauptformular (z. B. KundenID)
LinkChildFieldspassende 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.Parent funktioniert nur, wenn das Formular tatsächlich als Unterformular angezeigt wird. Öffnest du frmBestellungen einzeln (Standalone), löst Me.Parent einen Fehler aus. Prüfe im Zweifel mit einer eigenen Bedingung oder On 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!Steuerelement liest und setzt du die Inhalte; bei mehreren Zugriffen lohnt sich eine Dim frmUF As Form-Objektvariable.
  • .Form.Requery lädt das ganze Unterformular neu; ein gezieltes Requery auf ein Kombifeld erhält die Position.
  • LinkMasterFields/LinkChildFields (am Steuerelement) verknüpfen Haupt- und Unterformular und filtern automatisch.
  • Me.Parent greift aus dem Unterformular auf das Hauptformular zu — funktioniert nur, wenn das Formular wirklich eingebettet ist.
Nächste Lektion
Kombifelder & Nicht-in-Liste