Warum sollte man Formulare per VBA erstellen, wenn Microsoft Access doch die gute alte, etwas in die Jahre gekommene Entwurfsansicht dafür bereitstellt Ganz einfach: Weil es für den effizient arbeitenden Access-Entwickler immer wieder Aufgaben gibt, die er einfach nicht von Hand erledigen möchte. Oder weil der Access-Entwickler immer wiederkehrende Aufgaben in ein Access-Add-In oder ein COM-Add-In auslagern möchte. Und dort gibt es nun einmal keine Entwurfsansicht – dort ist VBA-Code gefragt, um neue Formulare zu erstellen und die gewünschten Steuerelemente auf das Formular zu bringen. Dieser Beitrag liefert alle Techniken, die zum Erstellen von Formularen und zum Ausstatten mit Steuerelementen notwendig sind.
Neues, leeres Formular erstellen
Mit einer ersten Funktion wollen wir ein neues, leeres Formular mit einem vorher festgelegten Namen erstellen. Das erledigt die Funktion CreateNewForm. Diese erwartet als Parameter den Namen, den das Formular nach dem Erstellen erhalten soll:
Public Sub CreateNewForm(strName As String) Dim frm As Form Dim strNameTemp As String Set frm = CreateForm() strNameTemp = frm.Name DoCmd.Close acForm, frm.Name, acSaveYes DoCmd.Rename strName, acForm, strNameTemp End Sub
Die Prozedur deklariert Variablen für das neue Form-Element (frm) und für den temporären von Access beim Erstellen vergebenen Namen (strNameTemp). Dann erstellt es mit der CreateForm-Funktion ein neues Formular. CreateForm liefert einen Verweis auf das neu erstellte Form-Objekt zurück, welches wir mit der Variablen frm referenzieren. Wir würden nun gern den Namen des Formulars einstellen, aber das ist nicht ohne weiteres möglich: Die Eigenschaft Name des Form-Objekts ist nämlich schreibgeschützt. Wie also dem Formular den gewünschten Namen geben Klar: Wir könnten es einfach nach dem Speichern und Schließen umbenennen, dafür gibt es die DoCmd.Rename-Methode. Allerdings erwartet die auch den vorherigen Namen des Formulars, und den kennen wir nicht. Allerdings können wir diesen zuvor mit frm.Name auslesen und speichern ihn in der Variablen strNameTemp. Danach schließen wir dann das Formular mit der Methode DoCmd.Close und den Parametern acForm für den Objekttyp, frm.Name für den Namen des zu schließenden Objekts und acSaveYes, damit die Änderungen an dem neu erstellten Formular ohne Rückfrage gespeichert werden.
Nach dem Schließen rufen wir dann DoCmd.Rename auf und übergeben mit dem ersten Parameter den neuen Namen, mit dem zweiten den Objekttyp (acForm) und mit dem dritten den vorherigen Objektnamen.
Rufen wir diese Prozedur nun wie folgt auf, legt dies ein neues, leeres Formular unter dem angegebenen Namen an, das direkt im Navigationsbereich erscheint:
CreateNewForm "frmNeuesFormular"
Formular bereits vorhanden
Wenn man diese Prozedur zwei Mal hintereinander mit dem gleichen Formularnamen aufruft, erhält man die Meldung aus Bild 1. Diese wird durch den Versuch ausgelöst, dem neuen Formular den Namen eines bereits vorhandenen Formulars zu übergeben. Dem können wir bereits zuvor vorbeugen, indem wir abfragen, ob bereits ein Formular dieses Namens vorhanden ist. Ob ein Formular bereits vorhanden ist, können wir auf verschiedene Arten prüfen. Wir könnten zum Beispiel versuchen, es zu öffnen, oder wir durchlaufen eine der Auflistungen der Formulare.
Bild 1: Meldung beim Versuch, einem Formular einen bereits vorhandenen Namen zu geben
Wir wählen letztere Variante. Die Funktion heißt ExistsForm und erwartet den Formularnamen als Parameter. Sie liefert das Ergebnis als Booleanwert zurück. Hier deklarieren wir für die Formulare eine Variable des Typs AccessObject. Warum nun AccessObject und nicht Form wie oben in der Prozedur CreateNewForm Weil die dort verwendete Funktion CreateForm ein Objekt des Typs Form erstellt, die Auflistung CurrentProject.AllForms, die wir durchsuchen wollen, jedoch Elemente des Typs AccessObjects liefert.
Mit objForm durchlaufen wir in einer For Each-Schleife alle Elemente der Auflistung CurrentProject.AllForms und prüfen, ob das aktuell mit objForm referenzierte Formular den mit strForm übergebenen Namen hat. Falls ja, stellen wir den Funktionswert auf True ein und verlassen die Funktion. Wenn die Funktion alle Elemente aus CurrentProject.AllForms durchläuft, ohne dass das passende Formular gefunden wird, liefert sie den Rückgabewert False (also den Standardwert für Rückgabewerte des Datentyps Boolean):
Public Function ExistsForm(strForm As String) As Boolean Dim objForm As AccessObject For Each objForm In CurrentProject.AllForms If objForm.Name = strForm Then ExistsForm = True Exit Function End If Next objForm End Function
Formular neu erstellen
Wenn das Formular bereits existiert, können wir den Benutzer fragen, ob das vorhandene Formular überschrieben werden soll. Ist das der Fall, löschen wir das Formular und erstellen es neu. Dazu erweitern wir die Prozedur CreateNewForm wie in Listing 1. Hier fügen wir direkt hinter der Deklaration der Variablen einen Aufruf der Funktion ExistsForm ein.
Public Function CreateNewForm(strName As String) As Boolean Dim frm As Form Dim strNameTemp As String If ExistsForm(strName) Then If MsgBox("Formular ''" & strName & "'' ist bereits vorhanden. Überschreiben", vbYesNo + vbExclamation, _ "Formular überschreiben") = vbYes Then If DeleteForm(strName) = False Then Exit Function End If Else Exit Function End If End If Set frm = CreateForm() strNameTemp = frm.Name frm.Visible = True DoCmd.Close acForm, frm.Name, acSaveYes DoCmd.Rename strName, acForm, strNameTemp CreateNewForm = True End Function
Listing 1: Erstellen eines neuen Formulars
Liefert diese den Wert True, dann zeigen wir ein Meldungsfenster an, das den Benutzer fragt, ob er das Formular überschreiben möchte. Falls ja, rufen wir eine Funktion namens DeleteForm auf (siehe weiter unten) und übergeben den Namen des zu löschenden Formulars. Diese könnte fehlschlagen, weil beispielsweise das zu löschende Formular gerade geöffnet ist. In diesem Fall soll die Prozedur einfach verlassen werden – die passende Fehlermeldung soll die Funktion DeleteForm liefern. Wenn der Benutzer die Frage, ob das vorhandene Formular gelöscht werden soll, mit Nein antwortet, soll die Prozedur auch verlassen werden.
Nur wenn das Formular noch nicht existiert oder gelöscht werden konnte, werden die anschließenden Schritte zum Erstellen des neuen Formulars ausgeführt.
Löschen eines vorhandenen Formulars
Wenn das Formular bereits vorhanden ist und der Benutzer es überschreiben möchte, müssen wir es löschen. Dazu haben wir die Funktion DeleteForm definiert, die den Namen des zu löschenden Formulars entgegennimmt und einen Boolean-Wert zurückliefert.
Die Funktion probiert bei deaktivierter eingebauter Fehlerbehandlung aus, ob das Formular mit DoCmd.DeleteObject gelöscht werden kann. Falls ja, erhält die Funktion den Rückgabewert True. Anderenfalls gibt die Funktion die entsprechende Fehlermeldung aus Err.Description aus und gibt den Standardwert False als Funktionsergebnis an die aufrufende Prozedur zurück:
Public Function DeleteForm(strName As String) As Boolean On Error Resume Next DoCmd.DeleteObject acForm, strName If Err.Number = 0 Then DeleteForm = True Else MsgBox Err.Description, vbCritical + vbOKOnly, _ "Löschen fehlgeschlagen" End If End Function
Damit haben wir bereits eine Funktion zum Erstellen eines neuen Formulars, das allerdings noch komplett leer ist und für das wir auch noch keine Eigenschaften eingestellt haben.
Formular weiterverarbeiten
Nun stehen zwei Aufgaben an: Die erste ist das Einstellen verschiedener Eigenschaften für das Formular. Die zweite ist das Erstellen von Steuerelementen im Formular. Letzteres beschreibt der Beitrag Steuerelemente erstellen (www.access-im-unternehmen.de/1336). Um die Eigenschaften kümmern wir uns jetzt gleich.
Um Eigenschaften einstellen zu können, benötigen wir einen Verweis auf das Formular in der Entwurfsansicht. Das heißt also, dass wir das Formular auch öffnen müssen. Da stellt sich die Frage: Könnten wir mit der Funktion CreateNewForm nicht direkt einen Verweis auf das neu erstellte und in der Formularansicht geöffnete Formular zurückgeben Das könnten wir tun, wir müssten dazu das Formular allerdings auch in dieser Funktion wieder öffnen.
Das Schließen ist dort unbedingt nötig, da wir es sonst nicht umbenennen können. Da wir nicht wissen, ob und wie das Formular nach dem Erstellen direkt weiterverarbeitet werden soll, geben wir einfach nur einen Boolean-Wert zurück, der angibt, ob das Formular erfolgreich erstellt wurde.
Eigenschaften des Formulars einstellen
In der Prozedur, welche die Funktion CreateNewForm aufgerufen hat, können wir nun das Formular in der Entwurfsansicht öffnen und die gewünschten Änderungen vornehmen.
Wie bereits erwähnt, wollen wir uns in diesem Beitrag zunächst um das Einstellen der verschiedenen Eigenschaften des Formulars kümmern und schauen uns diese dabei im Detail an. Das Öffnen gestalten wir wie folgt:
Public Sub Test_CreateNewForm() Dim frm As Form Dim strForm As String strForm = "frmNeuesFormular" If CreateNewForm(strForm) = True Then DoCmd.OpenForm strForm, acDesign Set frm = Forms(strForm) With frm ''Eigenschaften einstellen End With End If End Sub
Hier schreiben wir den Namen des zu erstellenden Formulars direkt in eine Variable, weil wir diesen mehr als einmal benötigen und anschließende Änderungen so nur an einer Stelle erfolgen müssen. Dann erstellen wir das neue Formular mit der Funktion CreateNewForm.
Ist dies erfolgreich, öffnen wir das neu erstellte Formular mit DoCmd.OpenForm in der Entwurfsansicht. Dazu stellen wir den zweiten Parameter View auf acDesign ein.
Damit wir danach komfortabel die Eigenschaften des Formulars einstellen können, referenzieren wir das Formular dann über die Forms-Auflistung und den Namen des Formulars mit der Form-Variablen frm. Für frm stellen wir dann die nachfolgend beschriebenen Eigenschaften ein.
Einstellungen für die Titelleiste
Die Titelleiste des Formulars (siehe Bild 2) verwendet gleich mehrere Eigenschaften.
Bild 2: Elemente der Titelleiste eines Formulars
- Die Titelleiste des Formulars stellen wir mit der Eigenschaft Caption ein.
- Ob das Formular das gleiche Icon anzeigen soll wie die Hauptanwendung, legen Sie übrigens nicht mit einer Formular-Eigenschaft fest, sondern in den Access-Optionen mit der Option Als Formular- und Berichtssymbol verwenden. Dies gilt dann für alle Formulare und Berichte.
- Ob die Schließen-Schaltfläche aktiviert ist, stellen sie mit der Eigenschaft CloseButton ein. Legen Sie den Wert auf False fest, wird die Schaltfläche ausgegraut dargestellt und der Benutzer kann sie nicht betätigen.
- Die Schaltflächen in der Titelleiste zum Minimieren und Maximieren des Fensters können Sie über die Benutzeroberfläche mit der Eigenschaft MinMaxSchaltflächen einstellen, über VBA mit MinMaxButtons. Die möglichen Werte sind: 0 (Keine), 1 (Min vorhanden), 2 (Max vorhanden) oder 3 (Beide vorhanden).
- Die Eigenschaft Mit Systemfeldmenü (ControlBox) stellt ein, ob überhaupt Steuerelemente in der Titelleiste angezeigt werden sollen. Falls nicht, sieht die Titelleiste wie in Bild 3 aus.
Bild 3: Titelleiste nur mit Überschrift
Abmessungen
Die Abmessungen des Formulars wie die Höhe und die Breite stellen Sie mit Eigenschaften für verschiedene Elemente ein. Die Breite ist eine Formular-Eigenschaft, diese entspricht der VBA-Eigenschaft Width. Eine Eigenschaft namens Höhe beziehungsweise Height vermissen wir allerdings im Eigenschaftenblatt. Der Grund ist einfach: Ein Formular kann mehrere Bereiche enthalten, die jeweils eine eigene Höhe haben – zum Beispiel der Detailbereich oder Formularkopf und -Fuß. Die Einstellungen dieser Bereiche besprechen wir weiter unten.
Standardansicht
Die Standardansicht stellt die Eigenschaft DefaultView ein. Diese nimmt die Werte der Enumeration acDefView entgegen:
- acDefViewContinuous (1): Endlosformular
- acDefViewDatasheet (2): Datenblatt
- acDefViewSingle (0): Einzelnes Formular
- acDefViewSplitForm (5): Geteiltes Formular