{"id":55001078,"date":"2017-04-01T00:00:00","date_gmt":"2020-05-14T13:41:45","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1078"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Verknuepfte_Daten_suchen","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/","title":{"rendered":"Verkn&uuml;pfte Daten suchen"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg09.met.vgwort.de\/na\/0727a06d35104f15b27567571fc8b688\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Wenn Sie eine Anwendung programmieren, die ihre Daten nur &uuml;ber die Benutzeroberfl&auml;che &auml;ndert, sehen Sie die &auml;nderungen ja immer direkt in den entsprechenden Formularen und Steuerelementen. Aber manchmal erstellen, &auml;ndern oder l&ouml;schen Sie Daten auch per Mausklick auf eine Schaltfl&auml;che und die dahinter liegende Prozedur erledigt den Rest. Gerade in der Entwicklungsphase m&ouml;chen Sie dann nat&uuml;rlich schnell sehen, ob die Daten auch wirklich wie gew&uuml;nscht editiert wurden. Dazu qu&auml;lt man sich dann meist durch die einzelnen Tabellen und pr&uuml;ft das Ergebnis. Wenn sich die Daten &uuml;ber verkn&uuml;pfte Tabellen erstrecken, wird dies erst recht anstrengend. Aber nicht mit der L&ouml;sung, die wir in diesem Beitrag vorstellen!<\/b><\/p>\n<h2>Beispieldatenbank<\/h2>\n<p>Als Beispiel dient uns die oft verwendete S&uuml;dsturm-Datenbank. Sie hat einige verkn&uuml;pfte Tabellen, mit denen wir das eingangs erw&auml;hnte Problem des schwierigen Nachvollziehens ge&auml;nderter oder neuer Daten leicht nachstellen k&ouml;nnen. Im ersten Beispiel wollen wir uns die verkn&uuml;pften Tabellen in der Reihenfolge <b>tblKunden<\/b>, <b>tblBestellungen<\/b>, <b>tblBestelldetails<\/b>, <b>tblArtikel <\/b>ansehen (s. Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_001.png\" alt=\"Tabellen der Datenbank S&uuml;dsturm\" width=\"649,559\" height=\"204,9873\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Tabellen der Datenbank S&uuml;dsturm<\/span><\/b><\/p>\n<h2>Die fertige L&ouml;sung<\/h2>\n<p>Am Ende dieses Artikels sollen Sie eine L&ouml;sung haben, mit der Sie verkn&uuml;pfte Tabellen mit einer Tiefe von vier Hierarchieebenen ausw&auml;hlen und analysieren k&ouml;nnen.<\/p>\n<p>Dazu erhalten Sie ein Formular, das vier Unterformulare enth&auml;lt, von denen jedes die Daten einer von bis zu vier Tabellen anzeigt (s. Bild 2). Das oberste Unterformular soll beispielsweise die Daten der Tabelle <b>tblKunden <\/b>anzeigen. Darunter finden Sie dann die Daten der Tabelle <b>tblBestellungen<\/b>. Wenn der Benutzer nun auf einen der Datens&auml;tze der Tabelle <b>tblKunden <\/b>klickt, soll das Unterformular mit den Daten der Tabelle <b>tblBestellungen <\/b>nur die Datens&auml;tze anzeigen, die zum aktuellen Kunden geh&ouml;ren.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_007.png\" alt=\"Die fertige L&ouml;sung\" width=\"649,559\" height=\"874,684\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Die fertige L&ouml;sung<\/span><\/b><\/p>\n<p>Darunter geht es weiter: Das dritte Unterformular zeigt alle Daten der Tabelle <b>tblBestelldetails <\/b>an, die mit dem Datensatz des zweiten Unterformulars mit den Bestellungen verkn&uuml;pft ist. Das vierte Unterformular liefert schlie&szlig;lich noch den dem Bestelldetail zugeordneten Datensatz der Tabelle <b>tblArtikel<\/b>.<\/p>\n<p>Der Clou bei der L&ouml;sung ist, dass Sie die Tabellen, deren Daten in den Unterformularen angezeigt werden, nicht fest in das Formular programmieren m&uuml;ssen, sondern dass es f&uuml;r alle beteiligten Tabellen, Prim&auml;rschl&uuml;sselfelder und Fremdschl&uuml;sselfelder Kombinationsfelder zur Auswahl gibt. Auf diese Weise k&ouml;nnen Sie mit dem Formular nicht nur verschiedene Konfigurationen von verkn&uuml;pften Tabellen untersuchen, sondern diese auch noch zur Laufzeit neu einstellen, um eine andere Konfiguration zu begutachten.<\/p>\n<p>Nun w&auml;re es nat&uuml;rlich aufwendig, immer wieder alle Eigenschaften einer Konfiguration neu einzugeben, wenn man diese einmal wechseln will oder das Formular gar in einer anderen Datenbank als der aktuellen einsetzen m&ouml;chte. Deshalb k&ouml;nnen Sie verschiedene Konfigurationen speichern und diese immer wieder neu abrufen. Wenn Sie das Formular erstmalig &ouml;ffnen, fragt dieses Sie gleich nach dem Namen der ersten anzulegenden Konfiguration. Diese wird dann nach dem &ouml;ffnen des Formulars oben im Kombinationsfeld angezeigt.<\/p>\n<p>Sie k&ouml;nnen nun mit den je nach Ebene zwei bis drei Kombinationsfeldern die Tabelle ausw&auml;hlen, die das entsprechende Unterformular anzeigen soll. Danach legen Sie zun&auml;chst f&uuml;r die obere Tabelle das Prim&auml;rschl&uuml;sselfeld fest.<\/p>\n<p>Damit das Formular wei&szlig;, welche Datens&auml;tze des zweiten Unterformulars zu dem im ersten Unterformular angezeigten Datensatz geh&ouml;ren, geben Sie f&uuml;r das zweite Unterformular das Fremdschl&uuml;sselfeld an, &uuml;ber das es mit den Datens&auml;tzen der &uuml;bergeordneten Tabelle verkn&uuml;pft ist.<\/p>\n<p>Auf die gleiche Weise verfahren Sie mit den folgenden Kombinationsfeldern f&uuml;r Prim&auml;r- und Fremdschl&uuml;sselfelder, bis Sie f&uuml;r das vierte Unterformular nur noch das Fremdschl&uuml;sselfeld angeben m&uuml;ssen.<\/p>\n<p>Wenn Sie bereits mehrere Konfigurationen angelegt haben, k&ouml;nnen Sie diese &uuml;ber das Kombinationsfeld mit der Beschriftung <b>Konfiguration<\/b> wechseln. Mit der <b>L&ouml;schen<\/b>-Schaltfl&auml;che entfernen Sie die aktuell ausgew&auml;hlte Konfiguration aus der Datenbank.<\/p>\n<h2>Auf geht&#8220;s!<\/h2>\n<p>Auf den folgenden Seiten werden wir uns zun&auml;chst eine einfache, statische Variante dieser L&ouml;sung ansehen, um die Grundlagen der Vorgehensweise zu verdeutlichen. Im Anschluss schauen wir uns dann an, wie das Formular zur flexiblen Anzeige der Daten verkn&uuml;pfter Tabellen programmiert wird.<\/p>\n<h2>Erstellen des Hauptformulars<\/h2>\n<p>Das Hauptformular dient zun&auml;chst nur als Container f&uuml;r die einelnen Unterformulare. Erstellen Sie also ein leeres Hauptformular und speichern Sie es unter dem Namen <b>frmVerknuepfteTabellen<\/b>.<\/p>\n<p>Gleich f&uuml;gen wir die einzelnen Unterformulare und die Funktion in Form von VBA-Code hinzu.<\/p>\n<h2>Erstellen der Unterformulare<\/h2>\n<p>Die Unterformulare sind prinzipiell alle gleich aufgebaut. Wir schauen uns dies am Beispiel des Formulars <b>sfmKunden<\/b> an, welches die Datens&auml;tze der Tabelle <b>tblKunden <\/b>abbilden soll. Dazu legen Sie ein neues, leeres Formular an und stellen als Datenherkunft die Tabelle <b>tblKunden <\/b>ein. Gegebenenfalls k&ouml;nnen Sie auch eine Abfrage erstellen, welche beispielsweise die Kunden nach dem Feld <b>Firma <\/b>sortiert. Danach f&uuml;gen Sie wie in Bild 3 alle Felder der Datenherkunft zum Detailbereich der Entwurfsansicht der Tabelle hinzu. Stellen Sie die Eigenschaft <b>Standardansicht<\/b> auf <b>Datenblatt <\/b>ein. Speichern Sie das Formular dann etwa unter dem Namen <b>sfmKunden<\/b> und schlie&szlig;en Sie es.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_002.png\" alt=\"Entwurf des Unterformulars f&uuml;r die Anzeige der Kundendatens&auml;tze\" width=\"424,7115\" height=\"431,1606\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Entwurf des Unterformulars f&uuml;r die Anzeige der Kundendatens&auml;tze<\/span><\/b><\/p>\n<h2>Unterformular in Hauptformular<\/h2>\n<p>Dann &ouml;ffnen Sie das Hauptformular in der Entwurfsansicht und ziehen das Unterformular <b>sfmKunden <\/b>aus dem Navigationsbereich in den Detailbereich des Hauptformulars. Das Ergebnis sieht etwa wie in Bild 4 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_003.png\" alt=\"Das Hauptformular mit einem ersten Unterformular\" width=\"549,6265\" height=\"353,2627\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Das Hauptformular mit einem ersten Unterformular<\/span><\/b><\/p>\n<h2>Weitere Unterformulare<\/h2>\n<p>Auf die gleiche Weise gehen Sie mit den Unterformularen f&uuml;r die Tabellen <b>tblBestellungen<\/b>, <b>tblBestelldetails <\/b>und <b>tblArtikel <\/b>vor: Legen Sie diese an, f&uuml;gen Sie Datenherkunft und Felder hinzu und ziehen Sie diese dann untereinander in das Formular <b>frmVerknuepfteTabellen<\/b>. Mit allen vier Unterformularen sieht das Formular dann in der Datenblattansicht wie in Bild 5 aus. Die vier Unterformulare zeigen hier jeweils alle Datens&auml;tze ihrer Datenquelle an.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_004.png\" alt=\"Das Hauptformular mit allen vier Unterformularen\" width=\"549,6265\" height=\"707,3625\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Das Hauptformular mit allen vier Unterformularen<\/span><\/b><\/p>\n<p>Das ist nat&uuml;rlich schon praktischer als wenn man immer alle Tabellen einzeln &ouml;ffnen muss. Allerdings wollen wir noch einen entscheidenden Schritt weitergehen: Wenn der Benutzer nun auf einen der Eintr&auml;ge der Tabelle <b>tblKunden <\/b>im Unterformular <b>sfmKunden <\/b>klickt, soll das n&auml;chste Unterformular nur noch die Datens&auml;tze der Tabelle <b>tblBestellungen <\/b>anzeigen, die &uuml;ber das Feld <b>KundeID<\/b> mit dem ausgew&auml;hlten Kundendatensatz verkn&uuml;pft sind.<\/p>\n<h2>Funktion hinzuf&uuml;gen<\/h2>\n<p>Dazu m&uuml;ssen wir ein paar Zeilen VBA-Code hinzuf&uuml;gen. Wir machen das erstmal auf die einfachste Weise. Das Ereignis, das wir ben&ouml;tigen, hei&szlig;t <b>Beim Anzeigen <\/b>und wird immer dann ausgel&ouml;st, wenn ein neuer Datensatz in einem Formular den Fokus erh&auml;lt.<\/p>\n<p>Diesem weisen wir nun eine Ereignisprozedur zu, welche die Datens&auml;tze des untergeordneten Unterformulars so filtert, dass es nur noch die mit dem aktuell ausgew&auml;hlten Datensatz verkn&uuml;pften Datens&auml;tze anzeigt.<\/p>\n<p>Der Plan ist also, eine Prozedur wie die folgende auszul&ouml;sen, die eine Referenz auf das darunter angeordnete Formular speichert und f&uuml;r diese die <b>Filter<\/b>-Eigenschaft mit einem entsprechenden Filter-Ausdruck belegt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Current()\r\n     <span style=\"color:blue;\">Dim <\/span>frm<span style=\"color:blue;\"> As <\/span>Form\r\n     <span style=\"color:blue;\">Set<\/span> frm = Me.Parent!sfmBestellungen.Form\r\n     frm.Filter = \"KundeID = \" & Me!KundeID\r\n     frm.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wenn wir das Formular nun &ouml;ffnen, erhalten wir allerdings  die Fehlermeldung aus Bild 6. Das ist etwas &uuml;berraschend: Wir haben das Unterformular doch korrekt referenziert Nach dem Akzeptieren des Fehlers mit Beenden schauen wir uns an, ob wir das Unterformular &uuml;ber den Direktbereich referenzieren k&ouml;nnen. Dazu setzen wir den folgenden Befehl ab:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_005.png\" alt=\"Fehlermeldung beim &ouml;ffnen des Formulars\" width=\"424,7115\" height=\"241,078\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Fehlermeldung beim &ouml;ffnen des Formulars<\/span><\/b><\/p>\n<pre>  Forms!frmVerknuepfteTabellen! sfmBestellungen.Form.Name\r\n   sfmBestellungen<\/pre>\n<p>Vom Direktfenster aus k&ouml;nnen wir also auf das Unterformular zugreifen. Also scheint es eine Frage des Timings zu sein. Das Ereignis <b>Beim Anzeigen <\/b>wird ja nicht nur dann ausgel&ouml;st, wenn der Benutzer den Datensatz wechselt, sondern auch direkt nach dem &ouml;ffnen des Formulars. Offensichtlich ist das Unterformular <b>sfmBestellungen<\/b> also noch nicht geladen, wenn das Ereignis <b>Beim Anzeigen <\/b>des Unterformulars <b>sfmKunden <\/b>ausgel&ouml;st wird.<\/p>\n<p>Wie k&ouml;nnen wir dieses Verhalten beeinflussen In welcher Reihenfolge werden die Unterformulare &uuml;berhaupt geladen, wenn sich mehrere Unterformulare im gleichen Hauptformular befinden Dies wollen wir experimentell pr&uuml;fen, indem wir ein neues, leeres Hauptformular erstellen und diesmal zuerst das Unterformular <b>sfmBestellungen <\/b>in den Entwurf des Formulars ziehen und erst dann <b>sfmKunden<\/b>.<\/p>\n<p>Den Code brauchen Sie nicht erneut einzugeben, da er sich ja in dem Unterformular <b>sfmKunden <\/b>befindet. Wenn Sie das Formular nun &ouml;ffnen, erscheint keine Fehlermeldung und das Unterformular <b>sfmBestellungen <\/b>zeigt nur die Bestellungen an, die zum aktuell im Unterformular <b>sfmKunden <\/b>ausgew&auml;hlten Datensatz geh&ouml;ren.<\/p>\n<h2>Verfeinerung des Codes<\/h2>\n<p>Wir wollen uns allerdings nicht auf solch willk&uuml;rliche Faktoren wie die Reihenfolge des Hinzuf&uuml;gens von Steuerelementen verlassen. Au&szlig;erdem ist es ja auch kein erkl&auml;rtes Ziel, gleich beim Anzeigen des Formulars alle Daten gleich auf den im ersten Formular ausgew&auml;hlten Datensatz zu konzentrieren.<\/p>\n<p>Schlie&szlig;lich ist es ohnehin kein guter Programmierstil, ein Unterformular von einem anderen Unterformular &uuml;ber den Umweg des Hauptformulars zu referenzieren. Und wenn wir die hier verwendete Prozedur auch f&uuml;r die verkn&uuml;pften Tabellen in den &uuml;brigen Unterformularen nutzen wollen, verteilt sich der Code schnell &uuml;ber mehrere Formulare und wird un&uuml;bersichtlich.<\/p>\n<p>Daher wollen wir s&auml;mtlichen Code gleich ins Hauptformular &uuml;berf&uuml;hren, von wo wir die Unterformulare referenzieren und die Ereignisprozeduren f&uuml;r das Ereignis <b>Beim Anzeigen <\/b>der verschiedenen Unterformulare implementieren wollen (s. Listing 1). Also l&ouml;schen wir zun&auml;chst die Ereignisprozedur <b>Form_Current <\/b>aus dem Unterformular <b>sfmKunden<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>WithEvents frm_sfmBestellungen<span style=\"color:blue;\"> As <\/span>Form\r\n<span style=\"color:blue;\">Dim <\/span>WithEvents frm_sfmKunden<span style=\"color:blue;\"> As <\/span>Form\r\n<span style=\"color:blue;\">Dim <\/span>WithEvents frm_sfmBestelldetails<span style=\"color:blue;\"> As <\/span>Form\r\n<span style=\"color:blue;\">Dim <\/span>frm_sfmArtikel<span style=\"color:blue;\"> As <\/span>Form\r\n<span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Set<\/span> frm_sfmKunden = Me!sfmKunden.Form\r\n     frm_sfmKunden.OnCurrent = \"[Event Procedure]\"\r\n     <span style=\"color:blue;\">Set<\/span> frm_sfmBestellungen = Me!sfmBestellungen.Form\r\n     frm_sfmBestellungen.OnCurrent = \"[Event Procedure]\"\r\n     <span style=\"color:blue;\">Set<\/span> frm_sfmBestelldetails = Me!sfmBestelldetails.Form\r\n     frm_sfmBestelldetails.OnCurrent = \"[Event Procedure]\"\r\n     <span style=\"color:blue;\">Set<\/span> frm_sfmArtikel = Me!sfmArtikel.Form\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>frm_sfmKunden_Current()\r\n     <span style=\"color:blue;\">With<\/span> frm_sfmBestellungen\r\n         .Filter = \"KundeID = \" & frm_sfmKunden.KundeID\r\n         .FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>frm_sfmBestellungen_Current()\r\n     <span style=\"color:blue;\">With<\/span> frm_sfmBestelldetails\r\n         .Filter = \"BestellungID = \" & frm_sfmBestellungen.BestellungID\r\n         .FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>frm_sfmBestelldetails_Current()\r\n     <span style=\"color:blue;\">With<\/span> frm_sfmArtikel\r\n         .Filter = \"ArtikelID = \" & frm_sfmBestelldetails.ArtikelID\r\n         .FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Code, um die Unterformulare nacheinander zu filtern<\/span><\/b><\/p>\n<p>Danach legen Sie eine Variable f&uuml;r das Unterformular <b>sfmKunden <\/b>im Klassenmodul des Hauptformulars <b>frmVerknuepfteTabellen <\/b>an:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>WithEvents frm_sfmKunden<span style=\"color:blue;\"> As <\/span>Form<\/pre>\n<p>Damit diese gef&uuml;llt wird, implementieren wir das Ereignis <b>Beim Laden <\/b>des Hauptformulars wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Set<\/span> frm_sfmKunden = Me!sfmKunden.Form\r\n     frm_sfmKunden.OnCurrent = \"[Event Procedure]\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Nun m&uuml;ssen wir nur noch das Ereignis <b>Beim Anzeigen <\/b>des Unterformulars implementieren. Dazu w&auml;hlen Sie im Klassenmodul des Hauptformulars aus dem linken Kombinationsfeld den Eintrag <b>frm_sfmKunden <\/b>aus und aus dem rechten Kombinationsfeld den Eintrag <b>OnCurrent<\/b>. Dies legt die neue Ereignisprozedur an, die Sie wie folgt erg&auml;nzen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>frm_sfmKunden_Current()\r\n     <span style=\"color:blue;\">With<\/span> frm_sfmBestellungen\r\n         .Filter = \"KundeID = \" & frm_sfmKunden.KundeID\r\n         .FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das war es schon &#8211; wir haben den kompletten Code im Hauptformular und k&ouml;nnen so steuern, dass das Unterformular <b>sfmBestellungen <\/b>nur die Bestellungen anzeigt, die dem im Unterformular <b>sfmKunden <\/b>ausgew&auml;hlten Datensatz zugeordnet sind.<\/p>\n<p>Eine Voraussetzung ist daf&uuml;r zu erf&uuml;llen, damit Sie die Ereignisprozeduren der untergeordneten Formulare implementieren k&ouml;nnen: Diese m&uuml;ssen jeweils ein eigenes Klassenmodul enthalten.<\/p>\n<p>Dies stellen Sie am schnellsten &uuml;ber den Wert <b>Ja <\/b>f&uuml;r die Eigenschaft <b>Enth&auml;lt Modul <\/b>des jeweiligen Formulars ein.<\/p>\n<h2>Verkn&uuml;pfung aller Unterformulare<\/h2>\n<p><!--30percent--><\/p>\n<p>Damit alle Unterformulare jeweils die Daten des folgenden Unterformulars filtern, ben&ouml;tigen wir f&uuml;r jedes Unterformular die bereits vorgestellten Code-Zeilen.<\/p>\n<p>Wir deklarieren also f&uuml;r alle vier Unterformulare jeweils eine <b>Form<\/b>-Variable, von denen allerdings nur die ersten drei mit dem Schl&uuml;sselwort <b>WithEvents <\/b>ausgestattet werden m&uuml;ssen &#8211; das letzte Unterformular mit den Eintr&auml;gen der Tabelle <b>tblArtikel <\/b>soll ja beim Anklicken keine weiteren Datens&auml;tze mehr filtern.<\/p>\n<p>Die Prozedur <b>Form_Load <\/b>des Hauptformulars setzt dann die Verweise f&uuml;r die vier <b>Form<\/b>-Variablen auf die entsprechenden <b>Form<\/b>-Elemente in den Unterformular-Steuerelementen. F&uuml;r die ersten drei legt sie au&szlig;erdem fest, dass in diesem Klassenmodul auch nach Implementierungen des Ereignisses <b>OnCurrent <\/b>gesucht werden soll.<\/p>\n<p>Schlie&szlig;lich fehlen noch die Implementierungen der Ereignisse, die jeweils &auml;hnlich aufgebaut sind, aber sich auf die verschiedenen Unterformulare beziehen. <b>frm_sfmKunden_Current <\/b>stellt den Filter von <b>frm_sfmBestellungen <\/b>auf den aktuellen Kunden ein, <b>frm_sfmBestellungen_Current <\/b>den Filter von <b>frm_sfmBestelldetails <\/b>und <b>frm_sfmBestelldetails_Current <\/b>den von <b>frm_sfmArtikel<\/b>.<\/p>\n<h2>Benennung der Form-Variablen<\/h2>\n<p>Warum haben wir die Formular-Variablen nicht einfach genauso benannt wie die Unterformulare Wir haben es zun&auml;chst ausprobiert, aber Access kommt anscheinend nicht klar, wenn es einerseits ein Unterformular-Steuerelement und andererseits eine mit <b>WithEvents <\/b>deklarierte Variable mit dem gleichen Namen gibt.<\/p>\n<p>Wir haben bei diesem Versuch reproduzierbar einen Absturz von Access verursacht, als wir versucht haben, das Ereignis <b>Beim Anzeigen <\/b>f&uuml;r das Element <b>sfm_Bestellungen <\/b>anzulegen. Aus diesem Grund haben wir allen <b>Form<\/b>-Variablen noch das Pr&auml;fix <b>frm_ <\/b>vorangestellt.<\/p>\n<h2>Test des Formulars<\/h2>\n<p>Nach dem Wechsel in die Formularansicht funktioniert das Formular wie gew&uuml;nscht. Wenn Sie einen der Eintr&auml;ge des obersten Unterformulars mit den Daten der Tabelle <b>tblKunden <\/b>anklicken, zeigt das n&auml;chste Unterformular die dazu geh&ouml;rende Bestellung, das n&auml;chste die zur Bestellung geh&ouml;renden Bestelldetails und das letzte den Artikel zum jeweiligen Bestelldetail an (s. Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_006.png\" alt=\"Gefilterte Unterformulare\" width=\"549,6265\" height=\"715,213\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Gefilterte Unterformulare<\/span><\/b><\/p>\n<h2>Flexible Gestaltung<\/h2>\n<p>Nun ist es allerdings etwas umst&auml;ndlich, f&uuml;r jede neue Konstellation ein neues dieser Formulare samt Unterformularen erstellen zu m&uuml;ssen. Also machen wir das Formular etwas flexibler, indem wir dem Benutzer die Auswahl der Tabellen und der Verkn&uuml;pfungsfelder erm&ouml;glichen.<\/p>\n<p>Das ist allerdings etwas komplizierter als nur ein paar Kombinationsfelder zur Auswahl der beteiligten Tabellen und Felder hinzuzuf&uuml;gen und die dort gew&auml;hlten Eintr&auml;ge dann zur Laufzeit in den Code zu integrieren. Schlie&szlig;lich mussten wir ja jedes Unterformular separat erstellen und haben dort auch die Datenherkunft festgelegt und die verschiedenen Felder zum Detailbereich hinzugef&uuml;gt. Auch dies m&uuml;ssen wir ber&uuml;cksichtigen, wenn wir vier Unterformulare dynamisch mit den Daten verschiedener Tabellen f&uuml;llen wollen.<\/p>\n<p>Wir m&uuml;ssen also statt einiger per Drag and Drop aus der Feldliste in den Entwurf gezogener Felder einige ungebundene Textfelder anlegen, die wir erst zur Laufzeit mit den Feldern der angegebenen Tabelle oder Abfrage f&uuml;llen.<\/p>\n<p>Au&szlig;erdem sollten wir uns &uuml;berlegen, wie aufw&auml;ndig auch das Ausw&auml;hlen der Tabellen und Verkn&uuml;pfungsfelder noch ist, wenn der Benutzer diesen Vorgang mehrfach wiederholen muss. Es ist ja anzunehmen, dass der Benutzer l&auml;nger an einem bestimmten Algorithmus zum &auml;ndern von Daten arbeitet und das Formular mit seiner aktuellen Konfiguration auch h&auml;ufiger ben&ouml;tigt &#8211; vielleicht auch noch sp&auml;ter, wenn Fehler auftauchen oder &auml;nderungen vorzunehmen sind. F&uuml;r diesen Fall sorgen wir vor und legen eine Tabelle an, in welcher der Benutzer die Konfiguration speichern kann.<\/p>\n<h2>Flexibles Unterformular<\/h2>\n<p>Wir beginnen mit dem flexiblen Unterformular. Die Verwendung eines flexiblen Unterformulars hat gegen&uuml;ber den mit einer festen Datenherkunft versehenen Unterformularen den Vorteil, dass wir nur eines davon ben&ouml;tigen, das wir mehrfach in das Hauptformular einbetten und mit verschiedenen Daten f&uuml;ttern (s. Bild 8).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_008.png\" alt=\"Flexibles Unterformular\" width=\"599,593\" height=\"425,0403\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Flexibles Unterformular<\/span><\/b><\/p>\n<p>Dieses Formular k&ouml;nnen wir nat&uuml;rlich nicht mit einer festen Datenherkunft und entsprechend gebundenen Feldern versehen, sondern wir lassen die Eigenschaft <b>Datenherkunft <\/b>leer und f&uuml;gen einfach zehn Textfelder hinzu, denen wir die Namen <b>txt01 <\/b>bis <b>txt10 <\/b>geben. Die dabei automatisch hinzugef&uuml;gten Bezeichnungsfelder benennen wir mit den Namen <b>lbl01 <\/b>bis <b>lbl10<\/b>. Diese Benennung ist notwendig, weil wir diese Steuerelemente sp&auml;ter mit den Namen der Felder f&uuml;llen wollen. Die Bezeichnungsfelder werden zwar in der Datenblattansicht, die wir mit der Eigenschaft <b>Standardansicht <\/b>festlegen, nicht angezeigt, aber deren Beschriftungen werden f&uuml;r die Spalten&uuml;berschriften herangezogen. Ganz wichtig ist es, dass Sie f&uuml;r dieses Formular die Eigenschaft <b>Enth&auml;lt Modul <\/b>auf den Wert <b>Ja <\/b>einstellen, da wir sonst, wie weiter oben bereits beschrieben, keine Ereignisse dieses Formulars im Klassenmodul des &uuml;bergeordneten Formulars implemenieren k&ouml;nnen (genau genommen k&ouml;nnen wir diese nat&uuml;rlich implementieren, aber sie werden dann niemals ausgel&ouml;st).<\/p>\n<p>Das waren schon alle Schritte, die f&uuml;r die Erstellung des Unterformulars <b>sfmTabellen <\/b>n&ouml;tig sind. Kein Wunder: Die Ereignisprozeduren f&uuml;r dieses Formular landen ja auch alle im &uuml;bergeordneten Formular.<\/p>\n<h2>Konfigurationstabelle<\/h2>\n<p>Bevor wir zur Gestaltung und Programmierung des Hauptformulars kommen, ben&ouml;tigen wir noch eine Tabelle namens <b>tblKonfigurationen<\/b>. Wie eingangs erw&auml;hnt, wollen wir ja die einzelnen Konfigurationen speichern und wieder ausw&auml;hlen k&ouml;nnen. F&uuml;r das Speichern der anfallenden Daten nutzen wir unter Access nat&uuml;rlich eine Tabelle.<\/p>\n<p>Diese sieht in der Entwurfsansicht wie in Bild 9 aus und enth&auml;lt Felder zum Speichern aller beim Definieren einer Konfiguration anfallenden Daten &#8211; die Tabellen f&uuml;r das erste bis vierte Unterformular, die Prim&auml;rschl&uuml;sselfelder f&uuml;r die ersten drei Unterformulare und die Fremdschl&uuml;sselfelder f&uuml;r die unteren drei Unterformulare.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_010.png\" alt=\"Tabelle zum Speichern der Konfigurationen\" width=\"649,559\" height=\"552,6525\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Tabelle zum Speichern der Konfigurationen<\/span><\/b><\/p>\n<h2>Dynamisches Hauptformular erstellen<\/h2>\n<p>Das Hauptformular hei&szlig;t <b>frmTabellen <\/b>und ist an die soeben vorgestellte Tabelle <b>tblKonfigurationen <\/b>gebunden. Der obere Bereich dieses Formulars sieht im Entwurf so wie in Bild 10 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_009.png\" alt=\"Entwurf des oberen Bereichs des Formulars frmTabellen\" width=\"649,559\" height=\"320,3573\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Entwurf des oberen Bereichs des Formulars frmTabellen<\/span><\/b><\/p>\n<p>Beginnen wir mit den Datensatzherk&uuml;nften f&uuml;r die Kombinationsfelder. Die vier Kombinationsfelder zur Auswahl der im jeweiligen Unterformular anzuzeigenden Tabelle hei&szlig;en <b>cboTabelle1 <\/b>bis <b>cboTabelle4<\/b> und enthalten alle die gleiche Abfrage als Datensatzherkunft. Diese zeigt Bild 11 in der Entwurfsansicht. Diese Abfrage verwendet die Systemtabelle <b>MSysObjects <\/b>als Datenherkunft, die wiederum alle Access-Objekte enth&auml;lt. Mit dem Kriterium f&uuml;r das erste Feld klammern wir System- und versteckte Tabellen aus dem Abfrageergebnis aus, mit dem Kriterium f&uuml;r das Feld <b>Type <\/b>lassen wir nur Tabellen verschiedener Arten sowie Abfragen zu. Diese Abfrage legen Sie als Datensatzherkunft f&uuml;r die vier Kombinationsfelder <b>cboTabelle1 <\/b>bis <b>cboTabelle4 <\/b>an.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_02\/pic_1078_011.png\" alt=\"Datensatzherkunft der Kombinationsfelder zur Auswahl der in den Unterformularen anzuzeigenden Tabellen\" width=\"549,6265\" height=\"348,8215\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Datensatzherkunft der Kombinationsfelder zur Auswahl der in den Unterformularen anzuzeigenden Tabellen<\/span><\/b><\/p>\n<p>Die Kombinationsfelder <b>cboPrimaerschluessel1 <\/b>bis <b>cboPrimaerschluessel3 <\/b>und <b>cboFremdschluessel2 <\/b>bis <b>cboFremdschluessel4 <\/b>sollen die in den mit den Kombinationsfeldern <b>cboTabellen1 <\/b>bis <b>cboTabellen4 <\/b>ausgew&auml;hlten Tabellen enthaltenen Felder zur Auswahl anbieten. Dazu sind zwei Schritte n&ouml;tig: Erstens m&uuml;ssen wir die Eigenschaft <b>Herkunftsart <\/b>f&uuml;r diese Kombinationsfelder auf den Wert <b>Feldliste <\/b>einstellen. Zweitens m&uuml;ssen wir daf&uuml;r sorgen, dass nach Auswahl eines Eintrags in einem der Kombinationsfelder <b>cboTabellen1<\/b> bis <b>cboTabellen4 <\/b>die Datensatzherkunft der Kombinationsfelder mit dem Prim&auml;rschl&uuml;sselfeldern und Fremdschl&uuml;sselfeldern auf den Namen der soeben ausgew&auml;hlten Tabelle eingestellt wird.<\/p>\n<p>Dazu legen wir etwa f&uuml;r das Kombinationsfeld <b>cboTabellen1 <\/b>eine Ereignisprozedur an, die durch das Ereignis <b>Nach Aktualisierung <\/b>ausgel&ouml;st wird und wie folgt aussieht:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cboTabellen1_AfterUpdate()\r\n     Me!cboPrimaerschluessel1.RowSource = _\r\n         Nz(Me!cboTabellen1)\r\n     Me!cboPrimaerschluessel1 = Null\r\n     Me!cboPrimaerschluessel1.SetFocus\r\n     Me!cboPrimaerschluessel1.Dropdown\r\n     Me!sfmTabelle1.Form.RecordSource = _\r\n         Nz(Me!cboTabellen1)\r\n     UnterformularEinstellen Me!sfmTabelle1.Form\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese Prozedur stellt die Datensatzherkunft auf den Wert <b>Nz(Me!cboTabellen1) <\/b>ein, was dazu f&uuml;hrt, dass entweder der Name der ausgew&auml;hlten Tabelle oder, falls das Kombinationsfeld geleert wurde, kein Wert im Kombinationsfeld <b>cboPrimaer-schlues-selfeld1 <\/b>landet. Das Kombinationsfeld <b>cboPrimaerschluesselfeld1 <\/b>wird geleert, erh&auml;lt den Fokus und wird mit der Methode <b>DropDown <\/b>aufgeklappt.<\/p>\n<p>Au&szlig;erdem stellt diese Prozedur die Datenherkunft des Unterformulars <b>sfm-Tabelle1 <\/b>auf diese Tabelle ein, damit dieses die entsprechenden Daten anzeigt. Das noch fehlende Unterformular ziehen Sie einfach per Drag and Drop aus dem Navigationsbereich in den Detailbereich der Entwurfsansicht des Hauptformulars.<\/p>\n<p>Stellen Sie die Eigenschaft <b>Horizontaler Anker <\/b>auf <b>Beide <\/b>ein, damit sich die Gr&ouml;&szlig;e beim Anpassen der Gr&ouml;&szlig;e des Hauptformulars ebenfalls &auml;ndert.<\/p>\n<p>Die Prozedur <b>cboTabellen1_AfterUpdate <\/b>h&auml;lt schlie&szlig;lich noch einen Aufruf einer Prozedur namens <b>UnterformularEinstellen <\/b>bereit, der sie einen Verweis auf das Unterformular <b>sfmTabellen1 <\/b>&uuml;bermittelt. Diese Prozedur schauen wir uns weiter unten an.<\/p>\n<p>Die <b>Nach Aktualisierung<\/b>-Ereignisprozeduren der &uuml;brigen Kombinationsfelder zur Auswahl der Tabellen sehen &auml;hnlich aus. Sie enthalten allerdings an die vorhandenen, mit einer Datensatzherkunft zu f&uuml;llenden Kombinationsfelder angepasste Anweisungen &#8211; so soll die Prozedur f&uuml;r das Kombinationsfeld <b>cboTabellen2 <\/b>nat&uuml;rlich nicht nur das Prim&auml;rschl&uuml;ssel-Kombinationsfeld, sondern auch noch das Fremdschl&uuml;ssel-Kombinationsfeld f&uuml;llen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cboTabellen2_AfterUpdate()\r\n     Me!cboPrimaerschluessel2.RowSource = _\r\n         Nz(Me!cboTabellen2)\r\n     Me!cboPrimaerschluessel2 = Null\r\n     Me!cboPrimaerschluessel2.SetFocus\r\n     Me!cboPrimaerschluessel2.Dropdown\r\n     Me!cboFremdschluessel2.RowSource = Nz(Me!cboTabellen2)\r\n     Me!cboFremdschluessel2 = Null\r\n     Me!sfmTabelle2.Form.RecordSource = Nz(Me!cboTabellen2)\r\n     UnterformularEinstellen Me!sfmTabelle2.Form\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Einstellen der Unterformulare<\/h2>\n<p>Die soeben erw&auml;hnte Prozedur <b>UnterformularEinstellen<\/b> finden Sie in Listing 2. Sie sorgt daf&uuml;r, dass die Textfelder im Unterformular an die entsprechenden Felder der dynamisch hinzugef&uuml;gten Datenherkunft gebunden werden. Au&szlig;erdem m&uuml;ssen nat&uuml;rlich auch die Bezeichnungsfelder auf die entsprechenden Feldnamen eingestellt werden.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>UnterformularEinstellen(sfm<span style=\"color:blue;\"> As <\/span>Form)\r\n     <span style=\"color:blue;\">Dim <\/span>ctl<span style=\"color:blue;\"> As <\/span>Control\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>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>j<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> rst = sfm.Recordset\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         For Each fld In rst.Fields\r\n             <span style=\"color:blue;\">If <\/span>i = 10<span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit For<\/span>\r\n             i = i + 1\r\n             sfm.Controls(\"txt\" & Format(i, \"00\")).ColumnHidden = <span style=\"color:blue;\">False<\/span>\r\n             sfm.Controls(\"txt\" & Format(i, \"00\")).ControlSource = fld.Name\r\n             sfm.Controls(\"lbl\" & Format(i, \"00\")).Caption = fld.Name\r\n             <span style=\"color:blue;\">Debug.Print<\/span> fld.Name\r\n         <span style=\"color:blue;\">Next<\/span> fld\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>i &lt; 10<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>i = 0<span style=\"color:blue;\"> Then<\/span> i = 1\r\n         For j = i To 10\r\n             sfm.Controls(\"txt\" & Format(j, \"00\")).ColumnHidden = <span style=\"color:blue;\">True<\/span>\r\n             sfm.Controls(\"txt\" & Format(j, \"00\")).ControlSource = \"\"\r\n             sfm.Controls(\"lbl\" & Format(j, \"00\")).Caption = \"\"\r\n         <span style=\"color:blue;\">Next<\/span> j\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: Einstellen der Steuerelemente in den Unterformularen<\/span><\/b><\/p>\n<p>Das Formular weist zun&auml;chst das &uuml;ber die gleichnamige Eigenschaft ermittelte <b>Recordset <\/b>des mit <b>sfm <\/b>&uuml;bergebenen Unterformular-Objekts der Variaben <b>rst <\/b>zu. Dann durchl&auml;uft sie in einer <b>For Each<\/b>-Schleife alle <b>Field<\/b>-Objekte dieses Recordsets. Dabei pr&uuml;ft sie jeweils, ob die Z&auml;hlervariable <b>i <\/b>bereits den Wert <b>10 <\/b>erreicht hat. Dies ist notwendig, da das Unterformular ja nur zehn Textfelder zur Anzeige von Feldern der Datenherkunft enth&auml;lt. Solange der Wert <b>10 <\/b>noch nicht erreicht ist, stellt die Prozedur die Eigenschaft <b>ColumnHidden <\/b>des Textfeldes auf den Wert <b>False <\/b>ein, damit die zu diesem Textfeld geh&ouml;rende Spalte der Datenblattansicht eingeblendet wird.<\/p>\n<p>Anderenfalls wird die Schleife an dieser Stelle verlassen. Sollten zuvor einmal nicht alle Spalten genutzt worden sein, wurden diese n&auml;mlich ausgeblendet und m&uuml;ssen nun wieder eingeblendet werden. Die folgende Anweisung stellt die Eigenschaft <b>ControlSource<\/b>, also den Steuerelementinhalt, auf das aktuell durchlaufene Feld des Recordsets ein. Schlie&szlig;lich erh&auml;lt noch das Bezeichnungsfeld den Namen des Felds als Beschriftung. W&auml;hrend dieser drei Anweisungen greift die Prozedur &uuml;ber einen Ausdruck auf die Textfelder zu, der sich aus der Zeichenkette <b>txt <\/b>sowie der Variablen <b>i <\/b>im Format <b>&#8222;00&#8220;<\/b> zusammensetzt. Damit k&ouml;nnen leicht in einer Schleife die Steuerelemente <b>txt01 <\/b>bis <b>txt10 <\/b>und <b>lbl01 <\/b>bis <b>lbl10 <\/b>durchlaufen werden.<\/p>\n<p>Nun kann es allerdings geschehen, dass die Tabelle weniger als zehn Felder enth&auml;lt. In diesem Fall sollen die &uuml;brigen Spalten nat&uuml;rlich nicht leer bleiben, sondern diese sollen ausgeblendet werden. Daher pr&uuml;fen wir mit einer <b>If&#8230;Then<\/b>-Bedingung im Anschluss einfach, ob die Laufvariable <b>i <\/b>kleiner als <b>10 <\/b>ist, was darauf hindeutet, dass die Tabelle weniger als zehn Felder aufweist. Dann folgt eine weitere <b>For&#8230;Next<\/b>-Schleife, die diesmal die Variable <b>i <\/b>als Startwert und den Wert <b>10 <\/b>als Endwert verwendet sowie die Variable <b>j <\/b>als Laufvariable.<\/p>\n<p>Wenn die Tabelle beispielsweise sechs Felder enth&auml;lt, hat <b>i<\/b> zu diesem Zeitpunkt den Wert <b>6<\/b>, der dann aber gleich auf <b>7 <\/b>erh&ouml;ht wird, damit die Schleife den richtigen Einstiegspunkt erh&auml;lt. Dann durchl&auml;uft die Prozedur die <b>For&#8230;Next<\/b>-Schleife f&uuml;r die Werte von <b>7 <\/b>bis <b>10 <\/b>und stellt innerhalb der Schleife die Eigenschaft <b>ColumnHidden <\/b>auf den Wert <b>True<\/b>, um die Spalte auszublenden. Au&szlig;erdem wird der Steuerelementinhalt geleert und die Beschriftung des Bezeichnungsfeldes auf eine leere Zeichenkette eingestellt.<\/p>\n<p>Dieser Vorgang wird f&uuml;r alle Unterformulare durchgef&uuml;hrt.<\/p>\n<h2>Beim Laden des Hauptformulars<\/h2>\n<p>Wenn das Hauptformular geladen wird, sollen in der Ereignisprozedur <b>Form_Load <\/b>einige vorbereitende Aktionen durchgef&uuml;hrt werden (s. Listing 3). Hier gehen wir zun&auml;chst davon aus, dass das Formular ge&ouml;ffnet wird, w&auml;hrend noch keine Konfigurationen in der Tabelle <b>tblKonfigurationen <\/b>gespeichert sind. Daher wollen wir den Benutzer nach dem Namen der ersten anzulegenden Konfiguration fragen und zeigen dazu eine <b>InputBox <\/b>an, welche die gew&uuml;nschten Informationen aufnimmt. Hat der Benutzer eine Bezeichnung eingegeben, legt die Prozedur einen neuen Datensatz in der Tabelle <b>tblKonfigurationen <\/b>an und speichert dort auch bereits die angegebene Bezeichnung. Danach ermittelt die Prozedur den Wert des Feldes <b>KonfigurationID <\/b>des neuen Datensatzes und aktualisiert die Datenherkunft des Formulars, bevor es das Recordset des Hauptformulars auf den soeben neu erstellten Datensatz einstellt. Sollte der Benutzer keine neue Bezeichnung eingegeben haben, wird das Formular geschlossen.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Dim <\/span>strBezeichnung<span style=\"color:blue;\"> As String<\/span>\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>lngKonfigurationID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">If <\/span>IsNull(Me!Bezeichnung)<span style=\"color:blue;\"> Then<\/span>\r\n         strBezeichnung = InputBox(\"Bezeichnung eingeben:\", \"Neue Konfiguration\")\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strBezeichnung) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n             db.Execute \"INSERT INTO tblKonfigurationen(Bezeichnung) VALUES(''\" & strBezeichnung & \"'')\", dbFailOnError\r\n             lngKonfigurationID = db.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0)\r\n             Me.Requery\r\n             Me.Recordset.FindFirst \"KonfigurationID = \" & lngKonfigurationID\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             DoCmd.Close acForm, Me.Name\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     UnterformulareAktualisieren\r\n     <span style=\"color:blue;\">Set<\/span> sfm1 = Me!sfmTabelle1.Form\r\n     sfm1.OnCurrent = \"[Event Procedure]\"\r\n     <span style=\"color:blue;\">Set<\/span> sfm2 = Me!sfmTabelle2.Form\r\n     sfm2.OnCurrent = \"[Event Procedure]\"\r\n     <span style=\"color:blue;\">Set<\/span> sfm3 = Me!sfmTabelle3.Form\r\n     sfm3.OnCurrent = \"[Event Procedure]\"\r\n     <span style=\"color:blue;\">Set<\/span> sfm4 = Me!sfmTabelle4.Form\r\n     sfm4.OnCurrent = \"[Event Procedure]\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Ereignisprozedur, die beim Laden des Hauptformulars ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Anschlie&szlig;end ruft die Prozedur die Routine <b>Unter-for-mu-lare-Aktualisieren <\/b>auf (siehe weiter unten) und nimmt danach einige Einstellungen f&uuml;r die Programmierung der Unterformulare vor. F&uuml;r jedes dieser Unterformulare legen wir dazu eine Objektvariable im Kopf des Klassenmoduls an:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>WithEvents sfm1<span style=\"color:blue;\"> As <\/span>Form\r\n<span style=\"color:blue;\">Private <\/span>WithEvents sfm2<span style=\"color:blue;\"> As <\/span>Form\r\n<span style=\"color:blue;\">Private <\/span>WithEvents sfm3<span style=\"color:blue;\"> As <\/span>Form\r\n<span style=\"color:blue;\">Private <\/span>WithEvents sfm4<span style=\"color:blue;\"> As <\/span>Form<\/pre>\n<p>Danach weist die Prozdur jeder dieser Variablen das entsprechende Formular im Unterformular-Steuerelement zu und stellt die Eigenschaft <b>Beim Anzeigen <\/b>(<b>OnCurrent<\/b>) auf den Wert <b>[Ereignisprozedur] <\/b>(<b>[Event Procedure]<\/b>) ein. Dadurch k&ouml;nnen wir dieses Ereignis f&uuml;r die jeweiligen Unterformulare im aktuellen Klassenmodul implementieren.<\/p>\n<h2>Ereignis Beim Anzeigen des Hauptformulars<\/h2>\n<p>Nach dem Ereignis <b>Form_Load <\/b>wird die f&uuml;r die Ereigniseigenschaft <b>Beim Anzeigen <\/b>hinterlegte Prozedur <b>Form_Current <\/b>ausgel&ouml;st:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Current()\r\n     Me!cboKonfiguration = Me!KonfigurationID\r\n     UnterformulareAktualisieren\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese stellt das Kombinationsfeld <b>cboKonfigurationen<\/b>, welches nicht nur die Auswahl einer Konfiguration erlauben, sondern auch den Namen der aktuellen Konfiguration anzeigen soll, auf den Datensatz ein, der gerade im Formular angezeigt wird. Danach ruft sie die Prozedur <b>UnterformulareAktualisieren <\/b>auf, die Sie in Listing 4 finden.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>UnterformulareAktualisieren()\r\n     Me!cboFremdschluessel4.RowSource = Nz(Me!cboTabellen4)\r\n     Me!sfmTabelle4.Form.RecordSource = Nz(Me!cboTabellen4)\r\n     UnterformularEinstellen Me!sfmTabelle4.Form\r\n     \r\n     Me!cboPrimaerschluessel3.RowSource = Nz(Me!cboTabellen3)\r\n     Me!cboFremdschluessel3.RowSource = Nz(Me!cboTabellen3)\r\n     Me!sfmTabelle3.Form.RecordSource = Nz(Me!cboTabellen3)\r\n     UnterformularEinstellen Me!sfmTabelle3.Form\r\n     \r\n     Me!cboPrimaerschluessel2.RowSource = Nz(Me!cboTabellen2)\r\n     Me!cboFremdschluessel2.RowSource = Nz(Me!cboTabellen2)\r\n     Me!sfmTabelle2.Form.RecordSource = Nz(Me!cboTabellen2)\r\n     UnterformularEinstellen Me!sfmTabelle2.Form\r\n     \r\n     Me!cboPrimaerschluessel1.RowSource = Nz(Me!cboTabellen1)\r\n     Me!sfmTabelle1.Form.RecordSource = Nz(Me!cboTabellen1)\r\n     UnterformularEinstellen Me!sfmTabelle1.Form\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Aktualisieren der Steuerelemente der Unterformulare<\/span><\/b><\/p>\n<h2>Unterformulare aktualisieren<\/h2>\n<p>Die Prozedur <b>UnterformulareAktualisieren <\/b>wird immer beim Anzeigen beziehungsweise Wechseln des aktuellen Datensatzes aufgerufen. Sie stellt die Eigenschaften <b>Datensatzherkunft <\/b>der Kombinationsfelder und die Eigenschaft <b>Datenherkunft <\/b>der Unterformulare auf die in den Steuerelementen <b>cboTabellen1 <\/b>bis <b>cboTabellen4 <\/b>gespeicherten Tabellen ein. Au&szlig;erdem ruft die Prozedur noch f&uuml;r jedes Unterformular die bereits beschriebene Routine <b>UnterformularEinstellen <\/b>auf, um die zur angegebenen Tabelle geh&ouml;renden Felder zu binden und anzuzeigen.<\/p>\n<h2>Ereignis Beim Anzeigen der Unterformulare<\/h2>\n<p>Wie oben angek&uuml;ndigt, wollen wir das Ereignis <b>Beim Anzeigen <\/b>der Unterformulare nicht in den Unterformularen selbst implementieren, sondern gleich im Hauptformular. So ist der Code des gesamten Formulars samt Unterformularen in einem Klassenmodul. Au&szlig;erdem k&ouml;nnen wir &uuml;ber die Objektvariablen <b>Me<\/b>, <b>sfm1<\/b>, <b>sfm2<\/b>, <b>sfm3 <\/b>und <b>sfm4 <\/b>bequem auf die verschiedenen Formularinstanzen zugreifen.<\/p>\n<p>Was aber soll nun geschehen, wenn ein neuer Datensatz in einem der Unterformulare <b>sfm1 <\/b>bis <b>sfm4 <\/b>angezeigt wird Wir wollen daf&uuml;r sorgen, dass das n&auml;chste Unterformular so gefiltert wird, dass es nur noch die Datens&auml;tze anzeigt, deren Wert im Fremdschl&uuml;sselfeld mit dem Wert des Prim&auml;rschl&uuml;sselfeldes des Datensatzes im ausl&ouml;senden Formular &uuml;bereinstimmt. Wenn das erste Unterformular also etwa die Kunden anzeigt und das zweite die Bestellungen, dann soll das zweite Formular nach Auswahl eines Kunden im ersten Formular nur noch die zu diesem Kunden geh&ouml;renden Bestellungen anzeigen.<\/p>\n<p>Die Ereignisprozedur aus Listing 5 pr&uuml;ft dazu zun&auml;chst, ob &uuml;berhaupt ein Prim&auml;rschl&uuml;sselfeld und ein Fremdschl&uuml;sselfeld ausgew&auml;hlt wurden. Dazu ermittelt es die Zeichenl&auml;nge und multipliziert die beiden Werte, wobei das Ergebnis einen Wert gr&ouml;&szlig;er als <b>0 <\/b>liefern sollte.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>sfm1_Current()\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Me!cboFremdschluessel2) * <span style=\"color:blue;\">Len<\/span>(Me!cboPrimaerschluessel1) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         sfm2.Filter = Me!cboFremdschluessel2 & \" = \" & sfm1.Controls(Nz(Me!cboPrimaerschluessel1))\r\n         sfm2.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         sfm2.Filter = \"\"\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 5: Ereignis, das beim Anzeigen eines Datensatzes im Unterformular ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Danach stellt die Prozedur die Eigenschaft <b>Filter <\/b>f&uuml;r das Unterformular auf einen Wert ein, der sich aus dem Wert des Kombinationsfeldes <b>cboFremdschluessel <\/b>(also dem Namen des Fremdschl&uuml;sselfeldes), einem Gleichheitszeichen und dem Wert des Prim&auml;rschl&uuml;sselfeldes des &uuml;bergeordneten Formulars zusammensetzt und etwa wie folgt aussieht:<\/p>\n<pre>KundeID = 123<\/pre>\n<p>Anschlie&szlig;end aktiviert sie den Filter durch Einstellen der Eigenschaft <b>FilterOn <\/b>auf <b>True<\/b>. Sollte eines der beiden Kombinationsfelder nicht gef&uuml;llt sein, wird der Filter schlicht und einfach geleert.<\/p>\n<h2>Ausw&auml;hlen einer anderen Konfiguration<\/h2>\n<p>Wenn der Benutzer einen der anderen Eintr&auml;ge des Kombinationsfeldes <b>cboKonfiguration <\/b>ausw&auml;hlt, soll die entsprechende Konfiguration auch im Formular angezeigt werden.<\/p>\n<p>Dies erledigen wir mit der folgenden Prozedur, die durch das Ereignis <b>Nach Aktualisierung <\/b>des Kombinationsfeldes <b>cboKonfigurationen <\/b>ausgel&ouml;st wird:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cboKonfiguration_AfterUpdate()\r\n     Me.Recordset.FindFirst \"KonfigurationID = \" _\r\n         & Me!cboKonfiguration\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Dies l&ouml;st nat&uuml;rlich auch die Ereignisprozedur <b>Form_Current <\/b>und die <b>Beim Anzeigen<\/b>-Ereignisprozeduren der vier Unterformulare aus, wodurch die Konfiguration wenig sp&auml;ter im Formular abgebildet wird. <\/p>\n<h2>Hinzuf&uuml;gen einer neuen Konfiguration<\/h2>\n<p>Wenn Sie eine neue Konfiguration hinzuf&uuml;gen m&ouml;chten, k&ouml;nnen Sie dies mit einem Klick auf die Schaltfl&auml;che <b>cmdNeu<\/b> erledigen. Diese l&ouml;st die Prozedur aus Listing 6 aus. Die Prozedur ermittelt zun&auml;chst per <b>InputBox <\/b>die Bezeichnung f&uuml;r die neue Konfiguration und pr&uuml;ft, ob der Benutzer eine Zeichenkette eingegeben hat. Falls ja, tr&auml;gt die Prozedur diese als neuen Datensatz in die Tabelle <b>tblKonfiguration <\/b>ein und ermittelt den Prim&auml;rschl&uuml;sselwert des neuen Datensatzes dieser Tabelle. Danach aktualisiert sie die Datenherkunft des aktuellen Formulars, um auch den neuen Datensatz anzeigen zu k&ouml;nnen. Schlie&szlig;lich sorgt der Aufruf der <b>FindFirst<\/b>-Methode des Recordsets des Formulars f&uuml;r die Anzeige des neuen Datensatzes. Der Benutzer kann nun die Tabellen, Prim&auml;rschl&uuml;sselfelder und Fremdschl&uuml;sselfelder ausw&auml;hlen.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdNeu_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strBezeichnung<span style=\"color:blue;\"> As String<\/span>\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>lngKonfigurationID<span style=\"color:blue;\"> As Long<\/span>\r\n     strBezeichnung = InputBox(\"Bezeichnung eingeben:\", \"Neue Konfiguration\")\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strBezeichnung) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n         db.Execute \"INSERT INTO tblKonfigurationen(Bezeichnung) VALUES(''\" & strBezeichnung & \"'')\", dbFailOnError\r\n         lngKonfigurationID = db.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0)\r\n         Me.Requery\r\n         Me.Recordset.FindFirst \"KonfigurationID = \" & lngKonfigurationID\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 6: Anlegen einer neuen Konfiguration<\/span><\/b><\/p>\n<h2>L&ouml;schen einer Konfiguration<\/h2>\n<p>Wenn der Benutzer die aktuelle Konfiguration l&ouml;schen will, kann er dies mit der Schaltfl&auml;che <b>cmdLoeschen <\/b>erledigen, die folgende Ereignisprozedur ausl&ouml;st:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdLoeschen_Click()\r\n     RunCommand acCmdDeleteRecord\r\n     Me.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Diese L&ouml;sung k&ouml;nnen Sie am besten beim Erstellen, Bearbeiten oder Testen von Algorithmen nutzen, die Daten per VBA anlegen, bearbeiten oder l&ouml;schen &#8211; also dort, wo die Ergebnisse nicht direkt in der Benutzeroberfl&auml;che erscheinen. Um die Anwendung dort nutzen zu k&ouml;nnen, importieren Sie einfach die beiden Formulare <b>frmTabellen <\/b>und <b>sfmTabellen <\/b>sowie die Tabelle <b>tblKonfigurationen <\/b>in die gew&uuml;nschte Datenbank.<\/p>\n<p>Alternativ k&ouml;nnen Sie diese drei Elemente auch in ein Add-In integrieren und die L&ouml;sung so flexibel f&uuml;r alle in Access ge&ouml;ffneten Datenbanken verf&uuml;gbar machen. Wie das geht, zeigen wir im Beitrag <b>Verkn&uuml;pfte Daten suchen per Add-In <\/b>(<b>www.access-im-unternehmen.de\/1083<\/b>).<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>VerknuepfteDatenSuchen.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/726348A7-2982-4BF5-9539-061B7EA2157B\/aiu_1078.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn Sie eine Anwendung programmieren, die ihre Daten nur &uuml;ber die Benutzeroberfl&auml;che &auml;ndert, sehen Sie die &Auml;nderungen ja immer direkt in den entsprechenden Formularen und Steuerelementen. Aber manchmal erstellen, &auml;ndern oder l&ouml;schen Sie Daten auch per Mausklick auf eine Schaltfl&auml;che, und die dahinterliegende Prozedur erledigt den Rest. Gerade in der Entwicklungsphase m&ouml;chen Sie dann nat&uuml;rlich schnell sehen, ob die Daten auch wirklich wie gew&uuml;nscht editiert wurden. Dazu qu&auml;lt man sich dann meist durch die einzelnen Tabellen und pr&uuml;ft das Ergebnis. Wenn sich die Daten &uuml;ber verkn&uuml;pfte Tabellen erstrecken, wird dies erst recht anstrengend. Aber nicht mit der L&ouml;sung, die wir in diesem Beitrag vorstellen!<\/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":[66022017,662017,44000021],"tags":[],"class_list":["post-55001078","post","type-post","status-publish","format-standard","hentry","category-66022017","category-662017","category-Tabellen_und_Datenmodellierung"],"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>Verkn&uuml;pfte Daten suchen - 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\/Verknuepfte_Daten_suchen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Verkn&uuml;pfte Daten suchen\" \/>\n<meta property=\"og:description\" content=\"Wenn Sie eine Anwendung programmieren, die ihre Daten nur &uuml;ber die Benutzeroberfl&auml;che &auml;ndert, sehen Sie die &Auml;nderungen ja immer direkt in den entsprechenden Formularen und Steuerelementen. Aber manchmal erstellen, &auml;ndern oder l&ouml;schen Sie Daten auch per Mausklick auf eine Schaltfl&auml;che, und die dahinterliegende Prozedur erledigt den Rest. Gerade in der Entwicklungsphase m&ouml;chen Sie dann nat&uuml;rlich schnell sehen, ob die Daten auch wirklich wie gew&uuml;nscht editiert wurden. Dazu qu&auml;lt man sich dann meist durch die einzelnen Tabellen und pr&uuml;ft das Ergebnis. Wenn sich die Daten &uuml;ber verkn&uuml;pfte Tabellen erstrecken, wird dies erst recht anstrengend. Aber nicht mit der L&ouml;sung, die wir in diesem Beitrag vorstellen!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-14T13:41:45+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg09.met.vgwort.de\/na\/0727a06d35104f15b27567571fc8b688\" \/>\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=\"28\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Verkn&uuml;pfte Daten suchen\",\"datePublished\":\"2020-05-14T13:41:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/\"},\"wordCount\":4907,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/0727a06d35104f15b27567571fc8b688\",\"articleSection\":[\"2\\\/2017\",\"2017\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/\",\"name\":\"Verkn&uuml;pfte Daten suchen - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/0727a06d35104f15b27567571fc8b688\",\"datePublished\":\"2020-05-14T13:41:45+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/0727a06d35104f15b27567571fc8b688\",\"contentUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/0727a06d35104f15b27567571fc8b688\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Verknuepfte_Daten_suchen\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Verkn&uuml;pfte Daten suchen\"}]},{\"@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":"Verkn&uuml;pfte Daten suchen - 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\/Verknuepfte_Daten_suchen\/","og_locale":"de_DE","og_type":"article","og_title":"Verkn&uuml;pfte Daten suchen","og_description":"Wenn Sie eine Anwendung programmieren, die ihre Daten nur &uuml;ber die Benutzeroberfl&auml;che &auml;ndert, sehen Sie die &Auml;nderungen ja immer direkt in den entsprechenden Formularen und Steuerelementen. Aber manchmal erstellen, &auml;ndern oder l&ouml;schen Sie Daten auch per Mausklick auf eine Schaltfl&auml;che, und die dahinterliegende Prozedur erledigt den Rest. Gerade in der Entwicklungsphase m&ouml;chen Sie dann nat&uuml;rlich schnell sehen, ob die Daten auch wirklich wie gew&uuml;nscht editiert wurden. Dazu qu&auml;lt man sich dann meist durch die einzelnen Tabellen und pr&uuml;ft das Ergebnis. Wenn sich die Daten &uuml;ber verkn&uuml;pfte Tabellen erstrecken, wird dies erst recht anstrengend. Aber nicht mit der L&ouml;sung, die wir in diesem Beitrag vorstellen!","og_url":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-14T13:41:45+00:00","og_image":[{"url":"http:\/\/vg09.met.vgwort.de\/na\/0727a06d35104f15b27567571fc8b688","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"28\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Verkn&uuml;pfte Daten suchen","datePublished":"2020-05-14T13:41:45+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/"},"wordCount":4907,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/0727a06d35104f15b27567571fc8b688","articleSection":["2\/2017","2017","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/","url":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/","name":"Verkn&uuml;pfte Daten suchen - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/0727a06d35104f15b27567571fc8b688","datePublished":"2020-05-14T13:41:45+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#primaryimage","url":"http:\/\/vg09.met.vgwort.de\/na\/0727a06d35104f15b27567571fc8b688","contentUrl":"http:\/\/vg09.met.vgwort.de\/na\/0727a06d35104f15b27567571fc8b688"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Verknuepfte_Daten_suchen\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Verkn&uuml;pfte Daten suchen"}]},{"@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\/55001078","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=55001078"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001078\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001078"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001078"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001078"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}