Formulare per VBA referenzieren Wenn Sie Formulare und Steuerelemente programmieren wollen, müssen Sie wissen, wie Sie diese referenzieren. Nicht immer geschieht dies vom Klassenmodul des Formulars selbst aus manchmal wollen Sie vielleicht auch von anderen Formularen auf die Steuer elemente eines anderen Formulars zugreifen oder auch von einer VBA-Prozedur in eine Standardmodul. Dieser Artikel zeigt, wie Sie von verschiedenen Orten aus auf die Formulare zugreifen können. In weiteren Artikeln betrachten wir dann etwa den Zugriff auf die darin enthaltenen Steuer elemente. Beispieldatenbank Die Beispiele dieses Artikels finden Sie in der Datenbank 1803_FormsControlsVBA- Read.accdb. Innerhalb des Formulars Wenn Sie ein Formular erstellen und diesem ein Klassenmodul zuweisen, das sogenannte Code behind-modul, dann können Sie von diesem aus auf andere Weise auf die Elemente des Formulars zugreifen als dies etwa von einem anderen Formular oder auch von einem Standardmodul aus möglich ist. Hier steht nämlich das Me-Schlüsselwort für den Zugriff auf die Objektvariable des aktuellen Formulars zur Verfügung. Zur Verdeutlichung legen Sie einfach einmal ein neues Formular in einer leeren Datenbank an und speichern dieses unter dem Namen frmbeispiel. Diesem fügen wir nun eine Schaltfläche hinzu, die wir mit der Beschriftung Name anzeigen und dem Namen cmdnameanzeigen versehen und für die wir eine neue Ereignisprozedur für das Ereignis Beim Klicken anlegen (siehe Bild 1). Der Ereignisprozedur fügen wir nun eine Anweisung hinzu, die den Namen des Formulars in einem Meldungsfenster ausgeben soll: Bild 1: Hinzufügen einer Ereignisprozedur für eine Schaltfläche Das hier wie selbstverständlich verwendete Schlüsselwort Me ist eine sehr praktische Vereinfachung für den Zugriff auf die Elemente des Formulars, auf das sich das Klassenmodul bezieht. Mit diesem Schlüsselwort können Sie auf alle Eigenschaften und Methoden des Formulars zugreifen und auch auf die darin angelegten Steuer elemente darauf gehen wir später ein. Von außen Wie aber greifen wir denn eigentlich von außen auf dieses Formular zu? Dazu müssen wir erst einmal wissen, ob das Formular geöffnet ist. Greifen wir auf ein Formular zu, das nicht geöffnet ist, erhalten wir einen Laufzeitfehler. Private Sub cmdnameanzeigen_click() MsgBox Me.Name Um dies auszuprobieren, fügen Sie der Beispieldatenbank ein Standardmodul namens mdlformularzugriff hinzu. Hier legen Sie die folgende Prozedur an: www.access-basics.de Seite 16
Public Sub NameAnzeigen() MsgBox Forms!frmBeispiel.Name Die Prozedur erledigt nichts anders als die im Formular für die Schaltfläche cmdname- Anzeigen Sie gibt ein Meldungsfenster mit dem Namen des Formulars aus. Allerdings wissen wir, wenn wir auf die Schaltfläche des Formulars klicken, dass dieses logischerweise gerade geöffnet ist und brauchen dies nicht zu prüfen. Beim Zugriff von außen müssen wir dies jedoch vorher absichern. Rufen Sie die obige Prozedur auf, nachdem Sie das Formular geschlossen haben, löst dies den Fehler aus Bild 2 aus. Prüfen, ob ein Formular geöffnet ist Für die Prüfung, ob ein Formular geöffnet ist, hat sich die folgende Funktion etabliert. Sie erwartet den Namen des zu untersuchenden Formulars als Parameter. Sie nutzt die SysCmd-Funktion, der sie die Konstante acsyscmdgetobjectstate, den Objekttyp undd den Namen des Formulars übergibt. Wenn das Ergebnis größer als 0 ist, ist das Formular geöffnet: Public Function IstFormularGeoeffnet(strFormular As µ IstFormularGeoeffnet = SysCmd(µ End Function String) As Boolean acsyscmdgetobjectstate, acform, strformular) > 0 Bild 2: Fehler beim Zugriff auf ein nicht geöffnetes Formular Wenn das Formular nicht geöffnet ist, weist die Prozedur per Meldungsfenster auf diesen Zustand hin. Auf das aktuelle Formular zugreifen In manchen Fällen möchten Sie auch einfach auf das aktuell geöffnete Formular zugreifen, um beispielsweise dessen Namen zu ermitteln. Hierfür stellt Microsoft eine Klasse mit verschiedenen Eigenschaften bereit. Diese heißt Screen und liefert beispielsweise über die Eigenschaft ActiveForm Zugriff auf das aktuell aktive Formular. Die folgende Prozedur gibt beispielsweise den Namen des aktuellen Formulars aus: Public Sub AktuellesFormular() MsgBox Screen.ActiveForm.Name Mit dieser Funktion können wir bei Zugriff von außen leicht prüfen, ob das Formular geöffnet ist. Die obige Prozedur erweitern wir dabei wie folgt: Public Sub NameAnzeigen() If IstFormularGeoeffnet("frmBeispiel") Then Else MsgBox Forms!frmBeispiel.Name MsgBox "Das Formular ist nicht geöffnet." Wenn Sie diese Prozedur ausführen und es ist kein Formular geöffnet, erhalten Sie wiederum eine Fehlermeldung diesmal die aus Bild 3. Dieser Fehler kann übrigens auch dann auftreten, wenn ein Formular geöffnet ist! Die ActiveForm-Eigenschaft ermittelt nämlich tatsächlich nur das aktive Formular, wenn es sich bei dem aktuell im Access-Fenster aktiven Element um ein Formular handelt. Wenn gerade eine Tabelle und ein Formular angezeigt werden, aber die Tabelle den Fokus hat, erhalten Sie den gleichen Fehler, als wenn gar kein Formular geöffnet ist. www.access-basics.de Seite 17
In diesem Fall gibt es keine geeignete Funktion, um zu prüfen, ob es sich bei dem Objekt, das aktuell den Fokus besitzt, um ein Formular handelt. Wir können hier lediglich unter Deaktivierung der eingebauten Fehlerbehandlung prüfen, ob es sich um ein Formular handelt. Diese Prüfung können wir allerdings wieder in einer eigenen Funktion unterbringen, die dann wie folgt aussieht. Die Funktion deaktiviert die Fehlerbehandlung und ermittelt dann die Länge des Namens des aktiven Formulars. Diese vergleicht sie mit dem Wert 0 und schreibt das Ergebnis in die Variable bolformularaktiv. Ist ein Formular aktiv, liefert dies den Wert True. Falls nicht, wird ein Fehler ausgelöst, den die zuvor deaktivierte Fehlerbehandlung allerdings unterdrückt. Der Wert von bolformularaktiv bleibt dann False: Public Function FormularAktiv() Dim bolformularaktiv As Boolean On Error Resume Next bolformularaktiv = µ On Error GoTo 0 Len(Screen.ActiveForm.Name) > 0 FormularAktiv = bolformularaktiv End Function Diese Funktion setzen wir dann wie folgt ein: Public Sub AktuellesFormular() If FormularAktiv Then Else MsgBox Screen.ActiveForm.Name MsgBox "Kein Formular aktiv." Geöffnete Formular ermitteln Ob das Access-Fenster überhaupt Formulare anzeigt, ermitteln wir beispielsweise mit der Forms-Auflistung. Diese enthält eine Auflistung aller aktuell geöffneten Formular im Access-Fenster, also auch diejenigen, Bild 3: Weiterer Fehler beim Zugriff auf ein nicht geöffnetes Formular die in der Entwurfsansicht geöffnet sind. Die Anzahl der geöffneten Formular geben Sie wie folgt aus: Public Sub AnzahlGeoeffneterFormulare() MsgBox "Es sind " & Forms.Count µ & " Formulare geöffnet." Formulare ausgeben Nachdem wir schon die Anzahl der Formulare kennen, wollen wir auch die Namen der Formulare ausgeben. Dazu nutzen wir erneut die Auflistung Forms. Diesmal deklarieren wir zuvor eine Objektvariable namens frm mit dem Datentyp Form. Mit dieser durchlaufen wir in einer For Each-Schleife alle Elemente der Forms-Auflistung und geben die Namen im Direktbereich des VBA-Editors aus: Public Sub FormulareAusgeben() Dim frm As Form For Each frm In Forms Wenn Sie zusätzlich noch erfahren wollen, in welcher Ansicht ein Formular angezeigt wird, können Sie die CurrentView-Eigenschaft ausgeben lassen: www.access-basics.de Seite 18
Debug.Print frm.currentview Diese liefert verschiedene Zahlenwerte, die mit den folgenden Werten übereinstimmen: Formular über den Index referenzieren Ein Formular können Sie auch über den Index der Forms-Auflistung referenzieren. Für das erste Formular der Auflistung verwenden Sie folgenden Befehl: 0: Entwurfsansicht 1: Formularansicht 2: Datenblattansicht 7: Layoutansicht Bestimmtes Formular referenzieren Wenn Sie wissen, welches Formular Sie von einem anderen Ort als dem Klassenmoduls dieses Formulars referenzieren wollen, also etwa von einem anderen Formular oder einem Standard- oder Klassenmodul, können Sie verschiedene Möglichkeiten für den Zugriff auf dieses Formular nutzen. Die erste ist die vereinfachte Form, die wie bereits oben genutzt haben: Debug.Print Forms!frmBeispiel.Name Die zweite gibt den Namen als Parameter der Forms- Auflistung an: Debug.Print Forms("frmBeispiel").Name Diese hat gegenüber der ersten Variante den Vorteil, dass Sie den Namen des Formulars auch in einer Variablen unterbringen können, in diesem Fall in der Variablen strformular: Public Sub FormularReferenzieren() Dim strformular As String strformular = "frmbeispiel" Debug.Print Forms(strFormular).Name Sinnvoll wird dies beispielsweise, wenn Sie den Namen als Parameter einer Routine entgegennehmen. Debug.Print Forms(0).Name Sie erkennen hier bereits, dass dieser Index 0-basiert ist. Das bedeutet, dass Sie, wenn Sie die Formular etwa in einer For...Next-Schleife durchlaufen wollen, die Schleife entsprechend anpassen müssen. In der folgenden Prozedur deklarieren wir eine Variable namens intforms, welche die Anzahl der Formular über die Eigenschaft Count der Forms-Auflistung ermittelt. Dann durchläuft sie in einer For...Next-Schleife alle Wert von 0 bis intforms - 1, um die in Forms enthaltenen Formulare über den Index anzusprechen: Public Sub FormularPerIndex() Dim i As Integer Dim intforms As Integer intforms = Forms.Count For i = 0 To intforms - 1 Next i Debug.Print Forms(i).Name Nicht geöffnete Formulare Nicht immer sind nur die geöffneten Formulare einer Anwendung interessant oder auch das aktive Formulare. Vielleicht wollen Sie dem Benutzer auch eine Übersicht der Formulare anzeigen, damit dieser eines davon öffnen kann? In diesem Fall benötigen Sie einen anderen Ansatz als die Forms-Auflistung, denn die liefert nur den Zugriff auf die geöffneten Formulare. Und den bietet Access: Die Klasse CurrentProject liefert mit der Auflistung AllForms die Möglichkeit, auf alle in der Datenbank gespeicherten Formulare zuzugreifen. Damit können wir zunächst einmal die Anzahl der vorhandenen Formulare ermitteln: Debug.Print CurrentProject.AllForms.Count www.access-basics.de Seite 19
Dann wollen wir die Formulare der aktuellen Datenbank doch gleich einmal in einer Schleife durchlaufen und ihren Namen ausgeben: Public Sub AlleFormulare() Dim frm As Form For Each frm In µ CurrentProject.AllForms Das gelingt allerdings nicht wie gewünscht, wie Bild 4 zeigt. Wir haben naiverweise angenommen, auch diese Auflistung würde wie die Forms-Auflistung Elemente des Typs Form enthalten. Das ist allerdings nicht der Fall. Also versuchen wir, den Typ der enthaltenen Elemente herauszufinden. Das gelingt am einfachsten mit der TypeName-Funktion, die wir wie folgt im Direktbereich absetzen: Debug.Print TypeName(CurrentProject.AllForms(0)) AccessObject Also müssen wir für die Laufvariable den Datentyp AccessObject definieren. Damit klappt nun auch das Durchlaufen aller Formulare der aktuellen Datenbank: Public Sub AlleFormulare() Dim frm As AccessObject For Each frm In CurrentProject.AllForms Bild 4: Fehler beim Versuch, alle Formulare zu durchlaufen ermitteln können, welche Formulare aktuell geöffnet sind. Dazu prüfen wir in der Schleife über alle Formular aus der AllForms-Auflistung einfach, ob ein Element den Wert True für die Eigenschaft IsLoaded aufweist und geben dieses dann im Direktbereich aus: Public Sub AlleGeoeffnetenFormulare() Dim frm As AccessObject For Each frm In CurrentProject.AllForms If frm.isloaded Then Zusammenfassung und Ausblick Dieser Artikel hat die verschiedenen Möglichkeiten gezeigt, auf Formulare zuzugreifen. Die AccessObject-Klasse enthält viel weniger Eigenschaften als die Form-Klasse. Das ist auch kein Wunder, denn es soll nur die allgemeinen Eigenschaften der Access-Objekte liefern. Sie enthält mit IsLoaded jedoch eine interessante Eigenschaft, mit der wir auch über diese Auflistung In weiteren Artikeln zeigen wir, wie Sie auf die enthaltenen Elemente wie Unterformulare und andere Steuer elemente wie Textfelder, Kombinationsfelder und so weiter zugreifen. Später erfahren Sie dann, wie Sie Formulare und Steuer elemente per VBA-Code erstellen können. www.access-basics.de Seite 20