Im Beitrag “Formulare per VBA erstellen” (www.access-im-unternehmen.de/1332) haben wir gezeigt, wie Sie per VBA ein neues, leeres Formular erstellen und seine Eigenschaften einstellen. Darauf wollen wir in diesem Beitrag aufbauen und zeigen, wie Sie dem Formular per VBA die gewünschten Steuerelemente hinzufügen können. Und auch Steuerelemente haben eine Menge Eigenschaften, die wir nach dem Anlegen einstellen müssen – Position, Aussehen und auch wieder Ereigniseigenschaften. Nach der Lektüre des vorliegenden Beitrags haben Sie alle Werkzeuge, die Sie brauchen, um beispielsweise Access-Add-Ins zu nutzen, um einer Anwendung neue Formulare und Steuerelemente hinzuzufügen.
Vorbereitung: Formular anlegen
Als Vorbereitung wollen wir mit den Techniken, die wir im oben genannten Beitrag zum Erstellen von Formularen gelernt haben, zunächst ein neues Formular erzeugen. Dazu verwenden wir eine Funktion, die weitere Funktionen aus dem oben genannten Beitrag nutzt.
Die folgende Funktion erwartet den Namen des zu erstellenden Formulars und übergibt diesen an eine weitere Funktion namens CreateNewForm. Liefert diese den Wert True zurück, wurde das Formular erfolgreich erstellt.
Dann öffnen wir dieses Formular in der Formularansicht und stellen noch die Anzeige von Kopf- und Fußbereich ein – diese Bereiche werden wir weiter unten nämlich auch mit Steuerelementen versehen. Schließlich gibt die Funktion einen Verweis auf das noch in der Entwurfsansicht geöffnete Form-Objekt zurück:
Public Function GetNewForm(strForm As String) As Form Dim frm As Form If CreateNewForm(strForm) = True Then DoCmd.OpenForm strForm, acDesign Set frm = Forms(strForm) With frm RunCommand acCmdFormHdrFtr .Section(acHeader).Visible = True .Section(acFooter).Visible = True End With End If Set GetNewForm = frm End Function
Steuerelemente anlegen per VBA
Diese Funktion rufen wir von der folgenden Prozedur aus auf und referenzieren das erstellte und geöffnete Formular mit der Variablen frm:
Public Sub SteuerelementeAnlegen() Dim frm As Form Set frm = GetNewForm("frmMitSteuerelementen") ''Steuerelemente anlegen End Sub
Danach können wir bereits loslegen, indem wir die gewünschten Anweisungen an Stelle des Kommentars ”Steuerelemente anlegen einfügen! Die minimale Version der Methode CreateControl hat nur zwei Parameter – den Namen des Formulars und den Typ des Steuerelements, hier acTextBox für ein Textfeld:
CreateControl frm.Name, acTextBox
Dieser Befehl legt bereits ein einfaches Steuerelement an, wobei die Position links oben im Detailbereich des Formulars ist.
Wichtig ist, dass Sie genau wie über die Benutzeroberfläche nur Steuerelemente anlegen können, wenn das Formular in der Entwurfsansicht geöffnet ist.
Die Methode CreateControl
Die Methode CreateControl, eigentlich ein Teil des Application-Objekts, aber auch ohne dessen Angabe aufrufbar, hat noch weitere Parameter. Nur die ersten beiden Parameter FormName und ControlType sind Pflichtparameter:
- FormName: Name des Formulars, in dem das Steuerelement angelegt werden soll
- ControlType: Typ des Steuerelements, der durch eine Konstante angegeben wird – zum Beispiel acTextBox, acLabel oder acCommandButton.
- Section: Bereich, in dem das Steuerelement angelegt werden soll. Sinnvolle Werte für das Anlegen von Steuerelementen in Formularen sind acDetail, acHeader und acFooter. Die übrigen Möglichkeiten, die per IntelliSense angezeigt werden, sind für Berichte gedacht.
- Parent: Verweis auf das übergeordnete Steuerelement. Hiermit können Sie beispielsweise festlegen, zu welchem Textfeld ein Bezeichnungsfeld gehört.
- ColumnName: Angabe eines Feldes der Datensatzquelle des Formulars, an welches das Steuerelement gebunden werden soll. Füllt die Eigenschaft Steuerelementinhalt und mehr – siehe weiter unten.
- Left: Position vom linken Rand des Formulars
- Top: Position vom oberen Rand des Formulars
- Width: Breite des Steuerelements
- Height: Höhe des Steuerelements
Textfeld mit Bezeichnungsfeld anlegen
Um ein Textfeld mit einem Bezeichnungsfeld zu erstellen, benötigen Sie zwei Aufrufe der CreateControl-Methode. Mit dem ersten erstellen Sie das Textfeld, mit dem zweiten das Bezeichnungsfeld.
Für das Bezeichnungsfeld stellen wir den Parameter Parent auf das Textfeld ein. Auf diese Weise werden die beiden Steuerelemente so verknüpft, wie es auch beim Anlegen von Textfeldern über den Entwurf geschieht oder wenn Sie Felder aus der Feldliste in den Entwurf ziehen.
Für ein einfaches Textfeld mit einem Bezeichnungsfeld benötigen Sie die folgenden Anweisungen. Die Variablen txt und lbl dienen zum Referenzieren der neu erstellten Steuerelemente. Das Textfeld erstellen wir im Formular mit dem Namen, den wir mit frm.Name für das mit frm wie oben referenzierte Formular abfragen, als acTextBox im Bereich acDetail. Außerdem legen wir die Position mit 1400 Twips vom linken und 100 Twips vom oberen Rand und die Größe mit einer Breite von 2000 Twips und einer Höhe von 300 Twips fest:
Dim txt As TextBox Dim lbl As Label Set txt = CreateControl(frm.Name, acTextBox, acDetail, , , 1400, 100, 2000, 300)
Danach erstellen wir das Bezeichnungsfeld ebenfalls in frm.Name als acLabel im Bereich acDetail. Es soll dem zuvor erstellten Textfeld untergeordnet werden, also geben wir für den Parameter Parent den Namen des Textfeldes an (mit txt.Name). txt.Name funktioniert immer, auch wenn wir den Namen des Textfeldes nicht explizit festgelegt haben und liefert für das erste Textfeld im Formular beispielsweise den Wert Text0.
Die Position und die Abmessungen definieren wir so, dass das Bezeichnungsfeld links vom Textfeld erscheint. Anschließend legen wir noch die Beschriftung fest, indem wir die Eigenschaft Caption für das zuvor definierte und mit der Variablen lbl referenzierte Bezeichnungsfeld auf den Wert Textfeld: festlegen:
Set lbl = CreateControl(frm.Name, acLabel, acDetail, txt.Name, , 100, 100, 1200, 300)
lbl.Caption = "Textfeld:"
Indem Sie das Bezeichnungsfeld mit dem Parent-Parameter an das Textfeld binden, sorgen Sie gleichzeitig dafür, dass die Eigenschaft Bezeichnungsname des Textfeldes auf den Namen des Bezeichnungsfeldes eingestellt wird.
Das Ergebnis finden Sie in Bild 1 (siehe Prozedur FormularMitTextfeldUndBezeichnungsfeld).
Bild 1: Textfeld mit Bezeichnungsfeld
Gebundene Textfelder anlegen
Nun gehen wir einen Schritt weiter und wollen zwei gebundenen Textfelder anlegen. Dazu stellen wir als Erstes die Eigenschaft Recordsource (Datensatzquelle) des Formulars auf die Tabelle tblArtikel ein:
frm.RecordSource = "tblArtikel"
Danach erstellen wir nacheinander zwei Textfelder mit Bezeichnungsfeldern, wobei wir im Gegensatz zum vorherigen Beispiel nun den Parameter ColumnName nutzen, um das Feld anzugeben, an welches das jeweilige Textfeld gebunden werden soll:
Dim txt As TextBox Dim lbl As Label Set txt = CreateControl(frm.Name, acTextBox, acDetail, , "ArtikelID", 1500, 100, 2000, 300) Set lbl = CreateControl(frm.Name, acLabel, acDetail, txt.Name, , 100, 100, 1300, 300) lbl.Caption = "ArtikelID:" Set txt = CreateControl(frm.Name, acTextBox, acDetail, , "Artikelname", 1500, 500, 2000, 300) Set lbl = CreateControl(frm.Name, acLabel, acDetail, txt.Name, , 100, 500, 1300, 300) lbl.Caption = "Artikelname:"
Das so erstellte Formular sieht in der Formularansicht wie in Bild 2 aus (siehe Prozedur GebundeneTextfelder).
Bild 2: Formular mit gebundenen Textfeldern
Gebundene Kombinationsfelder anlegen
Wenn wir die Tabelle tblArtikel betrachten, finden wir als Nächstes zwei Nachschlagefelder.
Diese wollen wir nun in Form von Kombinationsfeldern zum Formular hinzufügen. Für das erste Nachschlagefeld namens KategorieID sieht der dazu nötige Code wie folgt aus:
Dim cbo As ComboBox ... Set cbo = CreateControl(frm.Name, acComboBox, acDetail, , "KategorieID", 1500, 900, 2000, 300) Set lbl = CreateControl(frm.Name, acLabel, acDetail, cbo.Name, , 100, 900, 1300, 300) lbl.Caption = "KategorieID:"
Wie wir in Bild 3 sehen, brauchen wir nur das zugrunde liegende Nachschlagefeld der Tabelle mit dem Parameter Column-Name anzugeben, damit ein neues Kombinationsfeld mit allen in der Tabelle für dieses Feld festgelegten Eigenschaften erstellt wird (siehe Prozedur GebundeneKombinationsfelder).
Bild 3: Formular mit gebundenem Kombinationsfeld
Übernahme von Eigenschaften bei gebundenen Steuerelementen
Wenn Sie mit dem Parameter ColumnName ein Feld der zugrunde liegenden Datensatzquelle angeben, stellt dies nicht nur die Eigenschaft Steuerelementinhalt auf den Namen des zu bindenden Feldes ein. Dazu gehören Eigenschaften wie Textformat, Eingabeformat, Standardwert, Gültigkeitsregel oder Gültigkeitsmeldung. Bei Kombinationsfeldern auf Basis von Nachschlagefeldern werden, wir oben gezeigt, sogar die Eigenschaften des Nachschlagefeldes übernommen.
Detailformular erstellen
Ein oft erledigter Schritt ist das Erstellen eines Detailformulars, also ein Formular, das die Daten einer Tabelle oder Abfrage anzeigen soll. Dazu sind normalerweise einige Schritte nötig wie das Erstellen des Formulars, das Hinzufügen der Datensatzquelle, das Hineinziehen der Felder in den Formularentwurf und gegebenenfalls noch das Anordnen der Felder, weil Access beim Hineinziehen von Feldern aus der Feldliste beispielsweise Kontrollkästchen immer links vom Bezeichnungsfeld anordnet und die übrigen Steuerelemente immer rechts vom Bezeichnungsfeld.
Deshalb zeigen wir im Folgenden eine praktische Anwendung der Techniken, die Sie weiter oben gelernt haben.
Die Prozedur DetailformularErstellen erwartet drei Parameter:
- strForm: Name des zu erstellenden Formulars
- strRecordsource: Name der Datensatzquelle
- lngCaptionWidth: Breite der Bezeichnungsfelder mit einem Standardwert von 1500 Twips
Die Prozedur, deren Code Sie in Listing 1 finden, schließt zunächst eine gegebenenfalls noch geöffnete Instanz des Formulars mit dem in strForm übergebenen Namen. Dann erstellt sie dieses mit der Funktion GetNewForm unter dem angegebenen Namen neu und referenziert das neu erstellte und in der Entwurfsansicht geöffnete Formular mit der Variablen frm.
Public Sub DetailformularErstellen(strForm As String, strRecordsource As String, Optional lngCaptionWidth As Long = 1500) Dim frm As Form Dim db As DAO.Database Dim rst As DAO.Recordset Dim fld As DAO.Field Dim strDisplayControl As String Dim strCaption As String Dim txt As TextBox Dim lbl As Label Dim cbo As ComboBox Dim chk As CheckBox Dim lngTop As Long DoCmd.Close acForm, strForm Set frm = GetNewForm(strForm) frm.RecordSource = strRecordsource Set db = CurrentDb Set rst = db.OpenRecordset(strRecordsource) For Each fld In rst.Fields strDisplayControl = 0 strCaption = "" On Error Resume Next intDisplayControl = fld.Properties("DisplayControl") strCaption = fld.Properties("Caption") On Error GoTo 0 If Len(strCaption) = 0 Then strCaption = fld.Name End If Select Case intDisplayControl Case acCheckBox Set chk = CreateControl(frm.Name, acCheckBox, acDetail, , fld.Name, lngCaptionWidth + 200, lngTop + 100) chk.Name = "chk" & fld.Name Set lbl = CreateControl(frm.Name, acLabel, acDetail, chk.Name, , 100, lngTop + 100, lngCaptionWidth, 300) Case acComboBox Set cbo = CreateControl(frm.Name, acComboBox, acDetail, , fld.Name, lngCaptionWidth + 200, _ lngTop + 100, 2000, 300) cbo.Name = "cbo" & fld.Name Set lbl = CreateControl(frm.Name, acLabel, acDetail, cbo.Name, , 100, lngTop + 100, lngCaptionWidth, 300) Case Else Set txt = CreateControl(frm.Name, acTextBox, acDetail, , fld.Name, lngCaptionWidth + 200, _ lngTop + 100, 2000, 300) txt.Name = "txt" & fld.Name Set lbl = CreateControl(frm.Name, acLabel, acDetail, txt.Name, , 100, lngTop + 100, lngCaptionWidth, 300) End Select lbl.Caption = strCaption lngTop = lngTop + 400 Next fld End Sub
Listing 1: Prozedur zum Erstellen eines Detailformulars
Die einzige Formulareigenschaft, welche die Prozedur einstellt, ist RecordSource. Sie erhält den Wert aus strRecordsource.
Danach referenziert die Prozedur mit db das aktuelle Database-Objekt und mit rst ein Recordset auf Basis der mit strRecordsource übergebenen Datensatzquelle, bei der es sich um eine Tabelle, Abfrage oder auch einen SQL-Ausdruck handeln kann. Anschließend durchläuft sie in einer For Each-Schleife alle Felder der Fields-Auflistung des Recordsets.
In dieser Schleife stellt die Prozedur zunächst die beiden Variablen intDisplayControl und strCaption auf die Werte 0 beziehungsweise eine leere Zeichenkette ein. intDisplayControl soll später den Steuerelementtyp aufnehmen, der für die Anzeige des Feldes in der Datenblattansicht definiert wurde. Dieser Steuerelementtyp wird beim Entwerfen einer Tabelle automatisch von Access vorgegeben – bei Feldern des Datentyps Kurzer Text zum Beispiel Textfeld, bei Nachschlagefeldern Kombinationsfeld oder bei Ja/Nein-Feldern Kontrollkästchen.
Bei reinen Zahlenfeldern wird kein Steuerelement voreingestellt. Bild 4 zeigt, wo Sie die Eigenschaft DisplayControl beziehungsweise Steuerelement anzeigen im Entwurf der Tabelle einsehen können. DisplayControl liefert Werte einer Enumeration wie acTextBox, acComboBox oder acCheckBox.
Bild 4: Wert der Eigenschaft DisplayControl
Die Variable strCaption soll den Wert der Eigenschaft Beschriftung aufnehmen oder, wenn keine Beschriftung angelegt wurde, den Feldnamen. Die Eigenschaft Beschriftung heißt unter VBA Caption. Sie können diese auf der Registerseite Allgemein des oben referenzierten Screenshots festlegen, diese Beschriftung wird dann als Spaltenüberschrift oder auch als Label-Beschriftung beim Ziehen von Feldern aus der Feldliste verwendet.
Warum setzen wir die beiden Variablen intDisplayControl und strCaption immer wieder auf 0 und “” Weil die Properties DisplayControl und Caption, mit denen wir diese füllen wollen, nicht immer vorhanden sind und wir versuchen, diese unter Deaktivierung der Fehlerbehandlung aus den Properties abzufragen. Da wir dies innerhalb einer Schleife machen, würden die Variablen, wenn sie nicht aus den Properties gefüllt werden können, gegebenenfalls noch den Wert aus dem vorherigen Durchgang enthalten, wenn wir sie nicht leeren.
Die Werte der Eigenschaften DisplayControl und Caption fragen wir also bei deaktivierter Fehlerbehandlung über die Auflistung Properties ab und speichern diese in intDisplayControl und strCaption. War die Property Caption nicht vorhanden, ist strCaption danach leer und wir füllen es ersatzweise mit dem Namen des Feldes.
intDisplayControl nimmt einen der Werte acCheckbox, acComboBox, acTextBox oder 0 an. Diesen prüfen wir in der folgenden Select Case-Bedingung. Im Falle von acCheckBox erstellt die Prozedur mit der CreateControl-Methode ein neues Steuerelement des Typs acCheckbox im Detailbereich des Formulars. Das Feld wird an den mit fld.Name gelieferten Feldnamen gebunden.
Die Breite ermitteln wir aus dem Parameter lngCaptionWidth plus 200, damit wir 200 Twips Abstand zwischen Label und Steuerelement erhalten. Den Abstand von oben stellen wir über den Wert der Variablen lngTop plus 100 ein. lngTop erhöhen wir nach jedem Steuerelement um 400, damit das nächste Steuerelement um 400 Twips weiter unten angeordnet wird. Im Falle von acCheckBox brauchen wir Höhe und Breite nicht anzugeben, da die CheckBox immer gleich groß ist.
Anschließend weisen wir dem mit chk referenzierten neuen CheckBox-Steuerelement über die Eigenschaft Name den Namen des Feldes plus Präfix chk zu. Das folgende Label-Steuerelement legen wir links vom CheckBox-Steuerelement an. Weiter unten, außerhalb der Select Case-Bedingung, stellen wir noch seine Eigenschaft Caption auf den Wert aus strCaption ein.
Auf ähnliche Weise verfahren wir mit den Feldern, die für die Eigenschaft DisplayControl die Werte acComboBox oder acTextBox hinterlegt haben. Der Unterschied ist, dass wir diese Variablen des jeweiligen Typs zuweisen (ComboBox und TextBox) und dass wir für diese noch die Breite und die Höhe auf die Werte 2000 und 300 einstellen.
Schließlich weisen wir auch diesen Steuerelementen als Name ein Präfix wie cbo oder txt plus dem Feldnamen zu und erstellen die entsprechenden Label-Steuerelemente links neben dem Kombinations- oder Textfeld.
Die letzte Bedingung prüft übrigens nicht auf den Wert acTextBox, sondern verarbeitet alle übrigen Werte. Der Hintergrund ist, dass wir es ja nicht unbedingt mit acTextBox zu tun haben, sondern dass bei dem Steuerelement die Eigenschaft DisplayControl nicht definiert ist – dann soll dieses auch als TextBox-Steuerelement realisiert werden.
Nach dem Verlassen der Select Case-Bedingung stellen wir noch die Eigenschaft Caption des Label-Steuerelements aus lbl ein und erhöhen den Wert von lngTop um 400, damit das folgende Steuerelement unter dem aktuellen Steuerelement angelegt wird.
Den Aufruf gestalten wir beispielsweise wie folgt:
DetailformularErstellen "frmArtikelDetail", "tblArtikel", 2000
Das Ergebnis finden Sie in Bild 5.
Bild 5: Entwurf des per Code erstellten Formulars zur Anzeige von Artikeln in der Detailansicht
Doppelpunkte sicherstellen
Hier sehen wir noch einen kleinen Makel, denn die Beschriftungen werden nicht mit einem Doppelpunkt abgeschlossen. Wenn Sie das wünschen, können Sie es auf zwei Arten erledigen:
- Ergänzen der Label-Beschriftung um den Doppelpunkt
- Einstellen beziehungsweise sicherstellen, dass der Doppelpunkt automatisch hinzugefügt wird
Die letztere Variante wäre sinnvoller, denn es kann auch sein, dass bei Ihnen die Doppelpunkte automatisch hinzugefügt werden. Dies hängt von der Einstellung der Eigenschaft Mit Doppelpunkt der jeweiligen Standardsteuerelemente ab. Diese Eigenschaft sehen Sie bei bereits hinzugefügten Steuerelementen nicht, sondern nur, wenn Sie im Ribbon auf das jeweilige Steuerelement klicken – beispielsweise auf das Textfeld-Steuerelement -, ohne das Steuerelement tatsächlich zum Entwurf des Formulars hinzuzufügen und dann im Eigenschaftenblatt auf der Registerseite Format unten die Eigenschaft Mit Doppelpunkt betrachten (siehe Bild 6).
Bild 6: Einstellen der Eigenschaften für das Standardsteuerelement, hier für ein Textfeld.
Aber selbst wenn wir diese Eigenschaft wie folgt per VBA zu Beginn der Prozedur beispielsweise für die Textfelder dieses Formulars einstellen und den Formularentwurf anschließend speichern, führt dies nicht dazu, dass die Label anschließend automatisch mit abschließenden Doppelpunkten versehen werden. Das Standardsteuerelement für die Textbox erhalten Sie beispielsweise mit frm.DefaultControl(acTextBox) und weisen wie folgt den Wert True der Eigenschaft AddColon beziehungsweise Mit Doppelpunkt hinzu:
Set txt = frm.DefaultControl(acTextBox) txt.AddColon = True DoCmd.Save acForm, frm.Name
Es scheint also unabhängig davon zu sein, ob die Eigenschaft AddColon aktiviert ist oder nicht – wenn wir die Label-Steuerelemente separat hinzufügen, was per VBA nicht anders möglich ist, können wir die Doppelpunkte per VBA hinzufügen. Offensichtlich werden Doppelpunkte auch bei aktivierter Eigenschaft Mit Doppelpunkt für das Standardsteuerelement nur angelegt, wenn Sie das Textfeld über die Benutzeroberfläche hinzufügen oder durch das Ziehen von Feldern aus der Feldliste.
Also passen wir die Prozedur schlicht so an, dass die Doppelpunkte immer hinzugefügt werden:
lbl.Caption = strCaption & ":"
Danach erhalten wir die Beschriftungen mit Doppelpunkten.
Formular in der Datenblattansicht erstellen
Auf ähnliche Weise können Sie ein Formular erstellen, das standardmäßig in der Datenblattansicht angezeigt wird. Dazu müssen Sie zu der zuvor beschriebenen Prozedur lediglich die Zuweisung einer Eigenschaft hinzufügen, mit der wir die Standardansicht auf Datenblatt einstellen:
frm.DefaultView = acDefViewDatasheet
Sie erhalten dann genau das gleiche Ergebnis, allerdings in der Datenblattansicht. Die einzigen Elemente, die wir wegnehmen könnten, sind die Angaben der Position der Steuerelemente – alle anderen werden auch im Formular in der Datenblattansicht benötigt.
Allerdings wollen Sie vielleicht später manuelle Änderungen am Entwurf vornehmen, was schwierig wird, wenn alle Elemente übereinander angelegt wurden.
Die Prozedur für diesen Zweck heißt Datenblattformular-Erstellen und kann beispielsweise wie folgt aufgerufen werden:
DatenblattformularErstellen "sfmArtikelUebersicht", "tblArtikel", 2000
Damit erstellen wir ein Formular in der Datenblattansicht, das wir prima für das folgende Beispiel nutzen können.
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