Formulare per VBA erstellen

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.

Meldung beim Versuch, einem Formular einen bereits vorhandenen Namen zu geben

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.

Elemente der Titelleiste eines Formulars

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.
  • Titelleiste nur mit Überschrift

    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

Beispiel zum Einstellen der Eigenschaft Standardansicht auf Datenblatt:

frm.DefaultView = acViewDatasheet

Erlaubte Ansichten einstellen

Wenn Sie verhindern wollen, dass die Benutzer zwischen verschiedenen Ansichten wechseln, nutzen Sie die Eigenschaft ViewsAllowed dazu.

Mögliche Werte:

  • 0: Formularansicht und Datenblattansicht möglich
  • 1: Kein Wechsel von der Formularansicht zur Datenblattansicht möglich
  • 2: Kein Wechsel von der Datenblattansicht zur Formularansicht möglich

Sichtbarkeit

Mit der Eigenschaft Sichtbar (Visible) können Sie das Formular ein- und ausblenden.

Eigenschaften für geteilte Formulare

Wenn das Formular über die Eigenschaft DefaultView als geteiltes Formular angezeigt wird, werden die folgenden Eigenschaften ausgewertet:

  • Größe des geteilten Formulars (SplitFormSize) gibt je nach der mit SplitFormOrientation gewählten Position die Höhe oder Breite des Detailbereichs des geteilten Formulars an. Diese wird im Eigenschaftenblatt in Zentimeter und unter VBA in Twips angegeben.
  • Ausrichtung des geteilten Formulars (SplitFormOrientation): Gibt an, wo das Datenblatt angezeigt werden soll. Es gibt die folgenden Werte: acDatasheetOnBottom (1), acDatasheetOnLeft (2), acDatasheetOnRight (3) und acDatasheetOnTop (0).
  • Teilerleiste des geteilten Formulars (SplitFormSplitterBar): Gibt an, ob die Leiste zwischen den beiden Formularbereichen angezeigt werden soll. Wenn der Benutzer die Höhe/Breite der Bereiche nicht anpassen können soll, stellen Sie diese Eigenschaft auf False ein.
  • Datenblatt des geteilten Formulars (SplitFormDatasheet): Hier können Sie festlegen, ob Bearbeitungen im Datenblatt zulässig sein sollen. Es gibt die beiden Werte Bearbeitungen zulassen (acDatasheetAllowEdits) oder Schreibgeschützt (acDatasheetReadOnly.).
  • Drucken des geteilten Formulars (SplitFormPrinting): Hiermit legen Sie fest, welcher Bereich des geteilten Formulars im Fall der Fälle gedruckt werden soll. Die Eigenschaft nimmt die Werte Nur Datenblatt (acGridOnly) oder Nur Formular (acFormOnly) entgegen.
  • Position der Teilerleiste speichern (SaveSplitterBarPosition): Legt fest, ob die Position der Teilerleiste gespeichert werden soll, wenn diese beim Bearbeiten des geöffneten Formulars mit der Maus verschoben wurde. Beim Schließen wird dann abgefragt, ob die Position so wie geändert erhalten werden soll.

Einstellungen für die Anzeige des Formulars

Die folgenden Einstellungen blenden verschiedene Formularelemente ein- oder aus, außerdem enthalten sie Informationen über den Zustand zu modalen und Popup-Fenstern.

Die nachfolgend beschriebenen Elemente finden Sie teilweise im Screenshot aus Bild 4.

Ein- und ausblendbare Elemente im Formular

Bild 4: Ein- und ausblendbare Elemente im Formular

  • Automatisch zentrieren (AutoCenter): Legt fest, ob das Formular beim Öffnen automatisch im Access-Fenster zentriert werden soll.
  • Datensatzmarkierer (RecordSelectors): Aktiviert die Anzeige des Datensatzmarkierers (siehe Screenshot unter 1)
  • Navigationsschaltflächen (NavigationButtons): Aktiviert die Anzeige der Navigationsschaltflächen (siehe Screenshot unter 3).
  • Navigationsbeschriftung (NavigationCaption): Stellt die Beschriftung der Navigationsschaltflächen ein. Diese Beschriftung wird dort angezeigt, wo normalerweise Datensatz: steht (siehe Screenshot unter 2).
  • Trennlinien (DividingLines): Legt fest, ob im Endlosformular Trennlinien zwischen den Datensätzen angezeigt werden.
  • Bildlaufleisten (ScrollBars): Stellt ein, ob Bildlaufleisten angezeigt werden sollen. Es gibt die folgenden Einstellungen: 0: Nein, 1: Nur horizontal, 2: Nur vertikal und 3: In beide Richtungen (siehe Screenshot unter 4)
  • Rahmenart (BorderStyle): Gibt an, welche Rahmenart für Titelzeile, Formularrahmen et cetera verwendet werden soll. Es gibt die Werte 0 (Keine), 1 (Extra dünn), 2 (Veränderbar) und 3 (Dialog).

