Formulare sind ein zentraler Bestandteil jeder Access-Anwendung. Damit eine Access-Anwendung flexibel erweitert werden kann, ist es hilfreich, wenn bereits die Formulare flexibel gestaltet werden. Ein wichtiges Konzept für diese Gestaltung ist die Kapselung.
Was ist Kapselung?
Kapselung ist ein Konzept aus der objektorientierten Programmierung. Im Prinzip ist es eine Zugriffskontrolle auf Elemente einer Klasse.
(Wikipedia: Datenkapselung)
Zugriffsregel
Auf Elemente einer Klasse darf nur über definierte Schnittstellen zugegriffen werden. Diese Schnittstellen können Eigenschaften, Methoden oder Ereignisse sein. Was im "Inneren" dieser Klassen abläuft, darf für die Zugriffe von "außen" keine Rolle spielen.
Wenn diese Regel beachtet wird, kann der Code innerhalb einer Prozedur ohne Probleme geändert werden. Solange sich an den Schnittstellen nichts ändert, muss kein Element verändert werden, das diese Klasse nutzt.
Dieses Prinzip kann man auch bei Formularen anwenden. Stellen Sie sich die Steuerelemente als Eigentum des Formulars vor. Zugriff auf diese Elemente sind nur erlaubt, wenn beim Formular nachgefragt wird. Nachgefragt wird mittels Property-Prozeduren oder Methoden. Diese geben den Zugriff auf die Inhalte frei.
Beispiel: Zugriff auf Unterformular
Gegeben: Hauptformular mit Unterformular. Vom Hauptformular aus soll ein Datenwert aus dem Unterformular abgefragt werden.
Direkter Zugriff auf Steuerelement bzw. Datenfeld
X = me!sfrABC.Form!X
Gekapselter Zugriff über Property-Prozedur
X = me.sfrABC.Form.WertVonX
Die Property-Prozedur muss allerdings im Unterformular definiert werden:
Public Property Get WertVonX() As String WertVonX = Nz(Me!X, vbNullString) End Property
Das ist doch nur umständlich!
Auf den ersten Blick sieht das durchaus umständlich aus. Aber stellen Sie sich vor, dass Sie das Unterformular überarbeiten und das Datenfeld "X" nun nicht mehr im Unterformular enthalten ist, da es in ein Unterformular des Unterformulars verlagert wurde.
Nun müssten Sie in jedem Formular, in dem das geänderte Formular als Unterformular verwendet wird, den Zugriff umschreiben.
In der Property-Variante ändern Sie die Prozedur einmalig - und zwar genau in dem einen Formular, das Sie gerade bearbeiten. Da dabei die Schnittstelle (Eigenschaft WertVonX) nicht geändert wird, muss auch kein abhängiges Formular geändert werden.
Geänderte Property-Prozedur
Public Property Get WertVonX() As String WertVonX = Me.sfrNeuesUF.Form.WertVonX End Property
Genau diese Unabhängigkeit von Änderungen im „Inneren“ ist das Ziel der Kapselung.
Beispiel: Edit-Modus
Bei Eingabeformularen kann es sinnvoll sein, über einen „Edit-Button“ im Hauptformular die Datensatzänderungen zu aktivieren. (Anfangs wird das Formular mit AllowEdits = False geöffnet. Erst das Betätigen der Edit-Schaltfläche schaltet auf AllowEdits = True um.)
Wenn Unterformulare verwendet werden, muss dieses Umschalten auch bei den Formularen der Unterformularsteuerelemente durchgeführt werden.
Me.sfrABC.Form.AllowEdits = True Me.sfrXYZ.Form.AllowEdits = True ...
Falls in den Unterformularen noch weitere Unterformulare vorhanden sind, müssen auch diese eingestellt werden.
Damit man das nicht bei jedem Formular mit Unterformularen beachten muss, ist es hilfreich, in jedem betroffenen Formular eine Methode einzufügen, die diese Umstellung durchführt.
Vorteil: Jedes Formular kennt seine Unterformulare. Für die Unterformulare des Unterformulars ist aber bereits die Methode des jeweiligen Unterformulars zuständig. Damit kann man in einem Hauptformular nie ein Unterformular der Unterformulare übersehen.
Public Property Let AllowDataEdits(allowEdit As Boolean) Me.AllowEdits = allowEdit Me.AllowAdditions = allowEdit If allowEdit OR (Me.RecordsetClone.RecordCount <> 0) Then Me.sfrEinUF.Form.AllowDataEdits = allowEdit Me.sfrNochEinUF.Form.AllowDataEdits = allowEdit End If End Property
Anm.: If allowEdit OR (Me.RecordsetClone.RecordCount <> 0)
verhindert eine Fehlermeldung, wenn im Formular kein Datensatz vorhanden und somit auch das Unterformular nicht verfügbar ist.
In diese Prozedur könnte auch noch eine visuelle Änderung der Steuerelemente eingebaut werden, damit der Benutzer sofort erkennt, ob die Formularfelder bearbeitet werden können.
Auch eine Prüfung, ob der Benutzer die Daten überhaupt ändern darf, ist in dieser Prozedur gut aufgehoben.
Beispiel: Datenfilterung
Falls Sie einmal von einem Hauptformular aus die Datensätze in einem Unterformular filtern wollen, vermeiden Sie den direkten Zugriff auf die vorhandene Filter-Eigenschaft. Denn sollten Sie einmal das Unterformular bezüglich Datenzugriff ändern und z. B. die Datenherkunft des Formulars samt Filterkriterien einstellen, bewirkt die Filter-Eigenschaft möglicherweise nicht den gewünschten Effekt.
Wenn sie eine Hilfsprozedur zur Filterübergabe einsetzen, ist die eigentliche Datenfilterung in der Hand des jeweiligen Formulars und bei einer Änderung des Datenzugriffs muss keine Schnittstelle geändert werden.
Pubic Sub SetFilter(filterString as string) Me.Filter = filterString Me.FilterOn = (len(filterString)>0) End Sub
Sollte nun die Datenherkunft direkt gefiltert werden, müssen Sie nur diese Prozedur ändern.
Pubic Sub SetFilter(filterString as string) Dim strSQL as String strSQL = "select ... from Tabelle" If len(filterString) > 0 then strSQL = strSQL & " where " & filterString End If Me.Recordsource = strSQL End Sub
Sie sehen, dass bereits mit einfachen Mitteln das Prinzip der Kapselung umgesetzt werden kann.
Die konsequente Umsetzung von gekapselten Formularelementen ist anfangs etwas aufwendiger als das direkte Zugreifen auf die Elemente von außen. Spätestens bei den ersten Änderungen oder Erweiterungen macht sich dieser Aufwand aber bezahlt. Außerdem ist das Formular durch diese Gestaltung unabhängig von Aufbau anderer Formulare und kann somit an beliebiger Stelle eingesetzt werden. Wer den Schnittstellenprozeduren aussagekräftige Namen gibt, wird mit einem gut lesbaren Code belohnt.