{"id":55001528,"date":"2024-12-01T00:00:00","date_gmt":"2024-11-06T18:58:24","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1528"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Uebersichtsformular_per_Mausklick","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/","title":{"rendered":"&Uuml;bersichtsformular per Mausklick"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg02.met.vgwort.de\/na\/99965432c3954f3790bdbc69c88ccfb1\" width=\"1\" height=\"1\" alt=\"\"><b>Manche Aufgaben im Alltag eines Access-Entwicklers wiederholen sich immer wieder und unterscheiden sich nur durch Kleinigkeiten. Zum Beispiel sehen Detailformulare, &Uuml;bersichtsformulare oder auch Formulare zum Verwalten von Daten in Haupt- und Unterformular immer gleich aus &#8211; wenn auch f&uuml;r andere Daten.  Im Beitrag &#8222;Tabellendaten mit &Uuml;bersicht und Details anzeigen&#8220; (www.access-im-unternehmen.de\/1488) haben wir grunds&auml;tzlich gezeigt, wie wir ein Hauptformular mit einer &Uuml;bersicht in einem Unterformular anlegen und programmieren k&ouml;nnen. Der Beitrag &#8222;Detailformular per Mausklick erstellen&#8220; (www.access-im-unternehmen.de\/10) wiederum liefert ein Beispiel daf&uuml;r, wie wir ein einfaches Detailformular schnell definieren und per Mausklick erstellen k&ouml;nnen. Im vorliegenden Beitrag wollen wir beides kombinieren &#8211; also ein &Uuml;bersichtsformular mit Haupt- und Unterformular in einem Konfigurationsformular einrichten und dann automatisch erstellen.<\/b><\/p>\n<p>Im oben genannten Beitrag <b>Tabellendaten mit &Uuml;bersicht und Details anzeigen <\/b>(<b>www.access-im-unternehmen.de\/1488<\/b>) haben wir gezeigt, wie ein einfaches Formular zum Anzeigen der &Uuml;bersicht &uuml;ber die Daten eines Formulars erstellt werden kann.<\/p>\n<p>Dieses soll folgende Elemente beinhalten und sieht in der Formularansicht wie in Bild 1 aus:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_001.png\" alt=\"Beispiel f&uuml;r ein &Uuml;bersichtsformular\" width=\"549,559\" height=\"358,0313\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Beispiel f&uuml;r ein &Uuml;bersichtsformular<\/span><\/b><\/p>\n<ul>\n<li>Unterformular mit den anzuzeigenden Daten<\/li>\n<li>Schaltfl&auml;che zum Anlegen neuer Datens&auml;tze<\/li>\n<li>Schaltfl&auml;che zum Bearbeiten des aktuell markierten Datensatzes<\/li>\n<li>Schaltfl&auml;che zum L&ouml;schen des aktuell markierten Datensatzes<\/li>\n<li>Schaltfl&auml;che zum Schlie&szlig;en des Formulars<\/li>\n<li>Textfeld zum Eingeben von Suchbegriffen zum Suchen nach Datens&auml;tzen im Unterformular<\/li>\n<\/ul>\n<p>Au&szlig;erdem soll sich das Unterformular an die Gr&ouml;&szlig;e des Hauptformulars anpassen, wenn der Benutzer dieses vergr&ouml;&szlig;ert. Zum Erstellen eines solchen Formulars wollen wir in diesem Beitrag ein Konfigurationsformular erstellen sowie den Code, der n&ouml;tig ist, um das Formular auf Knopfdruck anhand der vorgenommenen Einstellungen zu erstellen.<\/p>\n<p>Dabei wollen wir auch direkt die M&ouml;glichkeit schaffen, das im Beitrag <b>Detailformular per Mausklick erstellen <\/b>(<b>www.access-im-unternehmen.de\/10<\/b>) erstellte Formular zum Erstellen neuer oder zum Bearbeiten vorhandener Datens&auml;tze aufzurufen beziehungsweise den Namen dieses Formulars zu diesem Zweck auszuw&auml;hlen.<\/p>\n<p>Wir beginnen, indem wir das Konfigurationsformular Schritt f&uuml;r Schritt zusammenstellen und dabei gleichzeitig den Code entwickeln, der zum Erstellen des Formulars dienen soll.<\/p>\n<p>Im gleichen Zuge stellen wir auch die Tabellen zusammen, welche die Konfigurationsdaten erfassen. Wir wollen diese speichern und jederzeit erneut abrufen k&ouml;nnen.<\/p>\n<p>Die dazu verwendeten Tabellen hei&szlig;en <b>tblOverviewforms <\/b>und <b>tblOverviewFields<\/b>. Die Tabellen sind &auml;hnlich aufgebaut wie in der L&ouml;sung zum Erstellen von Detailformularen. Die Tabelle <b>tblOverviewForm<\/b> sehen wir in der Entwurfsansicht in Bild 2. Sie enth&auml;lt die wesentlichen Informationen zum Erstellen des Hauptformulars und der Steuerelemente im Hauptformular.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_002.png\" alt=\"Tabelle f&uuml;r die Daten zum Erstellen von Haupt- und Unterformular\" width=\"649,559\" height=\"716,9205\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Tabelle f&uuml;r die Daten zum Erstellen von Haupt- und Unterformular<\/span><\/b><\/p>\n<p>Die Tabelle <b>tblOverviewFields <\/b>enth&auml;lt die Daten der Felder, die f&uuml;r die &Uuml;bersicht im Unterformular angezeigt werden sollen (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_003.png\" alt=\"Tabelle f&uuml;r die Daten der Felder im Unterformular\" width=\"649,559\" height=\"331,1633\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Tabelle f&uuml;r die Daten der Felder im Unterformular<\/span><\/b><\/p>\n<h2>Von der einfachen Access-Anwendung zum Add-In<\/h2>\n<p>Wir arbeiten wieder in zwei Schritten: Wir werden zun&auml;chst das Konfigurationsformular in der gleichen Anwendung entwickeln, in der wir auch testweise die Formulare anlegen und aus der die Tabellen oder Abfragen stammen, die als Grundlage f&uuml;r das &Uuml;bersichtsformular dienen. Erst wenn dies erledigt ist, wandeln wir die Datenbankdatei in eine Add-In-Datenbank um.<\/p>\n<p>Das Konfigurationsformular sieht in der Formularansicht wie in Bild 4 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_004.png\" alt=\"Formulare mit den Daten zum Erstellen des &Uuml;bersichtsformulars\" width=\"700\" height=\"651,2142\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Formulare mit den Daten zum Erstellen des &Uuml;bersichtsformulars<\/span><\/b><\/p>\n<p>Es enth&auml;lt oben links die Basisinformationen des zu erstellenden Formulars:<\/p>\n<ul>\n<li><b>Datensatzquelle<\/b>: Tabelle oder Abfrage mit den in der &Uuml;bersicht anzuzeigenden Daten<\/li>\n<li><b>Formularname<\/b>: Name des zu erstellenden Formulars<\/li>\n<li><b>Formulartitel<\/b>: Text f&uuml;r die Titelleiste des Formulars<\/li>\n<li><b>Rand\/Abstand<\/b>: Gibt die Abst&auml;nde der Steuerelemente zu den R&auml;ndern und zu den anderen Steuerelementen an.<\/li>\n<li><b>Automatisch zentrieren<\/b>: Legt den Wert f&uuml;r die Eigenschaft <b>Automatisch zentrieren <\/b>fest.<\/li>\n<li>Bereich <b>Suchen-Textfeld<\/b>: Hier finden wir Informationen dar&uuml;ber, ob ein Suchfeld angezeigt werden soll, wie die Beschriftung des Suchfeldes hei&szlig;t und welcher Code ausgel&ouml;st werden soll, wenn sich der Wert des Suchen-Feldes &auml;ndert.<\/li>\n<li>Bereich <b>OK-Button<\/b>: Enth&auml;lt Informationen dar&uuml;ber, ob eine OK-Schaltfl&auml;che angezeigt werden soll, welchen Text sie enthalten soll, welchen Code sie ausf&uuml;hren und welches Symbol sie enthalten soll.<\/li>\n<li>Bereich <b>Anlegen-Button<\/b>: siehe <b>OK-Button<\/b><\/li>\n<li>Bereich <b>Bearbeiten-Button<\/b>: siehe <b>OK-Button<\/b><\/li>\n<li>Bereich <b>L&ouml;schen-Button<\/b>: siehe <b>OK-Button<\/b><\/li>\n<\/ul>\n<p>Im unteren Bereich sehen wir schlie&szlig;lich noch ein Unterformular, das alle Felder der f&uuml;r die Eigenschaft <b>Datensatzquelle <\/b>ausgew&auml;hlten Tabelle oder Abfrage aufnimmt. Hier k&ouml;nnen wir individuelle Einstellungen f&uuml;r diese Felder vornehmen, zum Beispiel, ob dieses Feld angezeigt oder ignoriert werden soll. Au&szlig;erdem k&ouml;nnen wir die Beschriftung f&uuml;r die Spaltenk&ouml;pfe hier abweichend von den Feldnamen und den im Tabellenentwurf gespeicherten Beschriftungen vornehmen. Mit <b>Fieldindex <\/b>geben wir die Reihenfolge an und mit <b>FieldWidth <\/b>die Breite des Feldes. Au&szlig;erdem finden wir hier noch die typischen Eigenschaften f&uuml;r Felder, die als Kombinationsfelder ausgelegt sind und die wir hier auch nochmal individuell anpassen k&ouml;nnen.<\/p>\n<h2>Tabelle oder Abfrage mit den anzuzeigenden Daten ausw&auml;hlen<\/h2>\n<p>Der erste Schritt ist die Auswahl der Tabelle oder Abfrage, deren Daten im Unterformular angezeigt werden soll. Dazu ben&ouml;tigen wir ein Kombinationsfeld, mit dem wir alle Tabellen und Abfragen der aktuellen Datenbank ausw&auml;hlen k&ouml;nnen.<\/p>\n<p>Dieses Kombinationsfeld wollen wir mit allen Tabellen und Abfragen f&uuml;llen, die in der Tabelle <b>MSysObjects <\/b>vorhanden sind. Dabei m&uuml;ssen wir die Elemente erfassen, die im Feld <b>Type <\/b>einen der Werte <b>1<\/b>, <b>4<\/b>, <b>5 <\/b>oder <b>6 <\/b>enthalten und deren Wert im Feld <b>Name <\/b>nicht mit <b>F_ <\/b>oder <b>MSys <\/b>beginnt.<\/p>\n<p>Allerdings k&ouml;nnen wir dazu sp&auml;ter in der Add-In-Datenbank nicht einfach eine Abfrage zuweisen, die auf der Tabelle <b>MSysObjects <\/b>basiert. Damit w&uuml;rden wir n&auml;mlich auf die Tabelle <b>MSysObjects <\/b>der Add-In-Datenbank zugreifen und nicht auf die der Host-Datenbank, der wir das Formular hinzuf&uuml;gen wollen. Also m&uuml;ssen wir ein Recordset erstellen und dieses mit den entsprechenden Daten der Tabelle <b>MSysObjects<\/b> der Host-Datenbank f&uuml;llen.<\/p>\n<p>Das erledigen wir in der Prozedur, die durch das Ereignis <b>Beim Laden <\/b>des Formulars ausgel&ouml;st wird (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>dbc<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstIcons<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT Name FROM MSysObjects WHERE Type IN (1, 4, 5, 6) AND Name NOT LIKE ''F_*'' \" _\r\n         & \"AND Name NOT LIKE ''MSys*'' AND Name NOT LIKE ''USys*'' AND Name NOT LIKE ''~*''\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Set<\/span> Me!cboDatasource.Recordset = rst\r\n     <span style=\"color:blue;\">Set<\/span> rstIcons = dbc.OpenRecordset(\"SELECT id, [Name] FROM MSysResources WHERE Extension = ''png'' ORDER BY [Name]\", _\r\n         dbOpenDynaset)\r\n     <span style=\"color:blue;\">Set<\/span> Me.cboOKIcon.Recordset = rstIcons\r\n     Me!chkOKButton.DefaultValue = <span style=\"color:blue;\">True<\/span>\r\n     Me!txtOKCaption.DefaultValue = \"\"\"OK\"\"\"\r\n     Me!txtOKCode.DefaultValue = \"\"\"<span style=\"color:blue;\">Debug.Print<\/span> \"\"\"\"OK\"\"\"\"\"\"\"\r\n     Me!cboOKIcon.DefaultValue = 13\r\n     <span style=\"color:blue;\">Set<\/span> Me!cboAddNewIcon.Recordset = rstIcons\r\n     Me!chkAddNewButton.DefaultValue = <span style=\"color:blue;\">True<\/span>\r\n     Me!txtAddNewCaption.DefaultValue = \"\"\"Anlegen\"\"\"\r\n     Me!txtAddNewCode.DefaultValue = \"\"\"<span style=\"color:blue;\">Debug.Print<\/span> \"\"\"\"Anlegen\"\"\"\"\"\"\"\r\n     Me!cboAddNewIcon.DefaultValue = 10\r\n     <span style=\"color:blue;\">Set<\/span> Me!cboDeleteIcon.Recordset = rstIcons\r\n     Me!chkDeleteButton.DefaultValue = <span style=\"color:blue;\">True<\/span>\r\n     Me!txtDeleteCaption.DefaultValue = \"\"\"L&ouml;schen\"\"\"\r\n     Me!txtDeleteCode.DefaultValue = \"\"\"<span style=\"color:blue;\">Debug.Print<\/span> \"\"\"\"L&ouml;schen\"\"\"\"\"\"\"\r\n     Me!cboDeleteIcon.DefaultValue = 12\r\n     <span style=\"color:blue;\">Set<\/span> Me!cboEditIcon.Recordset = rstIcons\r\n     Me!chkEditButton.DefaultValue = <span style=\"color:blue;\">True<\/span>\r\n     Me!txtEditCaption.DefaultValue = \"\"\"Bearbeiten\"\"\"\r\n     Me!txtEditCode.DefaultValue = \"\"\"<span style=\"color:blue;\">Debug.Print<\/span> \"\"\"\"Bearbeiten\"\"\"\"\"\"\"\r\n     Me!cboEditIcon.DefaultValue = 11\r\n     Me!chkAutoCenter.DefaultValue = <span style=\"color:blue;\">True<\/span>\r\n     Me!cboButtonStyleID.DefaultValue = dbc.OpenRecordset(\"SELECT ButtonStyleID FROM tblButtonStyles\", _\r\n         dbOpenDynaset).Fields(0)\r\n     Me!txtSubformHeight.DefaultValue = 5000\r\n     Me!txtSubformWidth.DefaultValue = 10000\r\n     Me!txtMargin.DefaultValue = 50\r\n     Me!chkSearchTextbox.DefaultValue = <span style=\"color:blue;\">True<\/span>\r\n     Me!txtSearchCaption.DefaultValue = \"\"\"Suchen nach\"\"\"\r\n     Me!txtSearchCode.DefaultValue = \"\"\"<span style=\"color:blue;\">Debug.Print<\/span> \"\"\"\"Suchen\"\"\"\"\"\"\"\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(Nz(Me.OpenArgs, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         Me!cboDatasource = Me.OpenArgs\r\n         cboDatasource_AfterUpdate\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Aktionen beim Starten des Formulars frmOverviewForms<\/span><\/b><\/p>\n<p>Die Prozedur definiert zwei verschiedene <b>Database<\/b>-Objekte, von denen das erste mit <b>CurrentDb <\/b>das <b>Database<\/b>-Objekt der Host-Datenbank referenziert und das zweite mit <b>CodeDb <\/b>das <b>Database<\/b>-Objekt der Add-In-Datenbank. Solange wir noch mit einer Datenbank entwickeln, beziehen sich beide Objektvariablen auf das gleiche <b>Database<\/b>-Objekt. Mit der Variablen <b>rst <\/b>referenzieren wir die Datens&auml;tze der Tabelle <b>MSysObjects <\/b>der Host-Datenbank f&uuml;r das Kombinationsfeld der Datensatzquellen. Dieses weisen wir der <b>Recordset<\/b>-Eigenschaft des Kombinationsfeldes <b>cboDatasource <\/b>zu.<\/p>\n<p>Das Recordset <b>rstIcons <\/b>stellen wir auf die Tabelle <b>MSysResources <\/b>der Add-In-Datenbank ein. Diese Tabelle enth&auml;lt die Icons, die wir den Schaltfl&auml;chen der zu erstellenden Formulare zuweisen wollen. <\/p>\n<p>Das Recordset weisen wir den Kombinationsfeldern <b>cboOKIcon<\/b>, <b>cboAddNewIcon<\/b>, <b>cboDeleteIcon <\/b>und <b>cboEditIcon <\/b>zu.<\/p>\n<p>Au&szlig;erdem stellt die Prozedur beim Laden Standardwerte f&uuml;r die Kontrollk&auml;stchen und Textfelder der Schaltfl&auml;chen ein.<\/p>\n<h2>Ausw&auml;hlen einer Datensatzquelle f&uuml;r das zu erstellende &Uuml;bersichtsformular<\/h2>\n<p>Der erste Schritt beim Erstellen ist die Auswahl einer Datensatzquelle, auf deren Basis das &Uuml;bersichtsformular erstellt werden soll. Das Ausw&auml;hlen eines der Eintr&auml;ge des Kombinationsfeldes <b>cboDatasource <\/b>l&ouml;st das Ereignis <b>Nach Aktualisierung <\/b>aus, f&uuml;r das wir die Prozedur aus Listing 2 hinterlegen.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cboDatasource_AfterUpdate()\r\n     <span style=\"color:blue;\">If <\/span>ReadOverviewFieldsFromTable(Me!cboDatasource) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         Me!sfmOverviewforms.Form.Requery\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me!txtFormname, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         Me!txtFormname = <span style=\"color:blue;\">Replace<\/span>(<span style=\"color:blue;\">Replace<\/span>(Me!cboDatasource, \"tbl\", \"frm\"), \"qry\", \"frm\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me!txtUnterformularname, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         Me!txtUnterformularname = <span style=\"color:blue;\">Replace<\/span>(Me!txtFormname, \"frm\", \"sfm\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me!txtFormTitle, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         Me!txtFormTitle = <span style=\"color:blue;\">Replace<\/span>(<span style=\"color:blue;\">Replace<\/span>(Me!cboDatasource, \"tbl\", \"\"), \"qry\", \"\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Aktualisieren des Kombinationsfeldes cboDatasource<\/span><\/b><\/p>\n<p>Die Prozedur ruft eine weitere Funktion namens <b>ReadOverviewFieldsFromTable <\/b>auf, der wir die gew&auml;hlte Tabelle oder Abfrage &uuml;bergeben und die wir gleich beschreiben.   Hat diese Funktion die Felder erfolgreich ausgelesen und in die Tabelle <b>tblOverviewFields <\/b>geschrieben, wird das Unterformular <b>sfmOverviewforms <\/b>aktualisiert.<\/p>\n<p>Wenn <b>txtFormname <\/b>noch nicht gef&uuml;llt ist, tr&auml;gt die Prozedur automatisch den Namen der Datenquelle ein, wobei vorher Pr&auml;fixe wie <b>tbl <\/b>oder <b>qry <\/b>durch <b>frm <\/b>ersetzt werden. Das Unterformular erh&auml;lt den gleichen Namen, allerdings wird das Pr&auml;fix <b>frm <\/b>durch <b>sfm <\/b>ersetzt.<\/p>\n<p>F&uuml;r den Titel wird der gleiche Ausdruck eingetragen, jedoch werden die Pr&auml;fixe <b>tbl <\/b>und <b>qry <\/b>ersatzlos gestrichen.<\/p>\n<h2>Eintragen der Feldnamen f&uuml;r die &Uuml;bersicht im Unterformular<\/h2>\n<p>Die im Unterformular anzuzeigenden Felder werden erstmalig ausgelesen, sobald der Benutzer die Datensatzquelle selektiert hat. Dies l&ouml;st die Prozedur <b>cboDatasource_AfterUpdate <\/b>und in der Folge die Funktion <b>ReadOverviewFieldsFromTable <\/b>aus. Diese Funktion nimmt den Namen der Tabelle oder Abfrage entgegen, die als Datensatzquelle gew&auml;hlt wurde (siehe Listing 3). Dann referenziert sie die Host- und die Add-In-<b>Database<\/b>-Objekte mit den Variablen <b>db <\/b>und <b>dbc<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ReadOverviewFieldsFromTable(strDataSource<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database, dbc<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset, rstSource<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>bolReadFields<span style=\"color:blue;\"> As Boolean<\/span>, lngControlType<span style=\"color:blue;\"> As <\/span>AcControlType\r\n     <span style=\"color:blue;\">Dim <\/span>varRowSourceType<span style=\"color:blue;\"> As Variant<\/span>, varRowSource<span style=\"color:blue;\"> As Variant<\/span>, varBoundColumn<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>varCaption<span style=\"color:blue;\"> As Variant<\/span>, varColumnCount<span style=\"color:blue;\"> As Variant<\/span>, varColumnWidths<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field, i<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = dbc.OpenRecordset(\"SELECT * FROM tblOverviewfields WHERE OverviewformID = \" & Me!OverviewformID, _\r\n         dbOpenDynaset)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         rst.MoveLast\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     bolReadFields = <span style=\"color:blue;\">True<\/span>\r\n     Me.Dirty = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.RecordCount = 0<span style=\"color:blue;\"> Then<\/span>\r\n         bolReadFields = <span style=\"color:blue;\">MsgBox<\/span>(\"Sollen die Felder neu eingelesen werden?\", vbYesNo + vbExclamation, _\r\n             \"Felder neu einlesen?\") = vbYes\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>bolReadFields = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         dbc.Execute \"DELETE FROM tblOverviewfields WHERE OverviewformID = \" & Me!OverviewformID, dbFailOnError\r\n         <span style=\"color:blue;\">Set<\/span> rstSource = db.OpenRecordset(strDataSource, dbOpenDynaset)\r\n         For Each fld In rstSource.Fields\r\n             <span style=\"color:blue;\">Call<\/span> GetControlProperties(fld, varCaption, intControlType, varBoundColumn, varRowSourceType, _\r\n                 varRowSource, varColumnCount, varColumnWidths)\r\n             rst.Add<span style=\"color:blue;\">New<\/span>\r\n             rst!OverviewformID = Me!txtOverviewFormID\r\n             rst!FieldName = fld.Name\r\n             rst!Fieldindex = i\r\n             rst!FieldWidth = 2000\r\n             rst!FieldHeight = 300\r\n             rst!FieldColumn = 1\r\n             rst!Fieldlabel = Nz(varCaption, fld.Name)\r\n             rst!ControlType = lngControlType\r\n             rst!RowSourceType = varRowSourceType\r\n             rst!RowSource = varRowSource\r\n             rst!BoundColumn = varBoundColumn\r\n             rst!ColumnCount = varColumnCount\r\n             rst!ColumnWidths = varColumnWidths\r\n             rst.Update\r\n             i = i + 1\r\n         <span style=\"color:blue;\">Next<\/span> fld\r\n         ReadOverviewFieldsFromTable = <span style=\"color:blue;\">True<\/span>\r\n         Me!sfmOverviewforms.Form.Requery\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         ReadOverviewFieldsFromTable = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Aktualisieren der Felder f&uuml;r das &Uuml;bersichtsformular<\/span><\/b><\/p>\n<p>F&uuml;r die Add-In-Datenbank referenziert sie mit der Variablen <b>rst <\/b>die Datens&auml;tze der Tabelle <b>tblOverviewFields<\/b>, die &uuml;ber das Fremdschl&uuml;sselfeld <b>OverviewFormID <\/b>mit dem aktuellen Prim&auml;rschl&uuml;sselwert des Hauptformulars verbunden sind. Findet die Funktion hier bereits Datens&auml;tze, verschiebt sie den Datensatzzeiger auf den letzten Datensatz, um mit <b>rst.RecordCount <\/b>die Anzahl der Datens&auml;tze zu ermitteln. Dann stellt sie die Variable <b>bolReadFields <\/b>auf <b>True <\/b>und speichert alle &Auml;nderungen im Formular.<\/p>\n<p>Sind nun bereits Datens&auml;tze vorhanden, fragt die Funktion den Benutzer, ob diese neu eingelesen werden sollen. Antwortet der Benutzer mit Ja, beh&auml;lt <b>bolReadFields <\/b>den Wert <b>True <\/b>und die Felder werden nachfolgend neu ausgelesen. Anderenfalls werden die Felder nicht neu eingelesen.<\/p>\n<p>Im Falle des Neueinlesens l&ouml;scht die Funktion zun&auml;chst alle Eintr&auml;ge der Tabelle <b>tblOverviewfields<\/b>, die dem aktuell im Formular angezeigten Datensatz der Tabelle <b>tblOverviewForms <\/b>zugeordnet sind.<\/p>\n<p>Dann stellt sie das Recordset <b>rstSource <\/b>auf die mit <b>strDataSource <\/b>&uuml;bergebene Tabelle oder Abfrage ein. Anschlie&szlig;end durchl&auml;uft sie alle Felder dieses Recordsets. Dabei ruft sie f&uuml;r jedes Feld die Funktion <b>GetControlProperties <\/b>auf und &uuml;bergibt dieser mit <b>fld <\/b>einen Verweis auf das Feld sowie die Variablen <b>varCaption<\/b>, <b>intControlType<\/b>, <b>varBoundColumn<\/b>, <b>varRowSourceType<\/b>, <b>varRowSource<\/b>, <b>varColumnCount <\/b>und <b>varColumnWidths<\/b>. Diese Funktion, die wir weiter unten beschreiben, liest die Werte f&uuml;r die <b>Variant<\/b>-Parameter aus den Eigenschaften des <b>Field<\/b>-Objekts aus <b>fld <\/b>aus.<\/p>\n<p>Die folgenden Anweisungen tragen einige Informationen in das Recordset auf Basis der Tabelle <b>tblOverviewfields <\/b>ein. Dazu geh&ouml;rt der Prim&auml;rschl&uuml;sselwert des aktuell im Hauptformular angezeigten Datensatzes der Tabelle <b>tblOverviewForms<\/b>, damit die Daten dem jeweils zu erstellenden Formular zugeordnet werden k&ouml;nnen.<\/p>\n<p>Au&szlig;erdem tr&auml;gt sie den Feldnamen, den Index, den Wert 2000 als Feldbreite, die Beschriftung, den Steuerelementinhalt und einige Eigenschaften bez&uuml;glich eventuell in der Tabelle definierter Nachschlagefelder ein. Dazu geh&ouml;ren <b>ControlType<\/b>, <b>RowSourceType<\/b>, <b>RowSource<\/b>, <b>BoundColumn<\/b>, <b>ColumnCount <\/b>und <b>ColumnWidths<\/b>. Damit wird f&uuml;r jedes Feld der Datensatzquelle ein Datensatz in der Tabelle <b>tblOverviewfields <\/b>gespeichert und das Unterformular zur Anzeige dieser Felder aktualisiert.<\/p>\n<h2>Einlesen der Feldeigenschaften<\/h2>\n<p>Die soeben angesprochene Funktion <b>GetControlProperties <\/b>liest die verschiedenen Eigenschaften des mit dem Parameter <b>fld <\/b>&uuml;bergebenen Feldes ein und liefert diese in R&uuml;ckgabeparametern zur&uuml;ck (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetControlProperties(fld<span style=\"color:blue;\"> As <\/span>DAO.Field, varCaption<span style=\"color:blue;\"> As Variant<\/span>, intControlType<span style=\"color:blue;\"> As <\/span>AcControlType, _\r\n         varBoundColumn<span style=\"color:blue;\"> As Variant<\/span>, varRowSourceType<span style=\"color:blue;\"> As Variant<\/span>, varRowSource<span style=\"color:blue;\"> As Variant<\/span>, varColumnCount<span style=\"color:blue;\"> As Variant<\/span>, _\r\n         varColumnWidths<span style=\"color:blue;\"> As Variant<\/span>)\r\n     intControlType = 0\r\n     varCaption = Null\r\n     varBoundColumn = Null\r\n     varRowSourceType = Null\r\n     varRowSource = Null\r\n     varColumnCount = Null\r\n     varColumnWidths = Null\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     varCaption = fld.Properties(\"Caption\")\r\n     intControlType = fld.Properties(\"DisplayControl\")\r\n     Select Case intControlType\r\n         <span style=\"color:blue;\">Case <\/span>acTextBox\r\n             <span style=\"color:blue;\">Debug.Print<\/span> fld.Name, \"acTextBox\"\r\n         <span style=\"color:blue;\">Case <\/span>acComboBox\r\n             varBoundColumn = fld.Properties(\"BoundColumn\")\r\n             varRowSourceType = fld.Properties(\"RowSourceType\")\r\n             varRowSource = fld.Properties(\"RowSource\")\r\n             varColumnCount = fld.Properties(\"ColumnCount\")\r\n             varColumnWidths = fld.Properties(\"ColumnWidths\")\r\n         <span style=\"color:blue;\">Case <\/span>acCheckBox\r\n             <span style=\"color:blue;\">Debug.Print<\/span> fld.Name, \"acCheckBox\"\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"anderer Controltype\", intControlType\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Einlesen der Feldeigenschaften<\/span><\/b><\/p>\n<p>Einige Eigenschaften von Feldern kann man einfach so einlesen, aber bei einigen ist dies nicht so einfach m&ouml;glich: Es werden n&auml;mlich nicht alle Eigenschaften f&uuml;r jedes Feld angelegt. Beispielweise wird die Eigenschaft <b>Caption <\/b>nur f&uuml;r ein Feld hinterlegt, wenn der Benutzer die Eigenschaft <b>Beschriftung <\/b>&uuml;ber den Tabellenentwurf eingestellt hat. Anderenfalls ist die <b>Property <\/b>namens <b>Caption <\/b>schlicht nicht vorhanden und der Versuch, diese auszulesen, l&ouml;st einen Fehler aus.<\/p>\n<p>Daher lesen wir diese Werte bei deaktivierter Fehlerbehandlung ein. Das ist der Fall bei der Eigenschaft <b>Caption<\/b>, aber auch bei <b>DisplayControl<\/b>. Letztere legt fest, ob ein Feld im Datenblatt als Textfeld, Kontrollk&auml;stchen oder Kombinationsfeld angezeigt wird. Im Falle eines Kombinationsfeldes stehen noch einige weitere Eigenschaften zur Verf&uuml;gung. Um also herauszufinden, ob wir diese auch einlesen m&uuml;ssen, lesen wir zuerst den Wert der Eigenschaft <b>DisplayControl <\/b>ein. Lautet dieser <b>acComboBox<\/b>, lesen wir auch noch die nun verf&uuml;gbaren Eigenschaften <b>BoundColumn<\/b>, <b>RowSourceType<\/b>, <b>RowSource<\/b>, <b>ColumnCount <\/b>und <b>ColumnWidths <\/b>in die entsprechenden R&uuml;ckgabeparameter ein. Im Falle von <b>acTextBox <\/b>oder <b>acCheckBox <\/b>m&uuml;ssen keine weiteren Parameter eingelesen werden.<\/p>\n<h2>&Uuml;bersichtsformulare per Code erstellen<\/h2>\n<p>Damit haben wir alle Informationen erfasst, die wir zum Erstellen des &Uuml;bersichtsformulars ben&ouml;tigen und k&ouml;nnen nun den Code zusammenstellen. Dabei beginnen wir mit dem Unterformular, dass die Daten der Tabelle in der Datenblattansicht anzeigen soll. Wenn wir dieses erstellt haben, f&uuml;gen wir den Code zum Erstellen des Hauptformulars hinzu. Dieses wird schlie&szlig;lich auch ein Unterformularsteuerelement enthalten, das wir mit dem Unterformular f&uuml;llen.<\/p>\n<h2>Funktion zum Erstellen eines neuen Formulars<\/h2>\n<p>Wir verwenden eine einfache Funktion zum Erstellen der beiden Formulare. Diese hei&szlig;t <b>CreateNewForm<\/b> und erwartet den Namen des zu erstellenden Formulars als einzigen Parameter. Wie daran gut zu erkennen ist, erledigt die Funktion nichts anderes, als ein neues Formular zu erstellen (siehe Listing 5). Sie pr&uuml;ft mit der Hilfsfunktion ExistsForm, ob bereits ein Formular mit dem angegebenen Namen vorhanden ist:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>CreateNewForm(strName<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n      <span style=\"color:blue;\">Dim <\/span>frm<span style=\"color:blue;\"> As <\/span>Form\r\n      <span style=\"color:blue;\">Dim <\/span>strNameTemp<span style=\"color:blue;\"> As String<\/span>\r\n      <span style=\"color:blue;\">If <\/span>ExistsForm(strName)<span style=\"color:blue;\"> Then<\/span>\r\n          If <span style=\"color:blue;\">MsgBox<\/span>(\"Formular ''\" & strName & \"'' ist bereits vorhanden. &Uuml;berschreiben?\", vbYesNo + vbExclamation, _\r\n                  \"Formular &uuml;berschreiben\") = vbYes Then\r\n              <span style=\"color:blue;\">If <\/span>DeleteForm(strName) = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                  <span style=\"color:blue;\">Exit Function<\/span>\r\n              <span style=\"color:blue;\">End If<\/span>\r\n          <span style=\"color:blue;\">Else<\/span>\r\n              <span style=\"color:blue;\">Exit Function<\/span>\r\n          <span style=\"color:blue;\">End If<\/span>\r\n      <span style=\"color:blue;\">End If<\/span>\r\n      <span style=\"color:blue;\">Set<\/span> frm = CreateForm()\r\n      strNameTemp = frm.Name\r\n      frm.Visible = <span style=\"color:blue;\">True<\/span>\r\n      DoCmd.Close acForm, frm.Name, acSaveYes\r\n      DoCmd.Rename strName, acForm, strNameTemp\r\n      CreateNewForm = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Funktion zum Erstellen von Formularen<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ExistsForm(strForm<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n      <span style=\"color:blue;\">Dim <\/span>objForm<span style=\"color:blue;\"> As <\/span>AccessObject\r\n      For Each objForm In CurrentProject.AllForms\r\n          <span style=\"color:blue;\">If <\/span>objForm.Name = strForm<span style=\"color:blue;\"> Then<\/span>\r\n              ExistsForm = <span style=\"color:blue;\">True<\/span>\r\n              <span style=\"color:blue;\">Exit Function<\/span>\r\n          <span style=\"color:blue;\">End If<\/span>\r\n      <span style=\"color:blue;\">Next<\/span> objForm\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Falls ja, fragt die Funktion, ob das Formular &uuml;berschrieben werden soll. Antwortet man mit <b>Ja<\/b>, versucht die Routine, das Formular mit einer weiteren Funktion namens <b>DeleteForm <\/b>zu l&ouml;schen:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>DeleteForm(strName<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n      On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n      DoCmd.DeleteObject acForm, strName\r\n      <span style=\"color:blue;\">If <\/span>Err.Number = 0<span style=\"color:blue;\"> Then<\/span>\r\n          DeleteForm = <span style=\"color:blue;\">True<\/span>\r\n      <span style=\"color:blue;\">Else<\/span>\r\n          <span style=\"color:blue;\">MsgBox<\/span> Err.Description, <span style=\"color:blue;\">vbCr<\/span>itical + vbOKOnly, _\r\n              \"L&ouml;schen fehlgeschlagen\"\r\n      <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Gelingt dies nicht, wird die Funktion verlassen und liefert den Wert <b>False <\/b>zur&uuml;ck. Auch wenn man auf die Frage, ob ein bestehendes Formular &uuml;berschrieben werden soll, mit <b>Nein <\/b>antwortet, endet die Funktion mit dem R&uuml;ckgabewert <b>False<\/b>.<\/p>\n<p>Anderenfalls ruft die Funktion die Anweisung <b>CreateForm <\/b>auf und speichert den Verweis auf das neu erstellte Formular in der Variablen <b>frm<\/b>.<\/p>\n<p>Sie tr&auml;gt den von Access vergebenen Namen in die Variable <b>strNameTemp <\/b>ein. Das Formular wird dann geschlossen und die Funktion &auml;ndert noch den Namen vom tempor&auml;ren Namen in den als Parameter &uuml;bergebenen Namen.<\/p>\n<h2>Starten der Formularerstellung<\/h2>\n<p>Die eigentliche Formularerstellung mit dem Aufruf der zuvor beschriebenen Funktionen erfolgt, wenn der Benutzer die Schaltfl&auml;che <b>Erstellen <\/b>anklickt. F&uuml;r die Ereignisprozedur <b>Beim Klicken <\/b>hinterlegen wir die Prozedur aus Listing 6.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdCreate_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>frm<span style=\"color:blue;\"> As <\/span>Form\r\n     RunCommand acCmdSaveRecord\r\n     <span style=\"color:blue;\">If <\/span>CreateNewForm(Me!txtUnterformularname) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         DoCmd.OpenForm Me!txtUnterformularname, acDesign\r\n         <span style=\"color:blue;\">Set<\/span> frm = Forms(Me!txtUnterformularname)\r\n         <span style=\"color:blue;\">With<\/span> frm\r\n             .DefaultView = acDefViewDatasheet\r\n             .RecordSource = Me!cboDatasource\r\n             .HasModule = <span style=\"color:blue;\">True<\/span>\r\n             AddControlsOverviewSubform Me!OverviewformID\r\n         End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     ...\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Prozedur zum Erstellen der Formulare, hier zun&auml;chst f&uuml;r das Unterformular<\/span><\/b><\/p>\n<p>Diese speichert zun&auml;chst den aktuell im Formular angezeigten Datensatz. Nach dem Aufruf der weiter oben bereits beschriebenen Funktion <b>CreateForm <\/b>sollte das angehende Unterformular nun angelegt sein.<\/p>\n<p>Dieses &ouml;ffnen wir nun mit der <b>DoCmd.OpenForm<\/b>-Methode und referenzieren es mit der Objektvariablen <b>frm<\/b>. Nun stellen wir einige Eigenschaften f&uuml;r dieses Formular ein:<\/p>\n<ul>\n<li><b>DefaultView<\/b>: Legt mit <b>acDefViewDatasheet <\/b>fest, dass das Formular in der Datenblattansicht angezeigt werden soll.<\/li>\n<li><b>RecordSource<\/b>: Wird auf die aus <b>Me!cboDatasource <\/b>ausgelesene Datensatzquelle, also die Tabelle oder Abfrage, eingestellt.<\/li>\n<li><b>HasModule<\/b>: Legt mit dem Wert <b>True <\/b>fest, dass das Unterformular ein Klassenmodul enthalten soll.<\/li>\n<\/ul>\n<p>Au&szlig;erdem rufen wir f&uuml;r dieses Formular die Prozedur <b>AddControlsOverviewSubform <\/b>auf. Dieser Prozedur &uuml;bergeben wir den Prim&auml;rschl&uuml;sselwert des Datensatzes der Tabelle <b>tblOverviewforms<\/b>, f&uuml;r den wir die Steuerelemente hinzuf&uuml;gen wollen.<\/p>\n<h2>Steuerelemente zum Unterformular hinzuf&uuml;gen<\/h2>\n<p>Die Prozedur <b>AddControlsOverviewSubform <\/b>unterst&uuml;tzt uns beim Hinzuf&uuml;gen der Steuerelemente zum Unterformular, die in der Tabelle <b>tblOverviewfields<\/b> festgelegt wurden (siehe Listing 7).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AddControlsOverviewSubform(lngOverviewformID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>dbc<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rstControls<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strFormName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>ctl<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>lngMaxWidth<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngLabelWidth<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngTop<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n     <span style=\"color:blue;\">Set<\/span> rstForm = dbc.OpenRecordset(\"SELECT * FROM tblOverviewforms WHERE OverviewformID = \" & lngOverviewformID, _\r\n         dbOpenDynaset)\r\n     strFormName = rstForm!Subformname\r\n     <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n     <span style=\"color:blue;\">Set<\/span> rstControls = dbc.OpenRecordset(\"SELECT * FROM tblOverviewfields WHERE OverviewformID = \" _\r\n         & lngOverviewformID, dbOpenDynaset)\r\n     lngLabelWidth = GetMaxLabelWidth(rstControls)\r\n     lngTop = rstForm!Margin\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstControls.EOF\r\n         <span style=\"color:blue;\">If <\/span>rstControls!IgnoreField = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             Select Case rstControls!ControlType\r\n                 <span style=\"color:blue;\">Case <\/span>acTextBox\r\n                     <span style=\"color:blue;\">Set<\/span> ctl = AddTextBox(rstForm, rstControls, strFormName, acDetail, lngLabelWidth, lngTop, _\r\n                         lngMaxWidth)\r\n                 <span style=\"color:blue;\">Case <\/span>acComboBox\r\n                     <span style=\"color:blue;\">Set<\/span> ctl = AddComboBox(rstForm, rstControls, strFormName, acDetail, lngLabelWidth, lngTop, _\r\n                         lngMaxWidth)\r\n                 <span style=\"color:blue;\">Case <\/span>acCheckBox\r\n                     <span style=\"color:blue;\">Set<\/span> ctl = AddCheckBox(rstForm, rstControls, strFormName, acDetail, lngLabelWidth, lngTop, _\r\n                         lngMaxWidth)\r\n                 <span style=\"color:blue;\">Case Else<\/span>\r\n                     <span style=\"color:blue;\">Set<\/span> ctl = AddTextBox(rstForm, rstControls, strFormName, acDetail, lngLabelWidth, lngTop, lngMaxWidth)\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n             lngTop = lngTop + ctl.Height + rstForm!Margin\r\n             ctl.ColumnWidth = rstControls!FieldWidth\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         rstControls.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Prozedur zum Hinzuf&uuml;gen der Steuerelemente zum Unterformular<\/span><\/b><\/p>\n<p>Sie erwartet den Prim&auml;rschl&uuml;sselwert des Eintrags der Tabelle <b>tblOverviewforms<\/b> und weitere Parameter. Sie referenziert mit dem Recordset <b>rstForm <\/b>die Tabelle <b>tblOverviewforms <\/b>mit dem Hauptdatensatz f&uuml;r das zu erstellende Formular und ermittelt daraus den Namen des zu erstellenden Unterformulars.<\/p>\n<p>Dann referenziert sie die zu diesem Formular geh&ouml;renden Datens&auml;tze der Tabelle <b>tblOverviewfields <\/b>mit einem weiteren Recordset namens <b>rstControls<\/b>.<\/p>\n<p>Auch wenn dies in diesem Unterformular in der Datenblattansicht nicht unbedingt n&ouml;tig ist, holt die Prozedur mit der Funktion <b>GetMaxLabelWidth <\/b>die maximale Breite f&uuml;r die hinzuzuf&uuml;genden Steuerelemente (siehe Listing 8). In dieser Funktion ermitteln wir mithilfe der <b>Wizhook<\/b>-Klasse die Breiten f&uuml;r die Beschriftungen der abzubildenden Felder. Dabei nehmen wir ein Vorlagenformular zu Hilfe, das ein entsprechendes <b>Label<\/b>-Feld enth&auml;lt, von dem wir die Schriftarteigenschaften f&uuml;r die Berechnung der L&auml;nge der Texte heranziehen. Die Funktion durchl&auml;uft die Beschriftungen und ermittelt jeweils die Breite des Textes f&uuml;r die angegebenen Schrifteigenschaften. Ist die Breite f&uuml;r einen Text breiter als die bisher breiteste, wird dieser als der aktuell breiteste Wert gespeichert. Auf diese Weise erhalten wir am Ende den gr&ouml;&szlig;ten Wert f&uuml;r die Breite der Beschriftungen. Nachdem diese Breite ermittelt wurde, holen wir aus dem Feld <b>Margin <\/b>den Abstand zum oberen Rand und legen diesen als <b>lngTop <\/b>fest. Dann durchl&auml;uft die Prozedur alle Steuerelemente der Tabelle <b>tblOverviewfields <\/b>und pr&uuml;ft zuerst anhand der Eigenschaft <b>IgnoreField<\/b>, ob &uuml;berhaupt ein Steuerelement f&uuml;r dieses Feld angelegt werden soll. Falls ja, pr&uuml;fen wir in einer <b>Select Case<\/b>-Bedingung, welches Steuerelement angelegt werden soll. Auch, wenn es sich um ein Unterformular in der Datenblattansicht handelt, k&ouml;nnen neben Textfeldern auch Kombinationsfelder und Kontrollk&auml;stchen auftauchen.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetMaxLabelWidth(rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset)\r\n     <span style=\"color:blue;\">Dim <\/span>frm<span style=\"color:blue;\"> As <\/span>Form\r\n     <span style=\"color:blue;\">Dim <\/span>lbl<span style=\"color:blue;\"> As <\/span>Label\r\n     <span style=\"color:blue;\">Dim <\/span>lngBold<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngWidthText<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngHeight<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngWidthMax<span style=\"color:blue;\"> As Long<\/span>\r\n     DoCmd.OpenForm \"frmFontStyles\"\r\n     <span style=\"color:blue;\">Set<\/span> frm = Forms!frmFontStyles\r\n     <span style=\"color:blue;\">Set<\/span> lbl = frm!lblFontStyle\r\n     WizHook.Key = 51488399\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         <span style=\"color:blue;\">With<\/span> lbl\r\n             <span style=\"color:blue;\">If <\/span>.FontBold<span style=\"color:blue;\"> Then<\/span>\r\n                 lngBold = 700\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 lngBold = 400\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             WizHook.TwipsFromFont .FontName, .FontSize, lngBold, .FontItalic, .FontUnderline, 0, _\r\n                 rst!Fieldlabel & \":\", 0, lngWidthText, lngHeight\r\n         End <span style=\"color:blue;\">With<\/span>\r\n         <span style=\"color:blue;\">If <\/span>lngWidthText &gt; lngWidthMax<span style=\"color:blue;\"> Then<\/span>\r\n             lngWidthMax = lngWidthText\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     rst.MoveFirst\r\n     GetMaxLabelWidth = lngWidthMax\r\n     DoCmd.Close acForm, \"frmFontStyles\"\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Funktion zum Ermitteln der Breite der breitesten Beschriftung<\/span><\/b><\/p>\n<h2>Textfelder anlegen<\/h2>\n<p>Im Falle von <b>acTextBox <\/b>rufen wir die Funktion <b>AddTextBox <\/b>auf (siehe Listing 9). Dieser &uuml;bergeben wir die notwendigen Informationen &#8211; das Recordset <b>rstForm<\/b>, das Recordset <b>rstControls <\/b>mit den hinzuzuf&uuml;genden Feldern, den Namen des Formulars, den Bereich, in dem die Steuerelemente eingef&uuml;gt werden sollen und so weiter.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddTextBox(rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset, rstControls<span style=\"color:blue;\"> As <\/span>DAO.Recordset, strFormName<span style=\"color:blue;\"> As String<\/span>, _\r\n         lngSection<span style=\"color:blue;\"> As <\/span>AcSection, lngLabelWidth<span style=\"color:blue;\"> As Long<\/span>, lngTop<span style=\"color:blue;\"> As Long<\/span>, lngMaxWidth<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>ctl<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>lbl<span style=\"color:blue;\"> As <\/span>Label\r\n     <span style=\"color:blue;\">Set<\/span> ctl = CreateControl(strFormName, acTextBox, lngSection, , rstControls!FieldName, lngLabelWidth + 2 * _\r\n         rstForm!Margin, lngTop, rstControls!FieldWidth, Nz(rstControls!FieldHeight, 300))\r\n     <span style=\"color:blue;\">Set<\/span> lbl = CreateControl(strFormName, acLabel, lngSection, ctl.Name, , rstForm!Margin, lngTop, lngLabelWidth, _\r\n         Nz(rstControls!FieldHeight, 300))\r\n     lbl.Caption = rstControls!Fieldlabel & \":\"\r\n     <span style=\"color:blue;\">If <\/span>ctl.<span style=\"color:blue;\">Left<\/span> + ctl.Width &gt; lngMaxWidth<span style=\"color:blue;\"> Then<\/span>\r\n         lngMaxWidth = ctl.<span style=\"color:blue;\">Left<\/span> + ctl.Width\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> AddTextBox = ctl\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: Funktion zum Hinzuf&uuml;gen einer Textbox<\/span><\/b><\/p>\n<p>Die Routine verwendet die Funktion <b>CreateControl<\/b>, um dem Formular das Formular mit den entsprechenden Eigenschaften hinzuzuf&uuml;gen. Zus&auml;tzlich zum <b>Textbox<\/b>-Steuerelement wird auch noch ein <b>Label<\/b>-Steuerelement erstellt, das sp&auml;ter in der Datenblattansicht die Spalten&uuml;berschrift beisteuert. Au&szlig;erdem legt die Routine noch die Beschriftung des <b>Label<\/b>-Steuerelements fest und stellt die Position der Steuerelemente fest, damit diese untereinander eingef&uuml;gt werden.<\/p>\n<h2>Kontrollk&auml;stchen anlegen<\/h2>\n<p>Auf &auml;hnliche Weise legen wir mit der Funktion <b>AddCheckBox <\/b>die Steuerelemente f&uuml;r die Felder an, die als Kontrollk&auml;stchen ausgelegt werden sollen (siehe Listing 10).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddCheckBox(rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset, rstControls<span style=\"color:blue;\"> As <\/span>DAO.Recordset, strFormName<span style=\"color:blue;\"> As String<\/span>, _\r\n         lngSection<span style=\"color:blue;\"> As <\/span>AcSection, lngLabelWidth<span style=\"color:blue;\"> As Long<\/span>, lngTop<span style=\"color:blue;\"> As Long<\/span>, lngMaxWidth<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>ctl<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>lbl<span style=\"color:blue;\"> As <\/span>Label\r\n     <span style=\"color:blue;\">Set<\/span> ctl = CreateControl(strFormName, acCheckBox, lngSection, , rstControls!FieldName, lngLabelWidth + 2 * _\r\n         rstForm!Margin, lngTop + 50, rstControls!FieldWidth, Nz(rstControls!Fieldheight, 300))\r\n     <span style=\"color:blue;\">Set<\/span> lbl = CreateControl(strFormName, acLabel, lngSection, ctl.Name, , rstForm!Margin, lngTop, lngLabelWidth, _\r\n         Nz(rstControls!Fieldheight, 300))\r\n     lbl.Caption = rstControls!Fieldlabel & \":\"\r\n     <span style=\"color:blue;\">If <\/span>ctl.<span style=\"color:blue;\">Left<\/span> + ctl.Width &gt; lngMaxWidth<span style=\"color:blue;\"> Then<\/span>\r\n         lngMaxWidth = ctl.<span style=\"color:blue;\">Left<\/span> + ctl.Width\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> AddCheckBox = ctl\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 10: Funktion zum Hinzuf&uuml;gen eines Kontrollk&auml;stchens<\/span><\/b><\/p>\n<p>Hier finden wir einige wenige Unterschiede, zum Beispiel dass wir einen anderen Elementtypen verwenden, in diesem Fall <b>acCheckBox<\/b>.<\/p>\n<h2>Kombinationsfelder anlegen<\/h2>\n<p>Schlie&szlig;lich fehlt noch die dritte und aufwendigste Funktion zum Hinzuf&uuml;gen von Steuerelementen. Dabei f&uuml;gen wir mit dieser Funktion Kombinationsfelder zum Formular hinzu.<\/p>\n<p>Diese Funktion ist deshalb so aufwendig, weil wir hier wesentlich mehr Eigenschaften einstellen m&uuml;ssen. Dazu geh&ouml;rt die Angabe der gebundenen Spalte, die Anzahl der Spalten, die Spaltenbreiten, die Datensatzherkunft und der Herkunftstyp (siehe Listing 11).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddComboBox(rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset, rstControls<span style=\"color:blue;\"> As <\/span>DAO.Recordset, strFormName<span style=\"color:blue;\"> As String<\/span>, _\r\n         lngSection<span style=\"color:blue;\"> As <\/span>AcSection, lngLabelWidth<span style=\"color:blue;\"> As Long<\/span>, lngTop<span style=\"color:blue;\"> As Long<\/span>, lngMaxWidth<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>ctl<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>lbl<span style=\"color:blue;\"> As <\/span>Label\r\n     <span style=\"color:blue;\">Set<\/span> ctl = CreateControl(strFormName, acComboBox, lngSection, , rstControls!FieldName, lngLabelWidth + 2 * _\r\n         rstForm!Margin, lngTop, rstControls!FieldWidth, Nz(rstControls!Fieldheight, 300))\r\n     <span style=\"color:blue;\">Set<\/span> lbl = CreateControl(strFormName, acLabel, lngSection, ctl.Name, , rstForm!Margin, lngTop, lngLabelWidth, _\r\n         Nz(rstControls!Fieldheight, 300))\r\n     lbl.Caption = rstControls!Fieldlabel & \":\"\r\n     <span style=\"color:blue;\">With<\/span> ctl\r\n         .BoundColumn = rstControls!BoundColumn\r\n         .ColumnCount = rstControls!ColumnCount\r\n         .ColumnWidths = rstControls!ColumnWidths\r\n         .RowSource = rstControls!RowSource\r\n         .RowSourceType = rstControls!RowSourceType\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">If <\/span>ctl.<span style=\"color:blue;\">Left<\/span> + ctl.Width &gt; lngMaxWidth<span style=\"color:blue;\"> Then<\/span>\r\n         lngMaxWidth = ctl.<span style=\"color:blue;\">Left<\/span> + ctl.Width\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> AddComboBox = ctl\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 11: Funktion zum Hinzuf&uuml;gen eines Kombinationsfeldes<\/span><\/b><\/p>\n<h2>Unterformular pr&uuml;fen<\/h2>\n<p>Nachdem wir die Prozedur <b>cmdCreate_Click <\/b>durchgef&uuml;hrt haben, die wiederum die Routinen <b>CreateNewForm <\/b>und <b>AddControlsOverviewSubform <\/b>aufgerufen haben, ist das Unterformular bereits angelegt. Wir k&ouml;nnen uns seinen Entwurf nun ansehen (siehe Bild 5). Die Steuerelemente haben gegebenenfalls keinen Abstand voneinander, aber das spielt hier keine Rolle &#8211; das Unterformular soll ohnehin in der Datenblattansicht erscheinen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_005.png\" alt=\"Entwurf des automatisch generierten Unterformulars\" width=\"424,5589\" height=\"267,1934\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Entwurf des automatisch generierten Unterformulars<\/span><\/b><\/p>\n<p>Wechseln wir in die Datenblattansicht, sehen wir das Formular wie in Bild 6. Hier stellen wir fest, dass wir die initialen Spaltenbreiten noch optimieren k&ouml;nnen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_006.png\" alt=\"Per Code generiertes Formular in der Datenblattansicht\" width=\"649,559\" height=\"206,2091\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Per Code generiertes Formular in der Datenblattansicht<\/span><\/b><\/p>\n<p>Das erledigen wir in der Liste der Felder im Formular <b>frmOverviewforms<\/b>, wo wir die Spaltenbreiten individuell einstellen k&ouml;nnen (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_007.png\" alt=\"Einstellen der Spaltenbreiten f&uuml;r das Datenblatt\" width=\"700\" height=\"289,4575\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Einstellen der Spaltenbreiten f&uuml;r das Datenblatt<\/span><\/b><\/p>\n<p>Nachdem wir diese Werte angepasst und das Formular erneut erstellt haben, finden wir die Spalten in der gew&uuml;nschten Breite vor.<\/p>\n<h2>Hauptformular erstellen<\/h2>\n<p>Nun ben&ouml;tigen wir noch das Hauptformular, indem das Unterformular angezeigt wird. Um dieses anzulegen und dort das Unterformular einzuf&uuml;gen, erg&auml;nzen wir den Code der Prozedur <b>cmdCreate_Click <\/b>wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdCreate_Click()\r\n     ...\r\n     <span style=\"color:blue;\">If <\/span>CreateNewForm(Me!Formname) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         DoCmd.OpenForm Me!Formname, acDesign\r\n         <span style=\"color:blue;\">Set<\/span> frm = Forms(Me!Formname)\r\n         <span style=\"color:blue;\">With<\/span> frm\r\n             .AutoCenter = Me!chkAutoCenter\r\n             .Caption = Me!txtFormTitle\r\n             .DefaultView = acDefViewSingle\r\n             .RecordSelectors = <span style=\"color:blue;\">False<\/span>\r\n             .NavigationButtons = <span style=\"color:blue;\">False<\/span>\r\n             .DividingLines = <span style=\"color:blue;\">False<\/span>\r\n             .ScrollBars = <span style=\"color:blue;\">False<\/span>\r\n             .HasModule = <span style=\"color:blue;\">True<\/span>\r\n             .Width = Me!txtSubformWidth + 2 * Me!txtMargin\r\n             AddControlsOverviewMainForm _\r\n                 Me!OverviewformID\r\n         End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier legen wir mit <b>CreateNewForm <\/b>ein neues Formular an und speichern es unter dem Namen aus dem Feld <b>Formname <\/b>des Formulars. Danach &ouml;ffnen wir dieses in der Entwurfsansicht und passen es weiter an. Wir stellen die Eigenschaften <b>Automatisch zentrieren <\/b>und <b>Beschriftung <\/b>auf die gew&auml;hlten Werte ein. Die Standardansicht legen wir auf <b>Einzelnes Formular <\/b>fest. Die Eigenschaften <b>Datensatzmarkierer<\/b>, <b>Navigationsschaltfl&auml;chen<\/b>, <b>Trennlinien <\/b>und <b>Bildlaufleisten <\/b>stellen wir auf <b>Nein <\/b>ein.<\/p>\n<p><b>HasModule <\/b>legen wir auf <b>Ja <\/b>fest, da wir Ereignisprozeduren f&uuml;r das Suchfeld und die Schaltfl&auml;chen hinzuf&uuml;gen wollen. Die Breite des Formulars legen wir auf die Breite des Unterformulars plus zwei Mal den Abstand zum Rand aus dem Feld <b>Margin <\/b>fest. Schlie&szlig;lich rufen wir die Prozedur <b>AddControlsOverviewMainForm <\/b>auf, der wir einige Parameter wie etwa die ID des Datensatzes aus der Tabelle <b>tblOverviewforms <\/b>mit den Informationen zum Anlegen der Steuerelemente &uuml;bergeben.<\/p>\n<h2>Steuerelemente zum Hauptformular hinzuf&uuml;gen<\/h2>\n<p>Die Prozedur <b>AddControlsOverviewMainForm <\/b>erwartet als Parameter die ID des Datensatzes der Tabelle <b>tblOverviewforms<\/b>.<\/p>\n<p>Aus diesem stammt die Konfiguration zum Hinzuf&uuml;gen der Daten (siehe Listing 12). Sie &ouml;ffnet ein entsprechendes Recordset auf Basis dieser Tabelle. Der Formularname wird in <b>strFormName <\/b>zwischengespeichert, der Rand aus dem Feld <b>Margin <\/b>dient als Startwert der beiden Variablen <b>lngTop <\/b>und <b>lngLeft<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AddControlsOverviewMainForm(lngOverviewformID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>dbc<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstButtonStyles<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strFormName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>cmd<span style=\"color:blue;\"> As <\/span>CommandButton\r\n     <span style=\"color:blue;\">Dim <\/span>lngLeft<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngMaxWidth<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngTop<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n     <span style=\"color:blue;\">Set<\/span> rstForm = dbc.OpenRecordset(\"SELECT * FROM tblOverviewforms WHERE OverviewformID = \" & lngOverviewformID, _\r\n         dbOpenDynaset)\r\n     strFormName = rstForm!Formname\r\n     lngTop = rstForm!Margin\r\n     lng<span style=\"color:blue;\">Left<\/span> = rstForm!Margin\r\n     <span style=\"color:blue;\">Set<\/span> rstButtonStyles = dbc.OpenRecordset(\"SELECT * FROM tblButtonStyles WHERE ButtonStyleID = \" _\r\n         & rstForm!ButtonStyleID, dbOpenDynaset)\r\n     <span style=\"color:blue;\">If <\/span>rstForm!Searchtextbox = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Call<\/span> AddSearchControls(rstForm, lngLeft, lngTop)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>rstForm!EditButton = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> cmd = AddButton(rstForm, rstButtonStyles, \"Edit\", lngLeft, lngTop, lngMaxWidth)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>rstForm!AddNewButton = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> cmd = AddButton(rstForm, rstButtonStyles, \"AddNew\", lngLeft, lngTop, lngMaxWidth)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>rstForm!DeleteButton = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> cmd = AddButton(rstForm, rstButtonStyles, \"Delete\", lngLeft, lngTop, lngMaxWidth)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     lng<span style=\"color:blue;\">Left<\/span> = rstForm!Margin\r\n     lngTop = lngTop + 2 * rstForm!Margin + cmd.Height\r\n     AddSubform rstForm, lngLeft, lngTop\r\n     lngTop = lngTop + rstForm!Subformheight + 2 * rstForm!Margin\r\n     lng<span style=\"color:blue;\">Left<\/span> = rstForm!Margin\r\n     <span style=\"color:blue;\">If <\/span>rstForm!OKButton = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> cmd = AddButton(rstForm, rstButtonStyles, \"OK\", lngLeft, lngTop, lngMaxWidth)\r\n         cmd.VerticalAnchor = acVerticalAnchorBottom\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 12: Diese Prozedur steuert das Hinzuf&uuml;gen der Steuerelemente zum Hauptformular<\/span><\/b><\/p>\n<p>Ein weiteres Recordset &ouml;ffnet den Datensatz der Tabelle <b>tblButtonStyles<\/b>. Hier ist ein Satz von Informationen zum Layout der Schaltfl&auml;chen gespeichert, den wir im Formular <b>frmButtonStyles <\/b>bearbeiten k&ouml;nnen. Hier k&ouml;nnen wir auch neue Stylesets anlegen (siehe Bild 8).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_008.png\" alt=\"Formular zum Festlegen des Schaltfl&auml;chen-Styles\" width=\"424,5589\" height=\"180,6457\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Formular zum Festlegen des Schaltfl&auml;chen-Styles<\/span><\/b><\/p>\n<h2>Suchsteuerelemente hinzuf&uuml;gen<\/h2>\n<p>Hat der Benutzer mit dem Feld <b>SearchTextBox <\/b>festgelegt, dass ein Suchfeld angelegt werden soll, ruft die Prozedur eine weitere Routine namens <b>AddSearchControls <\/b>auf (siehe Listing 13). Diese erwartet einen Verweis auf das Recordset mit den Konfigurationsdaten sowie die linke und obere Position, an der neue Steuerelemente angelegt werden sollen. Es wird als Erstes das Bezeichnungsfeld f&uuml;r das Suchfeld erstellt. Dazu ruft sie die Anweisung <b>CreateControl <\/b>auf und &uuml;bergibt ihr das Zielformular, den Steuerelementtyp (<b>acLabel<\/b>), den Zielbereich sowie die Position und die Gr&ouml;&szlig;e. Die H&ouml;he haben wir mit <b>300 <\/b>voreingestellt, die Breite mit <b>100<\/b>. Warum so gering? Weil wir die Breite noch optimieren.  Dazu lesen wir die Beschriftung aus dem Feld <b>SearchCaption <\/b>aus und weisen diese dem Bezeichnungsfeld zu. Dann nutzen wir eine Hilfsfunktion namens <b>GetLabelWidth<\/b>, welche die optimale Breite des Bezeichnungsfeldes ermittelt. Dieser &uuml;bergeben wir einen Verweis auf das Bezeichnungsfeld sowie den anzuzeigenden Text als Parameter. Sie nutzt die <b>Wizhook<\/b>-Methode <b>TwipsFromFont<\/b>, um die Breite des Textes anhand der Eigenschaften des Bezeichnungsfeldes zu ermitteln:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddSearchControls(rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset, lngLeft<span style=\"color:blue;\"> As Long<\/span>, lngTop<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>txtSearch<span style=\"color:blue;\"> As <\/span>TextBox\r\n     <span style=\"color:blue;\">Dim <\/span>lblSearch<span style=\"color:blue;\"> As <\/span>Label\r\n     <span style=\"color:blue;\">Dim <\/span>lngLabelWidth<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> lblSearch = CreateControl(rstForm!Formname, acLabel, acDetail, , , lngLeft, lngTop + 50, 100, 300)\r\n     lblSearch.Caption = rstForm!searchcaption\r\n     lngLabelWidth = GetLabelWidth(lblSearch, rstForm!searchcaption) * 1.2\r\n     lblSearch.Width = lngLabelWidth\r\n     lng<span style=\"color:blue;\">Left<\/span> = lng<span style=\"color:blue;\">Left<\/span> + lblSearch.Width + rstForm!Margin\r\n     <span style=\"color:blue;\">Set<\/span> txtSearch = CreateControl(rstForm!Formname, acTextBox, acDetail, , , lngLeft, lngTop + 50, 3000, 300)\r\n     AddTextboxOnChangeEvent Forms(rstForm!Formname), txtSearch, rstForm!SearchCode\r\n     lng<span style=\"color:blue;\">Left<\/span> = lng<span style=\"color:blue;\">Left<\/span> + txtSearch.Width + rstForm!Margin\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 13: Funktion zum Anlegen des Suchfelds<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetLabelWidth(lbl<span style=\"color:blue;\"> As <\/span>Label, _\r\n         strCaption<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngBold<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngWidthText<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngHeight<span style=\"color:blue;\"> As Long<\/span>\r\n     WizHook.Key = 51488399\r\n     <span style=\"color:blue;\">With<\/span> lbl\r\n         <span style=\"color:blue;\">If <\/span>.FontBold<span style=\"color:blue;\"> Then<\/span>\r\n             lngBold = 700\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             lngBold = 400\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         WizHook.TwipsFromFont .FontName, .FontSize, _\r\n             lngBold, .FontItalic, .FontUnderline, 0, _\r\n             strCaption, 0, lngWidthText, lngHeight\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     GetLabelWidth = lngWidthText\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Diesen Wert multipliziert sie mit <b>1,2<\/b>, damit wir ein wenig Spiel bei der Breite des Bezeichnungsfeldes haben, und stellt die Breite schlie&szlig;lich auf diesen Wert ein. Dementsprechend passt die Prozedur die Position f&uuml;r das nachfolgend zu erstellende Textfeld an und erstellt dieses mit einem weiteren Aufruf der <b>CreateControl<\/b>-Methode. Diesmal wird ein Steuerelement des Typs <b>acTextBox <\/b>angelegt.<\/p>\n<h2>Ereignisprozedur mit Suchfunktion hinzuf&uuml;gen<\/h2>\n<p>Diesem Steuerelement f&uuml;gen wir noch eine Ereignisprozedur hinzu, in diesem Fall f&uuml;r das Ereignis <b>Bei &Auml;nderung<\/b>. Wir wollen hier die M&ouml;glichkeit bieten, immer zu filtern, wenn der Benutzer den Inhalt des Suchfeldes &auml;ndert. Dazu rufen wir die Prozedur <b>AddTextBoxOnChangeEvent <\/b>auf, die wie in Listing 14 aussieht.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AddTextboxOnChangeEvent(frm<span style=\"color:blue;\"> As <\/span>Form, txt<span style=\"color:blue;\"> As <\/span>TextBox, strCode<span style=\"color:blue;\"> As String<\/span>)\r\n      <span style=\"color:blue;\">Dim <\/span>objVBProject<span style=\"color:blue;\"> As <\/span>VBProject\r\n      <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBComponent\r\n      <span style=\"color:blue;\">Dim <\/span>objModule<span style=\"color:blue;\"> As <\/span>CodeModule\r\n      <span style=\"color:blue;\">Dim <\/span>lngEventProc<span style=\"color:blue;\"> As Long<\/span>\r\n      <span style=\"color:blue;\">If <\/span>frm.HasModule = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n          frm.HasModule = <span style=\"color:blue;\">True<\/span>\r\n      <span style=\"color:blue;\">End If<\/span>\r\n      txt.OnChange = \"[Event Procedure]\"\r\n      <span style=\"color:blue;\">Set<\/span> objVBProject = GetCurrentVBProject\r\n      <span style=\"color:blue;\">Set<\/span> objVBComponent = objVBProject.VBComponents(\"Form_\" & frm.Name)\r\n      <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> ExistsProc(txt.Name & \"_Change\", objVBComponent)<span style=\"color:blue;\"> Then<\/span>\r\n          <span style=\"color:blue;\">Set<\/span> objModule = objVBComponent.CodeModule\r\n          lngEventProc = objModule.CreateEventProc(\"Change\", txt.Name)\r\n          lngEventProc = lngEventProc + 1\r\n          objModule.DeleteLines lngEventProc, 1\r\n          objModule.InsertLines lngEventProc, strCode\r\n      <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 14: Diese Prozedur f&uuml;gt eine Ereignisprozedur f&uuml;r das Suchfeld hinzu.<\/span><\/b><\/p>\n<p>Sie stellt die Eigenschaft <b>OnChange <\/b>des Textfeldes auf <b>[Event Procecure] <\/b>ein, damit das Textfeld wei&szlig;, dass es eine solche Ereignisprozedur gibt. Au&szlig;erdem f&uuml;gt sie dem Klassenmodul des Formulars ein neues Ereignis mit einem Namen hinzu, der aus dem Namen des Steuerelements und der Bezeichnung des Ereignisses zusammengesetzt ist, beispielsweise <b>txtSuche_OnChange<\/b>. Als Code der Ereignisprozedur verwendet sie den Code, den der Benutzer f&uuml;r das Feld <b>SearchCode <\/b>der Tabelle <b>tblOverviewforms <\/b>hinterlegt hat.<\/p>\n<h2>Weitere Schaltfl&auml;chen hinzuf&uuml;gen<\/h2>\n<p>Die folgenden Anweisungen pr&uuml;fen jeweils, ob die Felder <b>EditButton<\/b>, <b>AddNewButton <\/b>und <b>DeleteButton <\/b>den Wert True enthalten. In diesem Fall ruft die Prozedur jeweils die Funktion <b>AddButton <\/b>hinzu und &uuml;bergibt einen Verweis auf das Recordset mit der Konfiguration, das Recordset mit den Style-Informationen sowie eine Kennzeichnung, die sich in einigen Feldern der Tabelle <b>tblOverviewforms <\/b>wiederfindet und die es erm&ouml;glicht, dass wir die Funktion <b>AddButton <\/b>f&uuml;r verschiedene Schaltfl&auml;chen programmieren konnten. Sie braucht nur einen Wert wie <b>Edit<\/b>, <b>AddNew <\/b>oder <b>Delete<\/b>, um die entsprechenden Felder der Tabelle <b>tblOverviewforms <\/b>auszulesen.<\/p>\n<p>Die Funktion <b>AddButton<\/b> finden wir in Listing 15. Sie erstellt als Erstes mit der <b>CreateControl<\/b>-Anweisung das neue <b>Button<\/b>-Element und stellt das Zielformular, den Steuerelementtyp und den Zielbereich im Formular ein. Au&szlig;erdem legen wir die Position auf bew&auml;hrte Art fest und stellen die Gr&ouml;&szlig;e ein, hier zun&auml;chst auf eine Breite von 2.000 und eine H&ouml;he von 400.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddButton(rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset, rstButtonStyles<span style=\"color:blue;\"> As <\/span>DAO.Recordset, strBtnLbl<span style=\"color:blue;\"> As String<\/span>, _\r\n         lngLeft<span style=\"color:blue;\"> As Long<\/span>, lngTop<span style=\"color:blue;\"> As Long<\/span>, lngMaxWidth<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>cmd<span style=\"color:blue;\"> As <\/span>CommandButton\r\n     <span style=\"color:blue;\">Dim <\/span>lngWidthBase<span style=\"color:blue;\"> As Long<\/span>, lngBold<span style=\"color:blue;\"> As Long<\/span>, lngWidthText<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngHeightText<span style=\"color:blue;\"> As Long<\/span>, lngIconID<span style=\"color:blue;\"> As Long<\/span>, strIconName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> cmd = CreateControl(rstForm!Formname, acCommandButton, acDetail, , , lngLeft, lngTop, 2000, 400)\r\n     <span style=\"color:blue;\">With<\/span> cmd\r\n         lngIconID = Nz(rstForm(strBtnLbl & \"ButtonIcon\"), 0)\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngIconID = 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span>CopyIcon(lngIconID) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 strIconName = CodeDb.OpenRecordset(\"SELECT Name FROM MSysResources WHERE ID = \" & lngIconID).Fields(0)\r\n                 .Picture = strIconName ''rstForm(\"cbo\" & strBtnLbl & \"ButtonIcon\").Columns(1) '' DLookup(\"Name\", _\r\n                     \"MSysResources\", \"Name = \" & rstForm(strBtnLbl & \"ButtonIcon\"))\r\n                 .PictureCaptionArrangement = acRight\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             .Caption = \" \" & rstForm(strBtnLbl & \"ButtonCaption\")\r\n             lngWidthBase = 550\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             .Caption = rstForm(strBtnLbl & \"ButtonCaption\")\r\n             lngWidthBase = 200\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         .BorderStyle = rstButtonStyles!BorderStyle\r\n         .BackStyle = rstButtonStyles!BackStyle\r\n         .Alignment = rstButtonStyles!Alignment\r\n         <span style=\"color:blue;\">If <\/span>strBtnLbl = \"OK\"<span style=\"color:blue;\"> Then<\/span>\r\n             .Default = rstForm!OKButtonAsStandard\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>strBtnLbl = \"Cancel\"<span style=\"color:blue;\"> Then<\/span>\r\n             .Cancel = rstForm!CancelButtonAsCancel\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         .Name = \"cmd\" & strBtnLbl\r\n         WizHook.Key = 51488399\r\n         <span style=\"color:blue;\">If <\/span>.FontBold<span style=\"color:blue;\"> Then<\/span>\r\n             lngBold = 700\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             lngBold = 400\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         WizHook.TwipsFromFont .FontName, .FontSize, lngBold, .FontItalic, .FontUnderline, 0, .Caption, 0, _\r\n             lngWidthText, lngHeightText\r\n         .Width = lngWidthBase + lngWidthText\r\n         lng<span style=\"color:blue;\">Left<\/span> = lng<span style=\"color:blue;\">Left<\/span> + .Width + 150\r\n         AddButtonEvent Forms(rstForm!Formname), cmd, Nz(rstForm(strBtnLbl & \"Code\"), \"\")\r\n         <span style=\"color:blue;\">If <\/span>cmd.<span style=\"color:blue;\">Left<\/span> + cmd.Width &gt; lngMaxWidth<span style=\"color:blue;\"> Then<\/span>\r\n             lngMaxWidth = cmd.<span style=\"color:blue;\">Left<\/span> + cmd.Width\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> AddButton = cmd\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 15: Prozedur zum Hinzuf&uuml;gen eines Buttons<\/span><\/b><\/p>\n<p>Dann pr&uuml;fen wir, ob der Benutzer ein Icon f&uuml;r die Schaltfl&auml;che ausgew&auml;hlt hat. Falls ja, ermitteln wir die ID des Icons aus der Tabelle <b>MSysResources<\/b>. Ist eines selektiert, kopieren wir das Icon zun&auml;chst mit der <b>CopyIcon<\/b>-Funktion aus der Tabelle <b>MSysResources <\/b>der Add-In-Datenbank in die gleichnamige Tabelle der Host-Datenbank, in der wir das Formular erstellen wollen (siehe Modul <b>mdlAddControls<\/b>).<\/p>\n<p>Ist dies gelingen, ermitteln wir den Wert des Feldes <b>Name <\/b>f&uuml;r den gefundenen Datensatz aus der Tabelle <b>MSysResources <\/b>der Host-Datenbank und weisen diesen der Eigenschaft <b>Picture <\/b>der hinzugef&uuml;gten Schaltfl&auml;che zu. Die Ausrichtung f&uuml;r das Icon legen wir auf links fest. Dann f&uuml;gen wir der Eigenschaft <b>Caption <\/b>die Beschriftung f&uuml;r die Schaltfl&auml;che aus der Tabelle <b>tblOverviewforms <\/b>hinzu.<\/p>\n<p>Hier kommt zum Tragen, dass wir f&uuml;r die unterschiedlichen Schaltfl&auml;chen eine Zeichenkette wie <b>AddNew<\/b>, <b>Edit <\/b>oder <b>Delete <\/b>&uuml;bergeben &#8211; diese wird nun bei Ermitteln des Feldes herangezogen, in dem sich die Beschriftung f&uuml;r die Schaltfl&auml;che befindet.<\/p>\n<p>Wenn der Benutzer kein Icon ausgew&auml;hlt hat, weisen wir einfach nur die Beschriftung zu.<\/p>\n<p>Schlie&szlig;lich stellt die Funktion <b>AddButton <\/b>noch die Eigenschaften der Schaltfl&auml;che ein, wie sie in dem gew&auml;hlten Style-Set aus der Tabelle <b>tblButtonStyles <\/b>angegeben ist.<\/p>\n<p>Schlie&szlig;lich stellen wir noch den Namen der Schaltfl&auml;che ein und ermitteln die Breite der Schaltfl&auml;che. Dazu nutzen wir wieder die <b>Wizhook<\/b>-Methode <b>TwipsFromFont<\/b>, der wir die Eigenschaften der Schriftart der Schaltfl&auml;che sowie den anzuzeigenden Text &uuml;bergeben. Die Breite stellen wir dann auf die Summe aus einer Basisbreite (f&uuml;r das Icon, falls vorhanden) und die Breite f&uuml;r den Text ein.<\/p>\n<p>Schlie&szlig;lich rufen wir noch die Prozedur <b>AddButtonEvent <\/b>auf. Diese ist &auml;hnlich aufgebaut wie die Prozedur <b>AddTextboxOnChangeEvent <\/b>und f&uuml;gt dem Formular eine Ereignisprozedur f&uuml;r die jeweilige Schaltfl&auml;che hinzu. Den Code f&uuml;r diese Ereignisprozeduren haben wir in den entsprechenden Feldern festgelegt.<\/p>\n<h2>Unterformular hinzuf&uuml;gen<\/h2>\n<p>Schlie&szlig;lich fehlt noch das Unterformular mit den anzuzeigenden Daten. Dieses legen wir mit der Prozedur <b>AddSubform <\/b>an, der wir einen Verweis auf das Recordset mit den Konfigurationsdaten sowie die Position &uuml;bergeben.<\/p>\n<p>Die Prozedur <b>AddSubform <\/b>finden wir in Listing 16. Sie erstellt wieder mit der Anweisung <b>CreateControl <\/b>ein neues Steuerelement, diesmal mit dem Typ <b>acSubform<\/b>. Dieses referenzieren wir mit der Variablen <b>sfm <\/b>mit dem Datentyp <b>Subform<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddSubform(rstForm<span style=\"color:blue;\"> As <\/span>DAO.Recordset, lngLeft<span style=\"color:blue;\"> As Long<\/span>, lngTop<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>sfm<span style=\"color:blue;\"> As <\/span>SubForm\r\n     <span style=\"color:blue;\">Set<\/span> sfm = CreateControl(rstForm!Formname, acSubform, acDetail, , , lngLeft, lngTop + 50, rstForm!Subformwidth, _\r\n         rstForm!Subformheight)\r\n     sfm.SourceObject = rstForm!subformname\r\n     sfm.HorizontalAnchor = acHorizontalAnchorBoth\r\n     sfm.VerticalAnchor = acVerticalAnchorBoth\r\n     <span style=\"color:blue;\">Set<\/span> AddSubform = sfm\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 16: Prozedur zum Hinzuf&uuml;gen des Unterformulars<\/span><\/b><\/p>\n<p>Mit der Eigenschaft <b>SourceObject <\/b>stellen wir den Namen des Formulars ein, dass im Unterformular angezeigt werden soll.<\/p>\n<p>Die beiden Eigenschaften <b>HorizontalAnchor <\/b>und <b>VerticalAnchor <\/b>stellen wir auf die Werte <b>acHorizontalAnchorBoth <\/b>und <b>acVerticalAnchorBoth <\/b>ein, damit das Unterformularsteuerelement seine Gr&ouml;&szlig;e anpasst, wenn der Benutzer die Gr&ouml;&szlig;e des &uuml;bergeordneten Formulars &auml;ndert.<\/p>\n<p>Schlie&szlig;lich gibt die Funktion den Verweis auf das Unterformular als Funktionsergebnis an die aufrufende Prozedur zur&uuml;ck, wo er aber in diesem Fall nicht verarbeitet wird. <\/p>\n<h2>OK-Schaltfl&auml;che hinzuf&uuml;gen<\/h2>\n<p>Damit fehlt nur noch die <b>Ok<\/b>-Schaltfl&auml;che. Diese legen wir in der n&auml;chsten Zeile unter dem Unterformular an. Zuvor pr&uuml;fen wir anhand des Feldes <b>OKButton<\/b>, ob eine solche Schaltfl&auml;che &uuml;berhaupt gew&uuml;nscht ist. Falls ja, verwenden wir einen weiteren Aufruf der Prozedur <b>AddButton<\/b>, um den Button hinzuzuf&uuml;gen. Schlie&szlig;lich stellen wir den vertikalen Anker dieser Schaltfl&auml;che auf <b>Unten <\/b>ein, damit diese nicht verschwindet, wenn der Benutzer das Formular vertikal vergr&ouml;&szlig;ert und sich das Unterformular nach unten ausdehnt. Auch f&uuml;r die <b>OK<\/b>-Schaltfl&auml;che f&uuml;gen wir noch ein Prozedur zum Formularmodul hinzu.<\/p>\n<h2>Von der L&ouml;sung zum Access-Add-In<\/h2>\n<p>Beim Entwickeln haben wir die Elemente dieses Projekts direkt in die bestehende L&ouml;sung aus dem Beitrag <b>Detailformular per Mausklick erstellen <\/b>(<b>www.access-im-unternehmen.de\/10<\/b>) integriert.<\/p>\n<p>Dabei handelt es sich bereits um eine <b>.accda<\/b>-Datenbank, also eine Add-In-Datenbank. <\/p>\n<p>Wir haben die Voraussetzungen f&uuml;r den Einsatz in anderen Datenbanken also bereits teilweise bereitgestellt. Allerdings wollen wir nun noch die letzten Schritte gehen, damit wir auch dieses Add-In zum Erstellen von &Uuml;bersichtsformularen nutzen k&ouml;nnen. Dazu erweitern wir die Tabelle <b>USysRegInfo<\/b> entsprechend, indem wir die vorhandenen Eintr&auml;ge kopieren. Hier benennen wir zun&auml;chst die Werte im Feld <b>Subkey <\/b>um, sodass die Eintr&auml;ge f&uuml;r die beiden Add-Ins unterschieden werden k&ouml;nnen.<\/p>\n<p>Au&szlig;erdem passen wir die Werte der Datens&auml;tze f&uuml;r <b>Expression <\/b>und <b>Description <\/b>beziehungsweise <b>Description<\/b> und <b>Function <\/b>wie in Bild 9 an.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_1528_009.png\" alt=\"Anpassen der Tabelle USysRegInfo\" width=\"700\" height=\"367,4663\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Anpassen der Tabelle USysRegInfo<\/span><\/b><\/p>\n<p>Schlie&szlig;lich f&uuml;gen wir im Modul <b>mdlAddIn<\/b> noch die Aufrufe f&uuml;r das neue Formular als Men&uuml;-Add-In und als Formular-Assistent hinzu (siehe Listing 17).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Autostart_Overviewforms()\r\n     DoCmd.OpenForm \"frmOverviewforms\"\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Function <\/span>StartWizard_OverviewForms(strRecordSource<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> rst = CodeDb.OpenRecordset(\"SELECT * FROM tblOverviewforms WHERE Datasource = ''\" & strRecordSource & \"''\")\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         DoCmd.OpenForm \"frmOverviewforms\", DataMode:=acFormEdit, WhereCondition:=\"OverviewformID = \" & rst!OverviewformID\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         DoCmd.OpenForm \"frmOverviewforms\", DataMode:=acFormAdd, OpenArgs:=strRecordSource\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 17: Die Funktionen zum Aufrufen des Formulars &uuml;ber die Add-In-Schnittstelle<\/span><\/b><\/p>\n<h2>Access-Add-In installieren<\/h2>\n<p>Damit wir das Access-Add-In nun in Access nutzen k&ouml;nnen, um neue Formulare auf Basis der Tabellen einer Datenbank erstellen zu k&ouml;nnen, m&uuml;ssen wir nur noch den Add-In-Manager aufrufen und dort auf <b>Neues hinzuf&uuml;gen&#8230; <\/b>klicken. Anschlie&szlig;end finden wir dort nicht nur den neuen Eintrag im Ribbon unter <b>Datenbanktools|Add-Ins|Add-Ins <\/b>vor, sondern auch beim Anlegen eines neuen Formulars per Assistent. <\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Beitrag beschreibt die Erstellung eines Access-Add-Ins, mit dem Sie mit wenigen Mausklicks h&uuml;bsch formatierte &Uuml;bersichtsformulare erstellen k&ouml;nnen.<\/p>\n<p>In einem weiteren Beitrag namens <b>Add-In f&uuml;r &Uuml;bersichtsformulare im Einsatz <\/b>(<b>www.access-im-unternehmen.de\/1529<\/b>) schauen wir uns noch an, wie dieses Add-In praktisch eingesetzt werden kann.<\/p>\n<p>Au&szlig;erdem k&ouml;nnen wir dieses Add-In noch dahingehend weiterentwickeln, dass wir das Erstellen des Codes f&uuml;r die Suchfunktion und die Schaltfl&auml;chen noch vereinfachen.<\/p>\n<p>Eine weitere M&ouml;glichkeit, die sich leicht bewerkstelligen lie&szlig;e, w&auml;re das Hinzuf&uuml;gen von Informationen wie dem Namen des Formulars, dass die Daten des &Uuml;bersichtsformulars in der Detailansicht anzeigt &#8211; und des Prim&auml;rschl&uuml;sselfeldes der Datensatzquelle dieses Formulars.<\/p>\n<p>Damit k&ouml;nnten wir dann die Erstellung des Codes f&uuml;r die beiden Schaltfl&auml;chen zum Anlegen und Bearbeiten des aktuell ausgew&auml;hlten Datensatzes ebenfalls automatisieren. Wir k&ouml;nnten dann einfach die entsprechenden <b>DoCmd.OpenForm<\/b>-Methoden in die entsprechenden Prozeduren eintragen. Auch das L&ouml;schen des aktuell markierten Datensatzes k&ouml;nnten wir auf diese Weise noch erg&auml;nzen. Gegebenenfalls holen wir dies in einer sp&auml;teren Ausgabe von Access im Unternehmen nach.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>amvDetailformBuilder.accda<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/28499C30-D600-4BCA-8F81-F4208BF86B0B\/aiu_1528.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Manche Aufgaben im Alltag eines Access-Entwicklers wiederholen sich immer wieder und unterscheiden sich nur durch Kleinigkeiten. Zum Beispiel sehen Detailformulare, &Uuml;bersichtsformulare oder auch Formulare zum Verwalten von Daten in Haupt- und Unterformular immer gleich aus &#8211; wenn auch f&uuml;r andere Daten.  Im Beitrag &#8222;Tabellendaten mit &Uuml;bersicht und Details anzeigen&#8220; (www.access-im-unternehmen.de\/1488) haben wir grunds&auml;tzlich gezeigt, wie wir ein Hauptformular mit einer &Uuml;bersicht in einem Unterformular anlegen und programmieren k&ouml;nnen. Der Beitrag &#8222;Detailformular per Mausklick erstellen&#8220; (www.access-im-unternehmen.de\/1490) wiederum liefert ein Beispiel daf&uuml;r, wie wir ein einfaches Detailformular schnell definieren und per Mausklick erstellen k&ouml;nnen. Im vorliegenden Beitrag wollen wir beides kombinieren &#8211; also ein &Uuml;bersichtsformular mit Haupt- und Unterformular in einem Konfigurationsformular einrichten und dann automatisch erstellen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662024,66062024,44000027],"tags":[],"class_list":["post-55001528","post","type-post","status-publish","format-standard","hentry","category-662024","category-66062024","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>&Uuml;bersichtsformular per Mausklick - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"&Uuml;bersichtsformular per Mausklick\" \/>\n<meta property=\"og:description\" content=\"Manche Aufgaben im Alltag eines Access-Entwicklers wiederholen sich immer wieder und unterscheiden sich nur durch Kleinigkeiten. Zum Beispiel sehen Detailformulare, &Uuml;bersichtsformulare oder auch Formulare zum Verwalten von Daten in Haupt- und Unterformular immer gleich aus - wenn auch f&uuml;r andere Daten. Im Beitrag &quot;Tabellendaten mit &Uuml;bersicht und Details anzeigen&quot; (www.access-im-unternehmen.de\/1488) haben wir grunds&auml;tzlich gezeigt, wie wir ein Hauptformular mit einer &Uuml;bersicht in einem Unterformular anlegen und programmieren k&ouml;nnen. Der Beitrag &quot;Detailformular per Mausklick erstellen&quot; (www.access-im-unternehmen.de\/1490) wiederum liefert ein Beispiel daf&uuml;r, wie wir ein einfaches Detailformular schnell definieren und per Mausklick erstellen k&ouml;nnen. Im vorliegenden Beitrag wollen wir beides kombinieren - also ein &Uuml;bersichtsformular mit Haupt- und Unterformular in einem Konfigurationsformular einrichten und dann automatisch erstellen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2024-11-06T18:58:24+00:00\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"37\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"&Uuml;bersichtsformular per Mausklick\",\"datePublished\":\"2024-11-06T18:58:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/\"},\"wordCount\":5285,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/99965432c3954f3790bdbc69c88ccfb1\",\"articleSection\":[\"2024\",\"6\\\/2024\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/\",\"name\":\"&Uuml;bersichtsformular per Mausklick - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/99965432c3954f3790bdbc69c88ccfb1\",\"datePublished\":\"2024-11-06T18:58:24+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/99965432c3954f3790bdbc69c88ccfb1\",\"contentUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/99965432c3954f3790bdbc69c88ccfb1\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Uebersichtsformular_per_Mausklick\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"&Uuml;bersichtsformular per Mausklick\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"&Uuml;bersichtsformular per Mausklick - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/","og_locale":"de_DE","og_type":"article","og_title":"&Uuml;bersichtsformular per Mausklick","og_description":"Manche Aufgaben im Alltag eines Access-Entwicklers wiederholen sich immer wieder und unterscheiden sich nur durch Kleinigkeiten. Zum Beispiel sehen Detailformulare, &Uuml;bersichtsformulare oder auch Formulare zum Verwalten von Daten in Haupt- und Unterformular immer gleich aus - wenn auch f&uuml;r andere Daten. Im Beitrag \"Tabellendaten mit &Uuml;bersicht und Details anzeigen\" (www.access-im-unternehmen.de\/1488) haben wir grunds&auml;tzlich gezeigt, wie wir ein Hauptformular mit einer &Uuml;bersicht in einem Unterformular anlegen und programmieren k&ouml;nnen. Der Beitrag \"Detailformular per Mausklick erstellen\" (www.access-im-unternehmen.de\/1490) wiederum liefert ein Beispiel daf&uuml;r, wie wir ein einfaches Detailformular schnell definieren und per Mausklick erstellen k&ouml;nnen. Im vorliegenden Beitrag wollen wir beides kombinieren - also ein &Uuml;bersichtsformular mit Haupt- und Unterformular in einem Konfigurationsformular einrichten und dann automatisch erstellen.","og_url":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/","og_site_name":"Access im Unternehmen","article_published_time":"2024-11-06T18:58:24+00:00","author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"37\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"&Uuml;bersichtsformular per Mausklick","datePublished":"2024-11-06T18:58:24+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/"},"wordCount":5285,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/99965432c3954f3790bdbc69c88ccfb1","articleSection":["2024","6\/2024","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/","url":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/","name":"&Uuml;bersichtsformular per Mausklick - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/99965432c3954f3790bdbc69c88ccfb1","datePublished":"2024-11-06T18:58:24+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#primaryimage","url":"http:\/\/vg02.met.vgwort.de\/na\/99965432c3954f3790bdbc69c88ccfb1","contentUrl":"http:\/\/vg02.met.vgwort.de\/na\/99965432c3954f3790bdbc69c88ccfb1"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Uebersichtsformular_per_Mausklick\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"&Uuml;bersichtsformular per Mausklick"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001528","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001528"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001528\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}