{"id":55000615,"date":"2008-08-01T00:00:00","date_gmt":"2021-03-22T16:19:39","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=615"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Hierarchien_visualisieren","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/","title":{"rendered":"Hierarchien visualisieren"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg09.met.vgwort.de\/na\/480f5043e4864c79ab00b2b24e81846e\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Hierarchien sind das A und O bei der Datenbankentwicklung. Sie im Datenmodell abzubilden und diese in Formularen anzuzeigen, sind jedoch zwei verschiedene Welten. Da es aber ohne passende Formulare zur Eingabe und Bearbeitung auch hierarchischer Daten nicht geht, stellen wir Ihnen in diesem Beitrag verschiedene M&ouml;glichkeiten f&uuml;r die Abfrage und Darstellung der unterschiedlichen Hierarchieformen vor.<\/b><\/p>\n<p>Die Vorarbeit zum Thema &#8222;Visualisierung von Hierarchien&#8220; liefert der Beitrag <b>Datenhierarchien in Access <\/b>(<a href=\"http:\/\/www.access-im-unternehmen.de\/555\">access-im-unternehmen.de\/555<\/a>), der die Realisierung der verschiedenen Hierarchiearten in entsprechend verkn&uuml;pften Tabellen zeigt. Auf diesem Beitrag bauen wir auf und zeigen nun, wie sich die verschiedenen Hierarchien durch Abfragen aufbereiten und in Formularen und passenden Steuerelementen anzeigen lassen.<\/p>\n<p><b>Darstellen von Begriffshierarchien<\/b><\/p>\n<p>Begriffshierarchien lassen sich erfreulich leicht behandeln, da die Datens&auml;tze selbst gar nicht kaskadierend anwachsen, sondern nur die Tabellen, auf die sie verteilt sind.<\/p>\n<p>Es wurden mehrere Typen von Begriffshierarchien im erw&auml;hnten Beitrag erl&auml;utert. F&uuml;r die Darstellung in der Oberfl&auml;che von Access ist es ausreichend, sich mit der Alternative disjunkt versus adjunkt auseinanderzusetzen. Erinnern Sie sich: Adjunkt bedeutet, dass sich ein Element auf h&ouml;herer Stufe in mehrere Detailtabellen fortsetzen kann. Im Beispiel Firma (Lieferant, Kunde) konnte eine Firma sowohl Kunden- als auch Lieferantendaten aufweisen oder beides zugleich oder keines von beiden.<\/p>\n<p>Disjunkt bedeutet, dass ein Element h&ouml;herer Stufe nur h&ouml;chstens einen Detaildatensatz haben kann. Im Beispiel Tiersystematik Wirbeltier (Fisch|Vogel|S&auml;uger) konnte ein Tier nur einen Folgedatensatz haben, da es zum Beispiel nicht gleichzeitig Fisch und Vogel sein kann. Einer der Detailbegriffe muss es aber sein.<\/p>\n<p><b>Abfragen von Begriffsbeziehungen<\/b><\/p>\n<p>Eine Abfrage &uuml;ber alle Tiere mit angeh&auml;ngten Spezialisierungen muss zwingend mit Outer Joins arbeiten, da ein Hauptdatensatz ja nur in einer Detailtabelle fortgesetzt werden kann. Die Entwurfsansicht sehen Sie in Bild 1, das Ergebnis in Bild 2.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic001_opt.jpeg\" alt=\"pic001.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Entwurf alle, disjunkt<\/span><\/b><\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic002_opt.jpeg\" alt=\"pic002.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Ergebnis alle, disjunkt<\/span><\/b><\/p>\n<p>Beachten Sie die systematisch leeren Felder in dieser Abfrage. Bei einem falschen Entwurf s&auml;he die Tabellenstruktur selbst so aus.<\/p>\n<p>Sinnvoller sind in der Regel spezialisierte Abfragen auf alle Fische, alle V&ouml;gel oder alle Tiere, aber ohne Spezialfelder. Eine Abfrage auf alle Fische filtert automatisch, wenn Sie einfach einen Inner Join benutzen. Das Ergebnis des folgenden SQL-Ausdrucks finden Sie in Bild 3.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic003_opt.jpeg\" alt=\"pic003.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Ergebnis Fische, disjunkt<\/span><\/b><\/p>\n<pre>SELECT Tier.idTier, Tier.Name, Tier.Gewicht, Fisch.Schuppenform, Fisch.Flossenzahl, Fisch.Wasser FROM Tier INNER JOIN Fisch\r\nON Tier.idTier = Fisch.fiFisch;<\/pre>\n<p>Die Abfrage gemeinsamer Eigenschaften aller Tiere ohne Spezialfelder ist trivial. Hier fragen Sie einfach die Tabelle <b>Tiere <\/b>alleine ab.<\/p>\n<p>Beim Abfragen einer adjunkten Hierarchie &auml;ndert sich nichts, mit dem Unterschied, dass die Abfrage aller Hierarchietabellen zugleich, wie in Bild 1 und 2, durchaus sinnvoll beziehungsweise sogar der Normalfall ist.<\/p>\n<p>Aus Gr&uuml;nden der &Uuml;bersichtlichkeit haben Sie bisher nur eine Mini-Hierarchie mit zwei Ebenen gesehen. Um den hierarchischen Charakter des Aufbaus noch etwas zu verdeutlichen, sehen Sie ein etwas komplexeres Beispiel in Bild 4.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic004_opt.jpeg\" alt=\"pic004.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Begriffshierarchie mit drei Stufen<\/span><\/b><\/p>\n<p><b>Formulardarstellung<\/b><\/p>\n<p>Es empfiehlt sich eine unterschiedliche Darstellungsweise f&uuml;r die beiden Hierarchietypen disjunkt und adjunkt. <\/p>\n<p><b>Disjunkte Formulare<\/b><\/p>\n<p>F&uuml;r die Pr&auml;sentation gibt es im Wesentlichen zwei sinnvolle M&ouml;glichkeiten, die sich nat&uuml;rlich weiter ausbauen lassen. Eine gemeinsame Darstellung in einem Formular nach dem Schema <b>Tierfelder+Fischfelder+Vogelfelder+S&auml;ugerfelder <\/b>wie in der Abfrage aus Bild 1 und 2 ist normalerweise weniger geeignet, da bei jedem Datensatz ein Teil der Spezialisierungsfelder systematisch leer bliebe. Die Detailfelder k&ouml;nnen nach Art und Menge in den Gruppen v&ouml;llig unterschiedlich sein.<\/p>\n<p>Bei den gew&auml;hlten Beispielen besteht in den spezialisierten Zweigen immer noch eine gewisse semantische Symmetrie. Bedenken Sie aber, dass eine Spezialisierung durchaus so aussehen k&ouml;nnte, dass Typ A &uuml;ber drei umfangreiche Textfelder verf&uuml;gt, w&auml;hrend Typ B statt dessen durch vierzig Kennzahlen, die in Form von Balken dargestellt werden sollen, charakterisiert wird. Es ist also wenig hilfreich, Detailfelder wechselseitig auszublenden oder &auml;hnliches. Hier sind nur typenspezifisch gestaltete Formulare sinnvoll.<\/p>\n<p>Aber zur&uuml;ck zu den Tieren: Benutzer, die sich f&uuml;r die Inhalte von Fischfeldern interessieren, brauchen also gar keine V&ouml;gel und S&auml;uger zu sehen.<\/p>\n<p>Benutzer wiederum, die sich f&uuml;r V&ouml;gel, S&auml;uger und Fische synoptisch interessieren, k&ouml;nnen eigentlich nur an den gemeinsamen Tierfeldern interessiert sein, da alle anderen keine gruppen&uuml;bergreifende Vergleichsbasis bieten.<\/p>\n<p>Um dem entgegenzukommen, bieten sich zwei Vorgehensweisen an:<\/p>\n<ul>\n<li class=\"aufz-hlung\">V&ouml;llig getrennte Spezialformulare f&uuml;r jede Gruppe:<\/li>\n<li class=\"aufz-hlung\"><b>frmFisch<\/b>: Tierfelder+Fischfelder<\/li>\n<li class=\"aufz-hlung\"><b>frmVogel<\/b>: Tierfelder+Vogelfelder<\/li>\n<li class=\"aufz-hlung\"><b>frmS&auml;uger<\/b>: Tierfelder+S&auml;ugerfelder<\/li>\n<li class=\"aufz-hlung\">Gemeinsames Formular f&uuml;r alle Tiere ohne Detailinformationen<\/li>\n<li class=\"aufz-hlung\"><b>frmTier<\/b>: Tierfelder<\/li>\n<\/ul>\n<p>In beiden F&auml;llen sehen die Formulare so aus, als bez&ouml;gen sie einfach nur eine Tabelle &#8211; die Begriffshierarchie bleibt v&ouml;llig im Hintergrund.<\/p>\n<p>Sie k&ouml;nnte sich aber zum Beispiel in einer Men&uuml;struktur zeigen (siehe Bild 5). F&uuml;r die Arbeit mit den konkreten Daten ist die hierarchische Struktur bedeutungslos.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic005_opt.jpeg\" alt=\"pic005.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Men&uuml; f&uuml;r Begriffshierarchie<\/span><\/b><\/p>\n<p>Ein Men&uuml;punkt &#8222;Alle&#8220; &ouml;ffnet dann sinnigerweise ein Formular, das die Eigenschaften anzeigt, die f&uuml;r alle Tiere gelten, w&auml;hrend ein Men&uuml;punkt &#8222;V&ouml;gel&#8220; ein Formular &ouml;ffnen k&ouml;nnte, das die gemeinsamen Eigenschaften aller Tiere plus die speziellen Eigenschaften von V&ouml;geln anzeigt.<\/p>\n<p>Hinter einem solchen Formular steht eine Abfrage wie die bereits unter Abfragen von Begriffsbeziehungen vorgestellte. Sie k&ouml;nnen darin ohne Weiteres neue Datens&auml;tze anlegen, wobei ein Autowert in der Haupttabelle automatisch als Fremdschl&uuml;ssel in der verkn&uuml;pften Detailtabelle auftaucht, sobald ein Spezialfeld gef&uuml;llt wird.<\/p>\n<p><b>Adjunkte Formulare<\/b><\/p>\n<p>Hier sieht die Sache anders aus, da ein Datensatz mehrere Spezialdatens&auml;tze haben kann, die m&ouml;glicherweise auch gemeinsam interessieren. Nat&uuml;rlich k&ouml;nnen Sie dennoch Spezialformulare wie im vorigen Kapitel erstellen. Eine &Uuml;bersicht aller Lieferanten mit ihren Lieferbedingungen und nat&uuml;rlich auch den allgemeinen Firmeninformationen ergibt durchaus Sinn, entsprechend auch f&uuml;r Kunden. Das entspricht analog einer reinen Fisch- oder Vogelabfrage.<\/p>\n<p>Allerdings ist die Zusammenfassung der Details in der Gesamtansicht durchaus von Interesse, da ein Hauptdatensatz ja &uuml;ber alle Details gleichzeitig verf&uuml;gen kann. Bei der Formulargestaltung ist wichtig, dass Sie durch Rahmenelemente, farbige Bereiche oder &auml;hnliche Ma&szlig;nahmen die hierarchische Zusammengeh&ouml;rigkeit der Datenbl&ouml;cke ausdr&uuml;cken. Einen einfachen Vorschlag hierzu sehen Sie in Bild 6.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic006_opt.jpeg\" alt=\"pic006.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 6: Adjunkte Hierarchie im Formular<\/span><\/b><\/p>\n<p>Eine platzsparende Alternative mit Registern ist in Bild 7 dargestellt.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic007_opt.jpeg\" alt=\"pic007.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 7: Adjunkte Hierarchie mit Register<\/span><\/b><\/p>\n<p>In beiden Beispielen werden keine Unterformulare verwendet und die Datenbasis der Formulare ist jeweils die Abfrage aus Bild 4. Die Register sind &uuml;brigens nicht verschachtelt, das zweite Register ist einfach &uuml;ber dem ersten platziert. Beim Registerwechsel schaltet das untergeordnete Register dennoch um: Es hat f&uuml;nf Seiten, die mit der Routine aus dem folgenden Listing gesteuert werden:<\/p>\n<pre>Private Sub RegisterMain_Change()\r\n    Dim i As Long\r\n    With Me!RegisterMain\r\n    For i = 0 To 2\r\n        .Pages(i).Visible = _\r\n        (Me!RegisterSub.Value = 0)\r\n    Next i\r\n    For i = 3 To 4\r\n        .Pages(i).Visible = _\r\n        (Me!RegisterStrSub.Value = 1)\r\n    Next i\r\n    End With\r\nEnd Sub<\/pre>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Darstellen von Objekthierarchien<\/p>\n<p>So einfach, wie mit den Begriffshierarchien haben Sie es mit den Objekthierarchien nicht. Im Gegenteil: Hier bietet die relationale Theorie allerlei auf, um Ihnen das Leben schwer zu machen. Abgeschlossene Hierarchien sind dabei noch vergleichsweise harmlos; offene reflexive Hierarchien entziehen sich aber einem reinen SQL-Zugriff v&ouml;llig. Es liegt in der Natur der Sache, dass reflexive Strukturen nur mit Selbstbezug (Rekursion) oder Schleifen (Iteration) behandelbar sind. Das ist mit ANSI-SQL jedoch nicht m&ouml;glich, sodass zus&auml;tzlich die Verwendung einer prozeduralen Sprache erforderlich wird &#8211; etwa VBA, um ein TreeView zu bef&uuml;llen.<\/p>\n<p><b>Arten der Visualisierung<\/b><\/p>\n<p>Um Objekthierarchien darzustellen, m&uuml;ssen Sie im Wesentlichen zwei Informationen grafisch &uuml;bersichtlich aufbereiten (mit der Frage, wie Sie diese aus den Hierarchietabellen gewinnen k&ouml;nnen, werden Sie sich noch besch&auml;ftigen m&uuml;ssen: sie stehen n&auml;mlich nicht einfach so drin). Das ist zum einen die Reihenfolge der Daten: Nachkommen sollten eine direkte Verbindung zu ihrem Elter haben und Geschwister beieinanderstehen. Zum anderen die Ebene: Angeh&ouml;rige der gleichen Generation sollten als solche erkennbar sein, auch wenn sie keine Geschwister sind. <\/p>\n<p>Es gibt zwei &uuml;bliche Darstellungsweisen, einmal vertikal in Form einer Liste und einmal horizontal in Form einer Tabelle. Die vertikale Darstellung ist als Baumansicht (TreeView) bekannt und verbreitet. Die Verwandtschaft zeigt sich durch Anordnung untereinander und Einr&uuml;ckung.<\/p>\n<pre>Vater1\r\nKind11\r\nEnkel111\r\nKind12\r\nVater2\r\nKind21<\/pre>\n<p>Die horizontale Darstellung hat die Form einer hierarchischen Tabelle (Hierarchical Grid, wie es zum Beispiel mit Visual Basic 6 eingef&uuml;hrt wurde) und ist weniger verbreitet. Die Verwandtschaft wird hier durch Anordnung nebeneinander und Zellverschmelzung ausgedr&uuml;ckt.<\/p>\n<p>Die grunds&auml;tzliche Bef&uuml;llungslogik ist f&uuml;r beide Steuerelemente identisch: Sie m&uuml;ssen die Daten in passender Reihenfolge unter Ber&uuml;cksichtigung der Ebene eintragen. Auf die hierarchische Tabelle soll nicht mehr weiter eingegangen werden. Das Hierarchical Flexgrid weist erhebliche Einschr&auml;nkungen auf und vergleichbare Controls von Drittherstellern gibt es zwar, aber die Programmierung weicht jeweils deutlich voneinander ab. <\/p>\n<p>Ein Spezialfall ist die Beschr&auml;nkung der Darstellung auf zwei Ebenen. In Access w&uuml;rden Sie hierzu ein Formular in Einzelansicht mit einem Unterformular in Endlos- oder Datenblattansicht verwenden.<\/p>\n<pre>Vater1\r\nKind11\r\nKind12<\/pre>\n<p>Wenn Sie in einem Endlosformular jedem Kinddatensatz einen Button verpassen, der das Kind zum aktuellen Datensatz im Hauptformular macht, haben Sie damit &uuml;brigens durchaus eine Funktionalit&auml;t erzeugt, die eine beliebig tiefe Hierarchie handhabbar macht. Sie schieben sozusagen ein &#8222;Fenster&#8220; &uuml;ber die Hierarchie, das immer nur den Blick auf zwei benachbarte Ebenen erlaubt, aber ansonsten beliebig positioniert werden kann. Solange Sie nicht wirklich einen Gesamt&uuml;berblick brauchen, ist das durchaus eine hinl&auml;ngliche Alternative. Sie werden zu jedem Fall sp&auml;ter noch ein Beispiel sehen.<\/p>\n<p><!--30percent--><\/p>\n<p><b>Datenabfragen bei Hierarchien<\/b><\/p>\n<p>Hierbei beschr&auml;nken wir uns auf die beiden praxisrelevanten F&auml;lle. Das ist zum einen die abgeschlossene irreflexive Hierarchie, bei der die Nutzdaten der Objekte mit den Hierarchieinformationen gemeinsam in den Tabellen jeder Ebene gespeichert sind, wobei die Anzahl der Ebenen beliebig, aber begrenzt (also bekannt) ist, und zum anderen die offene reflexive Hierarchie, bei der es eine Nutzdatentabelle und eine reine Hierarchietabelle gibt. Grundlegende Informationen, die zu einem Element immer wieder gebraucht werden, sind:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Wer ist mein Vater (Vorg&auml;nger)<\/li>\n<li class=\"aufz-hlung\">Wer sind meine Ahnen (Pfad)<\/li>\n<li class=\"aufz-hlung\">Wer sind meine Kinder<\/li>\n<li class=\"aufz-hlung\">Wie viele Kinder habe ich<\/li>\n<li class=\"aufz-hlung\">Wer sind meine Geschwister<\/li>\n<li class=\"aufz-hlung\">Wie viele Geschwister habe ich<\/li>\n<li class=\"aufz-hlung\">Wer sind meine Nachkommen<\/li>\n<li class=\"aufz-hlung\">Wie viele Nachkommen habe ich<\/li>\n<li class=\"aufz-hlung\">Zu welcher Generation geh&ouml;re ich<\/li>\n<\/ul>\n<p>Die Abfrage dieser Informationen mit SQL unterscheidet sich gegebenenfalls bei geschlossenen und offenen Hierarchien. Beim Arbeiten mit Recordsets in VBA k&ouml;nnen Teile dieser Informationen sich auch aus dem Programmablauf ergeben.<\/p>\n<p><b>Abgeschlossene Hierarchien<\/b><\/p>\n<p>Eine vollst&auml;ndige Hierarchietabelle ergibt sich sehr einfach und anschaulich, indem Sie alle Tabellen der Hierarchie hintereinander mit einem LEFT JOIN verbinden &#8211; LEFT JOIN deshalb, damit Sie auch kinderlose Datens&auml;tze h&ouml;herer Ebenen sehen. <\/p>\n<pre>SELECT\r\nEbene0.id0, Ebene0.Bezeichnung0,\r\nEbene1.id1, Ebene1.Bezeichnung1,\r\nEbene2.id2, Ebene2.Bezeichnung2\r\nFROM\r\n(Ebene0 LEFT JOIN Ebene1\r\nON Ebene0.id0 = Ebene1.fiParent1\r\n) LEFT JOIN Ebene2\r\nON Ebene1.id1 = Ebene2.fiParent2<\/pre>\n<p>Das Entwurfsdiagramm dazu sieht wie in Bild 8 aus, das Ergebnis wie in Bild 9. Ein anschauliches Beispiel dazu mit Kunden, Bestellungen und Artikeln sehen Sie in Bild 10.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic008_opt.jpeg\" alt=\"pic008.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 8: Hierarchie&uuml;berblick, Entwurf<\/span><\/b><\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic009_opt.jpeg\" alt=\"pic009.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 9: Hierarchie&uuml;berblick, Ergebnis<\/span><\/b><\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic010_opt.jpeg\" alt=\"pic010.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 10: Ein weiterer Hierarchie&uuml;berblick<\/span><\/b><\/p>\n<p>Dieses Vorgehen ist m&ouml;glich, da die Anzahl der Ebenen beim Abfrageentwurf feststeht.<\/p>\n<p>Das Abfragen des Vorg&auml;ngers ist banal: Sein Schl&uuml;ssel steht im Fremdschl&uuml;ssel des aktuellen Datensatzes, weitere Daten, etwa eine Bezeichnung, ergeben sich durch einen schlichten JOIN auf die Vorg&auml;ngertabelle.<\/p>\n<p>Der Pfad ergibt sich entsprechend durch einen JOIN bis zur Ursprungsebene. Die Kinder erhalten Sie mit folgendem SQL-Ausdruck, wobei X f&uuml;r die abzufragende Ebene steht:<\/p>\n<pre>SELECT * FROM Ebene(X) WHERE fi=Ebene(X-1).id<\/pre>\n<p><b>Erzeugen eines Baumes in einer Abfrage <\/b><\/p>\n<p>Theoretisch ist das recht einfach: Sie m&uuml;ssen die Daten der verschiedenen Ebenen nur alle in die richtige Reihenfolge untereinander bringen und den Abstammungsverh&auml;ltnissen gem&auml;&szlig; einr&uuml;cken. <\/p>\n<p>Praktisch ist das zwar m&ouml;glich, aber nicht unbedingt einfach.<\/p>\n<p>Um alle Daten in eine Abfrage zu bringen, brauchen Sie zun&auml;chst eine Union-Abfrage &uuml;ber alle Ebenen:<\/p>\n<pre>SELECT Bezeichnung FROM Ebene0\r\nUNION SELECT Bezeichnung FROM Ebene1\r\nUNION SELECT Bezeichnung FROM Ebene2\r\nUNION SELECT Bezeichnung FROM Ebene3<\/pre>\n<p>Die Ebene ergibt sich aus der Ursprungstabelle:<\/p>\n<pre>SELECT Bezeichnung, 0 As E FROM Ebene0\r\nUNION\r\nSELECT Bezeichnung, 1 As E FROM Ebene1\r\n&euro;...<\/pre>\n<p>Damit k&auml;me etwa folgende Darstellung heraus:<\/p>\n<pre>A (1)\r\nB (7)\r\nC (14)\r\nAa (2)\r\nAb (5)\r\nAc (6)\r\nBa (8)\r\nBb (9)\r\nBc (13)\r\nAaa (3)\r\nAab (4)\r\nBba (10)\r\nBbb (11)\r\nBbc (12)<\/pre>\n<p>In Klammern sehen Sie die Zeilennummern, die die Datens&auml;tze bei richtiger Anordnung haben m&uuml;ssten:<\/p>\n<pre>A (1)\r\nAa (2)\r\nAaa (3)\r\nAab (4)\r\nAb (5)\r\nAc (6)\r\nB (7)\r\nBa (8)\r\nBb (9)\r\nBba (10)\r\nBbb (11)\r\nBbc (12)\r\nBc (13)\r\nC (14)<\/pre>\n<p>Sie ben&ouml;tigen also noch Sortierfelder, die die richtige Reihenfolge sicherstellen. Dabei ist zu beachten: Die Sortierung bez&uuml;glich der Vaterschaft ist durch die Hierarchie vorgegeben, das hei&szlig;t, Kinder m&uuml;ssen direkt nach ihrem Vater einsortiert werden; die Sortierung innerhalb einer Generation ist beliebig, das hei&szlig;t, Geschwister k&ouml;nnten untereinander nach unterschiedlichen Kriterien sortiert sein.<\/p>\n<p>In einer Hierarchie <b>Kunde|Ansprechpartner|Betreute Projekte <\/b>m&ouml;chten Sie vielleicht den Kunden nach Firma oder Nachname sortieren, die Ansprechpartner innerhalb der Firmen nach Wichtigkeit und die von einem Ansprechpartner betreuten Projekte nach Datum. Das folgende Beispiel erstreckt einen Baum &uuml;ber drei Ebenen:<\/p>\n<pre>SELECT Order0, Order1, Order2, Space(4*E)\r\n&amp; Bez AS H\r\nFROM (SELECT Bezeichnung0 AS Bez, Order0, 0 AS\r\nOrder1, 0 AS Order2, 0 AS E FROM Ebene0) AS\r\nE0\r\nUNION SELECT Order0, Order1, Order2, Space(4*E)\r\n&amp; Bez AS H\r\nFROM (SELECT Bezeichnung1 AS Bez, Ebene0.Order0,\r\nEbene1.Order1, 0 AS order2, 1 AS E\r\nFROM Ebene0 INNER JOIN Ebene1 ON Ebene0.id0 =\r\nEbene1.fiParent1) AS E1\r\nUNION SELECT Order0, Order1, Order2, Space(4*E) &amp;\r\nBez AS H FROM (SELECT Bezeichnung2 AS Bez,\r\nEbene0.Order0, Ebene1.Order1, Ebene2.Order2,\r\n2 AS E\r\nFROM (Ebene0 INNER JOIN Ebene1 ON Ebene0.id0 =\r\nEbene1.fiParent1) INNER JOIN Ebene2\r\nON Ebene1.id1 = Ebene2.fiParent2) AS E2\r\nORDER BY order0, order1, order2<\/pre>\n<p>Das Ergebnis dieser Abfrage sehen Sie in Bild 11. Die k&uuml;nstlichen Einr&uuml;ckungen kommen durch den Einsatz der VBA-Funktion <b>Space() <\/b>zustande.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic011_opt.jpeg\" alt=\"pic011.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 11: <\/span><\/b><\/p>\n<p>In diesem Beispiel wurde mit in der Tabelle gespeicherten Nummern f&uuml;r eine benutzerdefinierte Sortierung gearbeitet. Nun wollen wir noch, wie eingangs versprochen, zeigen, wie Sie auch nach beliebigen Datenfeldern sortieren k&ouml;nnen.<\/p>\n<p>Sehen Sie sich hierzu dasselbe Beispiel noch einmal mit dem Feld <b>Bezeichnung <\/b>als Sortierkriterium an, wobei zu Demonstrationszwecken die obere Ebene einmal absteigend sortiert wurde.<\/p>\n<p>Die erforderlichen &auml;nderungen f&uuml;r die Textsortierung finden Sie in der Beispieldatenbank <b>DemoObjekthierarchie.mdb <\/b>in der Abfrage <b>H1NeuEbeneUnionNachBezeichnung<\/b>.<\/p>\n<p>Das einzige, was Sie dort tun m&uuml;ssen, ist also, Ihr als Sortierkriterium gew&uuml;nschtes Datenfeld anstelle von <b>Order0<\/b>, <b>Order1 <\/b>und <b>Order2<\/b> anzugeben, wobei Sie jeweils <b>Order0<\/b>, <b>Order1 <\/b>und <b>Order2<\/b> als Alias vergeben, wodurch der weitere Code nicht ge&auml;ndert wird. Die Ausgabe dieser Abfrage s&auml;he dann aus wie in Bild 12. Beachten Sie, dass die oberste Ebene aufsteigend sortiert ist und die unteren absteigend.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic012_opt.jpeg\" alt=\"pic012.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 12: Sortierung nach <\/span><\/b><\/p>\n<p><b>Erzeugen eines Baumes im Formular<\/b><\/p>\n<p>Nat&uuml;rlich k&ouml;nnten Sie die Abfrage aus dem vorangegangenen Abschnitt als Datenherkunft eines Endlosformulars benutzen und so eine Baumdarstellung erzeugen. Normalerweise werden Sie hier aber ein spezielles Steuerelement wie das Treeview-Control benutzen.<\/p>\n<p>Da die Programmierung eines TreeViews im Beitrag <b>TreeView-Steuerelement mit Daten f&uuml;llen <\/b>(Shortlink 321) schon einmal beschrieben wurde, gibt es hierzu an dieser Stelle nur ein paar allgemeine Hinweise.<\/p>\n<p>Es ist normalerweise nicht n&ouml;tig, das TreeView beim Laden des Formulars vollst&auml;ndig zu bef&uuml;llen. Um die Knotenkennzeichner (+, -) richtig anzuzeigen, ist es lediglich erforderlich, eine Ebene weiter zu f&uuml;llen, als angezeigt wird.<\/p>\n<p>Das Bef&uuml;llen untergeordneter Ebenen braucht jedoch erst beim Ereignis <b>Node_Click <\/b>eines Knotens zu erfolgen. So ersparen Sie sich rekursive Prozeduren und zeitaufwendige Bef&uuml;llungen f&uuml;r &auml;ste, die nachher doch keiner aufklappt.<\/p>\n<p>Wenn Sie allerdings zum Beispiel bei einer Knotenhierarchie Summen anzeigen m&uuml;ssen, die sich aus den letzten Ebenen (Bl&auml;ttern) der Hierarchie ergeben, m&uuml;ssen Sie in den sauren Apfel der vollst&auml;ndigen Bef&uuml;llung bei&szlig;en. <\/p>\n<p><b>Offene Hierarchien<\/b><\/p>\n<p>Eine vollst&auml;ndige Hierarchietabelle l&auml;sst sich hier im Gegensatz zur abgeschlossenen Hierarchie nicht mit reinem ANSI-SQL erzeugen. Nat&uuml;rlich ist es m&ouml;glich, einen beliebig tiefen SELF JOIN anzulegen, aber die Tiefe ist eben statisch und nicht dynamisch. Wenn Sie zum Beispiel vier JOIN-Ebenen vorsehen, ist alles gut, solange es nicht mehr als vier Ebenen in den Daten gibt.<\/p>\n<p>Die offene Hierarchie kann aber dynamisch (durch neue Datens&auml;tze) theoretisch beliebig tief werden, woran sich Ihre Abfragen dann nicht automatisch anpassen k&ouml;nnen. Falls Sie eine tabellarische Darstellung f&uuml;r eine offene Hierarchie brauchen, bleibt Ihnen nichts anderes &uuml;brig, als mit einer Prozedur die aktuell gr&ouml;&szlig;te Schachtelungstiefe zu bestimmen und mit dieser Information den SQL-Ausdruck einer Abfrage dynamisch aufzubauen.<\/p>\n<p>Die Routine <b>Hdepth <\/b>im Modul <b>Hierarchietiefe <\/b>der Beispieldatenbank <b>DemoObjekthierarchie <\/b>enth&auml;lt den erforderlichen Code, um die maximale Tiefe einer Hierarchie zu bestimmen. Dabei ist vorausgesetzt, dass Sie diese Hierarchie gem&auml;&szlig; den Entwurfsempfehlungen im ersten Teil des Artikels aufgebaut haben, also eine Hierarchietabelle verwenden, die nur Beziehungen und keine Wurzelelemente enth&auml;lt.<\/p>\n<p>Die Routine <b>Hdepth<\/b> liefert Ihnen also die aktuelle maximale Tiefe Ihrer Hierarchie. Der Code verzichtet dabei auf Rekursion.<\/p>\n<p>Die Hilfsfunktion <b>GetLevel <\/b>(zu finden im gleichen Modul wie <b>Hdepth<\/b>) k&ouml;nnten Sie auch in einer Abfrage verwenden, um die Ebene eines Eintrags anzuzeigen. Im Gegensatz zur geschlossenen Hierarchie ergibt sich diese ja nicht aus der Tabellenherkunft, sondern wird durch die Anzahl der Vorfahren bis zur Wurzel errechnet.<\/p>\n<p><b>Exkurs: Grenzen der Rekursion und dynamisch erzeugter Abfragen<\/b><\/p>\n<p>Rekursionen legen ihre Zwischenergebnisse auf dem Stapelspeicher von VBA ab, was fr&uuml;her oder sp&auml;ter zum Laufzeitfehler <b>Stapel&uuml;berlauf<\/b> f&uuml;hren kann. In der Praxis wird diese Grenze selten &uuml;berschritten, aber speziell bei der Verwendung von Recordsets in Rekursionen kommt eine weitere, viel niedrigere H&uuml;rde ins Spiel. Auch wenn in Ihrem Code scheinbar nur ein Recordset Verwendung findet, werden tats&auml;chlich so viele Recordset-Objekte gleichzeitig ge&ouml;ffnet, wie Ihre Rekursion tief ist. Jedes Recordset verbraucht nun Verbindungen zur aktuellen Datenbank und zu den bezogenen Tabellen. Bei tiefen Hierarchien k&ouml;nnen Sie sich dann, lange bevor der Stapelspeicher &uuml;berl&auml;uft, den Fehler <b>Mehr Tabellen k&ouml;nnen nicht ge&ouml;ffnet werden <\/b>einfangen. Dieser kann bei Schachtelungstiefen in der Gr&ouml;&szlig;enordnung ab etwa 240 eintreten.<\/p>\n<p>Das dynamische Erzeugen hat ebenfalls seine Grenzen, die durch die Komplexit&auml;t der verwendeten Abfrage bestimmt werden. Bei der Abfrage <b>qVBAMaximaleTiefe<\/b> aus der Beispielanwendung <b>DemoObjekthierarchie <\/b>liegt die Grenze bei einer Hierarchietiefe von 31.<\/p>\n<p><b>Dynamisches SQL erzeugen<\/b><\/p>\n<p>Zur&uuml;ck zur Abfrage. Mit der Information &uuml;ber die maximale Tiefe k&ouml;nnen Sie nun eine Abfrage dynamisch erzeugen, die der einfachen kaskadischen Darstellung mehrerer 1:n-Beziehungen entspricht, wie sie in Bild 8 bei den geschlossenen Hierarchien gezeigt wurde.<\/p>\n<p>Die erforderliche Routine <b>ModifyQuery <\/b>finden Sie im Modul <b>Hierarchietiefe <\/b>der Beispieldatenbank <b>DemoObjekthierarchie<\/b>.<\/p>\n<p>Mit der Information &uuml;ber die maximale Tiefe k&ouml;nnten Sie nat&uuml;rlich auch den Code f&uuml;r eine <b>UNION<\/b>-Abfrage in Baumansicht, wie Sie sie weiter oben bei den geschlossenen Hierarchien gesehen haben, mit VBA aufbauen.<\/p>\n<p>Um an dieser Stelle etwas zu theoretisieren: Sobald Sie die maximale Schachtelungstiefe ermittelt haben und mit VBA &uuml;ber die M&ouml;glichkeit verf&uuml;gen, mit dieser Information SQL dynamisch zu erzeugen, k&ouml;nnen Sie eine offene Hierarchie im Grunde auch wie eine geschlossene behandeln. Die eingangs erw&auml;hnte diesbez&uuml;gliche Problematik beruht nur darauf, dass solche Mittel im urspr&uuml;nglichen ANSI-Standard nicht vorgesehen sind und daher gegen die rein mengenorientierten Spielregeln der 70er Jahre versto&szlig;en. Sobald Sie prozedurale Vorgehensweisen verf&uuml;gbar haben und Ihr Sportsgeist es zul&auml;sst, dass Sie sie auch anwenden, sind offene Hierarchien mit SQL problemlos zu handhaben.<\/p>\n<p><b>Objekthierarchien im Formular<\/b><\/p>\n<p>Die Darstellung der Hierarchie im Formular hat zwei prinzipielle Aufgaben zu erf&uuml;llen: Zum einen die Information &uuml;ber die Struktur als solche, zum anderen die Organisation der Objektdaten, die an den hierarchisch organisierten Schl&uuml;sselfeldern h&auml;ngen &#8211; in dieser Hinsicht ist eine Hierarchie&uuml;bersicht dann ein Navigationssteuerelement f&uuml;r Datens&auml;tze.<\/p>\n<p><b>Abh&auml;ngige Haupt-Unterformulare<\/b><\/p>\n<p>Bei geschlossenen Hierarchien ist das die g&auml;ngige Methode. Ein Einzelformular &#8222;Kunde&#8220; mit einem Endlosunterformular &#8222;Bestellungen&#8220; f&uuml;hrt &uuml;ber Navigationsbuttons in der Liste zu einer Einzelansicht des Formulars &#8222;Bestellungen&#8220; mit einer Liste der Artikel, in der man &uuml;ber Navigationsbuttons zu einer Einzelansicht des Formulars &#8222;Artikel&#8220; gelangt und so weiter.<\/p>\n<p>Das Vorgehen ist aus zwei Gr&uuml;nden ausgesprochen gut geeignet: Einerseits ist die Anzahl der Ebenen begrenzt und bekannt, sodass der Entwurf der n&ouml;tigen Formularhierarchie &uuml;berschaubar ist. Andererseits sehen Sie bereits am gew&auml;hlten Beispiel, dass die organisatorische Struktur der Formulare erheblich voneinander abweichen kann, da zu Kunden ganz andere Daten dargestellt werden m&uuml;ssen als zu Bestellungen oder Artikeln.<\/p>\n<p>Aufgrund der Tatsache, dass jeder Objekttyp ebenenspezifisch ist, wie&szlig; der Benutzer auch immer, wo er sich gerade befindet. Das Verfahren ist so verbreitet, dass sich Beispiele er&uuml;brigen.<\/p>\n<p>Bei offenen Hierarchien k&ouml;nnen hingegen Haupt- und Unterformular selbstabh&auml;ngig, also rekursiv sein. Dies deshalb, weil hier die Objekte aller Ebenen vom selben Typ sein und &uuml;ber dieselben Felder verf&uuml;gen m&uuml;ssen &#8211; das folgt allein schon aus der zugrunde liegenden Tabellenstruktur.<\/p>\n<p>Das bedeutet, dass Sie nur zwei Formulare f&uuml;r beliebig viele Ebenen ben&ouml;tigen und bei Navigation vom Endlosunterformular aus im Hauptformular zum betreffenden Datensatz navigieren.<\/p>\n<p>Au&szlig;er als Notnagel ist das Verfahren hier aber dennoch wenig tauglich: Gerade bei offenen Hierarchien ist die Visualisierung der Gesamt&uuml;bersicht (Baum) ergonomisch besonders wichtig und obendrein fehlt die Orientierungshilfe durch den Objekttyp.<\/p>\n<p>Um das Beispiel Windows-Explorer zu bem&uuml;hen: Ein Ordner ist ein Ordner ist ein Ordner. Da ist intuitiv nicht klar, auf welcher Ebene Sie sich gerade befinden.<\/p>\n<p>Wie das Prinzip aussieht, soll Ihnen aber dennoch nicht vorenthalten werden.<\/p>\n<p>In Bild 13 sehen Sie ein solches Formular auf Ebene 1, Datensatz 1. In der Liste ist der zweite Button gedr&uuml;ckt, sodass das Formular gleich zu Ebene 2, Datensatz 2 navigieren und im Unterformular dessen untergeordnete Datens&auml;tze anzeigen wird.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic013_opt.jpeg\" alt=\"pic013.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 13: Rekursives Formular auf Ebene 1<\/span><\/b><\/p>\n<p>Den dahinterstehenden Code finden Sie im Modul des Formulars <b>tblHierarchieMainAIU <\/b>in der Beispieldatenbank <b>DemoObjekthierarchie<\/b>.<\/p>\n<p>Wie Sie dem Code entnehmen, ist das Verhalten so gesteuert, dass das Recordset des Hauptformulars immer nur ein Geschwisterb&uuml;ndel enth&auml;lt, wobei der Ausgangsdatensatz der aktive ist.<\/p>\n<p>Sie gehen zum Beispiel von Datensatz 1 mit den Kindern 11 bis 15 aus (siehe Bild 13) und aktivieren Kind 12 mit der Pfeil-Schaltfl&auml;che. Danach sehen Sie, wie nicht nur der angezeigte Hauptdatensatz auf Kind 12 wechselt, sondern das Recordset auch &uuml;ber f&uuml;nf S&auml;tze verf&uuml;gt: Au&szlig;er Kind 12 sind auch alle seine Geschwister, Kind 11 und Kind 13 bis 15 ansteuerbar.<\/p>\n<p>Mit dem Nach-Oben-Button im Hauptformular machen Sie den Vater des momentan angezeigten Datensatzes zum aktiven und k&ouml;nnen obendrein zu dessen Geschwistern navigieren.<\/p>\n<p>Vom ausgehenden Datensatz aus hei&szlig;t das: Gehe zu meinem Vater und mache aber auch alle Onkel verf&uuml;gbar.<\/p>\n<p>Das Vorgehen entspricht in etwa einer Navigation in Windows-Ordnern ohne Verwendung der Ordnerliste.<\/p>\n<p><b>Treeview als Navigator<\/b><\/p>\n<p>Aus vielen Programmen ist man die Baumansicht in Kombination mit einer Listenansicht gewohnt. Im Datenbankbereich bietet sich hier etwas ganz anderes an. Statt einer Listenansicht verwendet man das TreeView am besten zusammen mit (Unter-)Formularen.<\/p>\n<p>Dem TreeView kommen hier die eingangs erw&auml;hnten beiden Aufgaben zu, die Zusammenh&auml;nge zu visualisieren und die Navigation bereitzustellen. Die Grundidee ist hierbei, bei einem <b>Node_Click<\/b>-Ereignis gegebenenfalls das Herkunftsobjekt eines leeren Unterformularcontainers zu setzen (falls Sie verschiedene Formulare verwenden) und den Datensatz des Unterformulars auf das Element des angeklickten Knotens einzustellen.<\/p>\n<p><b>Feste Hierarchie<\/b><\/p>\n<p>Beginnen wir wieder mit einer geschlossenen Hierarchie. Die Elemente der ersten Ebene des Baumes seien Kunden, repr&auml;sentiert durch ihren Namen, der zweiten die Bestellungen, ausgewiesen zum Beispiel durch das Bestelldatum, die dritte Ebene schlie&szlig;lich Artikelnamen.<\/p>\n<p>Das Bef&uuml;llen des TreeViews ist rekursionsfrei einfach zu realisieren. Sie f&uuml;gen erst alle Kunden als Knoten derselben Ebene an. Vergeben Sie dabei als Knotenschl&uuml;ssel (<b>Node.Key<\/b>) zum Beispiel &#8222;K&#8220; plus den Wert des Prim&auml;rschl&uuml;ssels.<\/p>\n<p>Um die Bestellungen anzuf&uuml;gen, die diesen Kundenschl&uuml;ssel als Fremdschl&uuml;ssel f&uuml;hren, durchlaufen Sie die Knoten in einer Schleife.<\/p>\n<p>Pr&uuml;fen Sie auf <b>Left$(node.Key)=&#8220;K&#8220; <\/b>und verwenden Sie <b>Mid$(node.Key, 2) <\/b>&#8211; das ist der Prim&auml;rschl&uuml;ssel des Kunden &#8211; als Kriterium f&uuml;r einen SQL-Ausdruck, mit dem Sie die Bestellungen abfragen.<\/p>\n<p>F&uuml;gen Sie nun in jedem Kundenknoten die Bestellungen als Kindknoten mit dem Schl&uuml;ssel &#8222;B&#8220; plus den Prim&auml;rschl&uuml;ssel der Bestelltabelle an. Durchlaufen Sie nun die Knoten mit einer Pr&uuml;fung auf <b>Left$(node.Key)=&#8220;B&#8220; <\/b>und verwenden Sie <b>Mid$(node.Key, 2)<\/b>, um die Fremdschl&uuml;ssel f&uuml;r die n&auml;chste Ebene zu bekommen und so weiter.<\/p>\n<p>Das Verfahren l&auml;sst sich noch effizienter gestalten, aus Platzgr&uuml;nden beschr&auml;nkt sich dieser Artikel aber auf die dargestellte, einfach verst&auml;ndliche Variante.<\/p>\n<p><b>Offene Hierarchie<\/b><\/p>\n<p>Das Bef&uuml;llen eines TreeViews mit einer offenen Hierarchie ist etwas anspruchsvoller. Wie schon oben erw&auml;hnt, finden Sie eine Anleitung dazu im Beitrag <b>TreeView-Steuerelement mit Daten f&uuml;llen <\/b>(Shortlink 321).<\/p>\n<p>In der Routine <b>TreeViewFill <\/b>im Modul des Formulars <b>frmHierarchieAIU <\/b>der Beispieldatenbank <b>DemoObjekthierarchie <\/b>finden Sie einen iterativen Bef&uuml;llungscode f&uuml;r das hier vorgestellte Beispiel, mit dem Sie zum rekursiven Bef&uuml;llungscode aus oben genanntem Beitrag noch etwas hinzulernen.<\/p>\n<p>Nun zum eigentlichen Thema dieses Abschnitts: Der Baum als Navigationselement. In Bild 14 sehen Sie das Ergebnis eines solchen Formulars.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic014_opt.jpeg\" alt=\"pic014.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 14: Treeview mit Subform in der Formularansicht<\/span><\/b><\/p>\n<p>Den Code, der bei der Auswahl eines Knotens rechts im Formular den passenden Datensatz l&auml;dt, lernen Sie dann im folgenden Abschnitten kennen.<\/p>\n<p>Zu Beginn wird der leere Objektrahmen mit einem Formular versehen. Sie k&ouml;nnen hier per Code beliebig viele fertig vorbereitete Formulare abwechselnd laden.<\/p>\n<p>Danach wird das Unterformularobjekt mit einer SQL-Datenquelle (<b>RecordSource<\/b>) bef&uuml;llt, die die erforderlichen Felder f&uuml;r den gebundenen Betrieb bereitstellt, aber noch keine Datens&auml;tze enth&auml;lt. Datens&auml;tze werden erst beim Klick auf einen Knoten geladen:<\/p>\n<pre>Private Sub Form_Load()\r\n    Me.fsbDaten.SourceObject = _\r\n    \"frmHierarchieDatenAIU&euro;\r\n    Me.fsbDaten.Form.RecordSource = _\r\n    \"SELECT tblKnoten.idItem, &quot; _\r\n    &amp; &quot;tblKnoten.dtName \" _\r\n    &amp; \"FROM tblKnoten \" _\r\n    &amp; \"WHERE tblKnoten.idItem Is Null&euro;\r\n    TreeViewFill\r\n    Me.TV5.Nodes(1).Expanded = True\r\n    Me.TV5.Nodes(1).Selected = True\r\n    End Sub<\/pre>\n<p>Durch das Vorgehen im folgenden Listing enth&auml;lt der Datenbereich immer genau den einen ausgew&auml;hlten Datensatz. Damit k&ouml;nnen Sie nun eine offene Hierarchie beliebiger Tiefe verwalten.<\/p>\n<p>Sie k&ouml;nnten als kr&ouml;nenden Abschluss allerdings noch die Prinzipien der Baumnavigation und des rekursiven Formulars miteinander kreuzen.<\/p>\n<pre>Private Sub TV5_NodeClick(ByVal Node As Object)\r\n    Dim SQL As String\r\n    Dim id As Long\r\n    If Left$(Node.Key, 1) = \"R&euro; Then\r\n        SQL = \"SELECT tblKnoten.idItem, \" _\r\n        &amp; \"tblKnoten.dtName FROM tblKnoten\" _\r\n        &amp; \" WHERE tblKnoten.idItem Is Null&euro;\r\n    End If\r\n    If Left$(Node.Key, 1) = \"K&euro; Then\r\n        id = Mid$(Node.Key, 2)\r\n        SQL = \"SELECT tblKnoten.idItem, \" _\r\n        &amp; \"tblKnoten.dtName \" &amp; _\r\n        \"FROM tblKnoten \" &amp; _\r\n        \"WHERE tblKnoten.idItem=&euro; &amp; id\r\n    End If\r\n    Me!fsbDaten.Form.RecordSource = SQL\r\n    Me!txtPath.Value = Node.FullPath\r\nEnd Sub<\/pre>\n<p>Dazu w&uuml;rden Sie unter dem Datenbereich des Baumformulars noch eine zus&auml;tzliche Liste der direkten Kinder des dargestellten Hauptdatensatzes anzeigen.<\/p>\n<p>Der Vorteil ist in erster Linie der gewonnene zus&auml;tzliche Platz. W&auml;hrend der Baum allenfalls die Namen der Kinder anzeigt, k&ouml;nnen Sie im Endlosformular noch zus&auml;tzliche Kinddaten liefern.<\/p>\n<p>Das Ganze sieht dann aus wie in Bild 15. Die Navigationsbuttons aus dem rekursiven Formular sind hier nat&uuml;rlich obsolet, da das Navigieren bereits das TreeView &uuml;bernimmt.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Hierarchien-web-images\/pic015_opt.jpeg\" alt=\"pic015.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 15: Baumformular mit zus&auml;tzlicher Kinderliste<\/span><\/b><\/p>\n<p><b>Zusammenfassung<\/b><\/p>\n<p>Verschiedene Hierarchietypen erfordern f&uuml;r eine ergonomische Anzeige unterschiedliche Darstellungsweisen.<\/p>\n<p>Das R&uuml;stzeug, diese treffsicher zu unterscheiden, und die beschriebenen Anregungen, wie Sie mit der Darstellung verfahren k&ouml;nnen, werden Ihnen die Arbeit in der Praxis erleichtern.<\/p>\n<pre>Hierarchische Liste mit\r\nUnion-Abfrage<\/pre>\n<p><b><span style=\"color:darkgrey\">Datenfeldern<\/span><\/b><\/p>\n<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>DemoBegriffshierarchie.mdb<\/p>\n<p>DemoObjekthierarchie.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/D2EEDC79-E6C0-486A-A499-8C228DAC8B95\/aiu_615.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hierarchien sind das A und O bei der Datenbankentwicklung. Sie im Datenmodell abzubilden und diese in Formularen anzuzeigen, sind jedoch zwei verschiedene Welten. Da es aber ohne passende Formulare zur Eingabe und Bearbeitung auch hierarchischer Daten nicht geht, stellen wir Ihnen in diesem Beitrag verschiedene M&ouml;glichkeiten f&uuml;r die Abfrage und Darstellung der unterschiedlichen Hierarchieformen vor.<\/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":[662008,66042008,44000029,44000021],"tags":[],"class_list":["post-55000615","post","type-post","status-publish","format-standard","hentry","category-662008","category-66042008","category-Abfragetechnik_und_SQL","category-Tabellen_und_Datenmodellierung"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Hierarchien visualisieren - 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\/Hierarchien_visualisieren\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Hierarchien visualisieren\" \/>\n<meta property=\"og:description\" content=\"Hierarchien sind das A und O bei der Datenbankentwicklung. Sie im Datenmodell abzubilden und diese in Formularen anzuzeigen, sind jedoch zwei verschiedene Welten. Da es aber ohne passende Formulare zur Eingabe und Bearbeitung auch hierarchischer Daten nicht geht, stellen wir Ihnen in diesem Beitrag verschiedene M&ouml;glichkeiten f&uuml;r die Abfrage und Darstellung der unterschiedlichen Hierarchieformen vor.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2021-03-22T16:19:39+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg09.met.vgwort.de\/na\/480f5043e4864c79ab00b2b24e81846e\" \/>\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=\"24\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Hierarchien visualisieren\",\"datePublished\":\"2021-03-22T16:19:39+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/\"},\"wordCount\":4433,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/480f5043e4864c79ab00b2b24e81846e\",\"articleSection\":[\"2008\",\"4\\\/2008\",\"Abfragetechnik und SQL\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/\",\"name\":\"Hierarchien visualisieren - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/480f5043e4864c79ab00b2b24e81846e\",\"datePublished\":\"2021-03-22T16:19:39+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/480f5043e4864c79ab00b2b24e81846e\",\"contentUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/480f5043e4864c79ab00b2b24e81846e\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Hierarchien_visualisieren\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Hierarchien visualisieren\"}]},{\"@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":"Hierarchien visualisieren - 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\/Hierarchien_visualisieren\/","og_locale":"de_DE","og_type":"article","og_title":"Hierarchien visualisieren","og_description":"Hierarchien sind das A und O bei der Datenbankentwicklung. Sie im Datenmodell abzubilden und diese in Formularen anzuzeigen, sind jedoch zwei verschiedene Welten. Da es aber ohne passende Formulare zur Eingabe und Bearbeitung auch hierarchischer Daten nicht geht, stellen wir Ihnen in diesem Beitrag verschiedene M&ouml;glichkeiten f&uuml;r die Abfrage und Darstellung der unterschiedlichen Hierarchieformen vor.","og_url":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/","og_site_name":"Access im Unternehmen","article_published_time":"2021-03-22T16:19:39+00:00","og_image":[{"url":"http:\/\/vg09.met.vgwort.de\/na\/480f5043e4864c79ab00b2b24e81846e","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"24\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Hierarchien visualisieren","datePublished":"2021-03-22T16:19:39+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/"},"wordCount":4433,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/480f5043e4864c79ab00b2b24e81846e","articleSection":["2008","4\/2008","Abfragetechnik und SQL","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/","url":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/","name":"Hierarchien visualisieren - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/480f5043e4864c79ab00b2b24e81846e","datePublished":"2021-03-22T16:19:39+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#primaryimage","url":"http:\/\/vg09.met.vgwort.de\/na\/480f5043e4864c79ab00b2b24e81846e","contentUrl":"http:\/\/vg09.met.vgwort.de\/na\/480f5043e4864c79ab00b2b24e81846e"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Hierarchien_visualisieren\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Hierarchien visualisieren"}]},{"@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\/55000615","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=55000615"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000615\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}