Außerdem gibt es noch zwei Eigenschaften, welche beide auf True eingestellt werden, wenn Sie das Formular mit DoCmd.OpenForm mit dem Wert acDialog für den Parameter WindowMode öffnen:

DoCmd.OpenForm "frmBeispiel", WindowMode:=acDialog

Die Eigenschaften lauten Popup (im Eigenschaftenblatt und unter VBA) und Modal (nur unter VBA verfügbar). Wenn Sie ein Formular wie oben öffnen, weisen diese beiden Eigenschaften beide den Wert True auf. Wenn Sie beide beim Erstellen auf True einstellen, wird das Formular immer als modaler Dialog geöffnet.

Ribbon und Menüs

Auch zum Festlegen des Ribbons, das mit einem Formular angezeigt werden soll und zu den Menüs, die mit Access 2003 abgekündigt wurden, gibt es einige Eigenschaften. Das Ribbon eines Formulars stellen Sie mit der Eigenschaft Name des Menübands (RibbonName) ein. Hier geben Sie den Namen eines der Einträge der Tabelle USysRegInfo ein. Die übrigen Eigenschaften wollen wir nur der Vollständigkeit halber erwähnen. Mit Menüleiste (MenuBar) und Symbolleiste (Toolbar) geben Sie die mit einem Formular anzuzeigenden Menüs an. Die Eigenschaft Kontextmenüleiste (ShortcutMenuBar) hingegen können Sie auch unter Access 2007 und neuer noch verwenden. Voraussetzung ist, dass Sie beispielsweise mit dem folgenden Code eine solche Kontextmenüleiste erstellt haben:

Dim cbr As CommandBar
Dim cbc As CommandBarButton
On Error Resume Next
CommandBars("cbrKontextmenue").Delete
On Error GoTo 0
Set cbr = CommandBars.Add("cbrKontextmenue",  msoBarPopup, False, True)
Set cbc = cbr.Controls.Add(msoControlButton)
With cbc
     .Caption = "Beispielbutton"
End With

Danach können Sie das Kontextmenü aus der Liste im Eigenschaftenblatt auswählen und es auch der Eigenschaft ShortCutMenuBar zuweisen:

frm.ShortCutMenuBar = "cbrKontextmenue"

Mit der Eigenschaft Kontextmenü (ShortcutMenu) legen Sie fest, ob das Formular überhaupt ein Kontextmenü anzeigen soll. Damit deaktivieren Sie sowohl eingebaute als auch benutzerdefinierte Kontextmenüs.

Dateneinstellungen

Die Eigenschaft Datensatzquelle (RecordSource) stellt die Tabelle oder Abfrage ein, deren Daten im Formular angezeigt werden können.

Mit der Eigenschaft Zyklus (Cycle) stellen Sie ein, ob beim Verlassen des letzten Feldes zum ersten Feld der Aktivierreihenfolge oder umgekehrt etwa mit der Tabulator- oder der Eingabetaste der Datensatz gewechselt werden soll. Die Eigenschaft kann die Werte 0 (Alle Datensätze), 1 (Aktueller Datensatz) und 2 (Aktuelle Seite) annehmen.

Die Eigenschaft Standardwerte abrufen (FetchDefaults) gibt an, ob Standardwerte für Datensätze schon vor dem Speichern angezeigt werden sollen.

Datenoperationen erlauben oder verbieten

Die folgenden Eigenschaften dienen dazu, verschiedene Operationen mit Daten zu erlauben oder zu unterbinden:

  • Daten eingeben (DataEntry): Legt fest, ob das Formular beim Öffnen nur einen neuen, leeren Datensatz anzeigt (True) oder ob alle Datensätze angezeigt werden sollen (False).
  • Anfügen zulassen (AllowAdditions): Legt fest, ob neue Datensätze hinzugefügt werden können.
  • Löschen zulassen (AllowDeletions): Legt fest, ob Datensätze gelöscht werden können.
  • Bearbeitungen zulassen (AllowEdits): Legt fest, ob Datensätze bearbeitet werden können.
  • Filter zulassen (AllowFilters): Legt fest, ob Filter gesetzt werden dürfen.
  • Recordsettyp (RecordsetType): Legt den Recordset-Typ für das Formular fest. Kann die folgenden Werte annehmen: 0 (Dynaset), 1 (Dynaset mit inkonsistenten Updates) und 2 (Snapshot)
  • Datensätze sperren (RecordLocks): Gibt an, ob Datensätze beim Bearbeiten gesperrt werden sollen. Mögliche Werte: Keine Sperrungen (0), Alle Datensätze (1) oder Bearbeiteter Datensatz (2).

Filter und Sortierung

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar