{"id":55000923,"date":"2014-02-01T00:00:00","date_gmt":"2020-05-22T21:19:13","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=923"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Stuecklisten_Teil_I","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/","title":{"rendered":"St&uuml;cklisten, Teil I"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/ac3a102298f54458b887e18af009bc73\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>St&uuml;cklisten dienen dazu, die Einzelteile eines Objekts strukturiert darzustellen. Strukturiert bedeutet dabei, dass die Einzelteile jeweils zu Baugruppen zusammengefasst werden. Ein Objekt besteht also aus Baugruppen und\/oder Einzelteilen, wobei jede Baugruppe wieder aus Baugruppen und\/oder Einzelteilen besteht &#8211; bis am Ende jede Baugruppe in ihre Einzelteile aufgel&ouml;st ist. Einzelteile sind die kleinsten Einheiten in der St&uuml;ckliste, sie k&ouml;nnen nicht weiter aufgeteilt werden.Dieser Beitrag soll zeigen, wie Sie St&uuml;cklisten mit Access verwalten. Dabei spielt das TreeView-Steuerelement eine gro&szlig;e Rolle.<\/b><\/p>\n<p>Die St&uuml;ckliste kann dazu f&uuml;r verschiedene Zwecke genutzt werden: Sie k&ouml;nnen daraus zum Beispiel entnehmen, welche Mengen der verschiedenen Einzelteile ben&ouml;tigt werden. Dies ist sowohl f&uuml;r die Beschaffung der ben&ouml;tigten Einzelteile wichtig als auch f&uuml;r die Kalkulation der Materialkosten.<\/p>\n<p><b>Datenmodell<\/b><\/p>\n<p>Das Datenmodell der L&ouml;sung sieht im &uuml;berblick wie in Bild 1 aus. Die Tabelle <b>tblBaugruppen <\/b>enth&auml;lt alle Baugruppen, f&uuml;r die in unserem einfach gehaltenen Ansatz nur der Name angegeben werden soll. Die Tabelle enth&auml;lt lediglich die beiden Felder <b>BaugruppeID <\/b>als Prim&auml;rschl&uuml;sselfeld sowie das Feld <b>Baugruppe <\/b>zur Eingabe einer Bezeichnung f&uuml;r die Baugruppe. Diese Tabelle kommt noch ein zweites Mal in der &uuml;bersicht des Datenmodells vor. Dies hat den Hintergrund, dass Sie jeder Baugruppe weitere Baugruppen unterordnen k&ouml;nnen. Eine Baugruppe besteht ja nicht direkt lediglich aus Einzelteilen, sondern kann auch andere aus Einzelteilen oder auch Baugruppen zusammengesetzte Baugruppen enthalten.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_001.png\" alt=\"&uuml;bersicht des Datenmodells f&uuml;r die St&uuml;ckliste\" width=\"650\" height=\"310,4363\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: &uuml;bersicht des Datenmodells f&uuml;r die St&uuml;ckliste<\/span><\/b><\/p>\n<p>Die Abbildung zeigt die Tabelle <b>tblBaugruppen<\/b> ein zweites Mal, damit wir die Beziehung zwischen zwei Baugruppen abbilden k&ouml;nnen.<\/p>\n<p><b>Verkn&uuml;pfung zwischen Baugruppen<\/b><\/p>\n<p>Dies geschieht n&auml;mlich durch die Verkn&uuml;pfungstabelle <b>tblBaugruppenzuordnungen<\/b> (s. Bild 2). Sie enth&auml;lt die Felder BaugruppenzuordnungID (als Prim&auml;rschl&uuml;sselfeld), <b>BaugruppeVaterID <\/b>zur Angabe der &uuml;bergeordneten Baugruppe aus der Tabelle <b>tblBaugruppen<\/b>, das Feld <b>BaugruppeKindID <\/b>zur Angabe der untergeordneten Baugruppe sowie das Feld <b>Menge<\/b>.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_002.png\" alt=\"Entwurf der Tabelle tblBaugruppenzuordnungen\" width=\"650\" height=\"379,3038\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Entwurf der Tabelle tblBaugruppenzuordnungen<\/span><\/b><\/p>\n<p>Es kann ja auch sein, dass eine Baugruppe gleich mehrmals einer anderen Baugruppe zugeordnet werden soll (zum Beispiel vier Reifen zu einem Auto). Die gew&uuml;nschte Anzahl tragen Sie dann in das Feld <b>Menge <\/b>ein.<\/p>\n<p>F&uuml;r dieses Feld legen wir au&szlig;erdem den Wert <b>1 <\/b>als Standardwert fest &#8211; dieser muss dann beim Anlegen gegebenenfalls angepasst werden.<\/p>\n<p>Au&szlig;erdem soll die Tabellen einen aus den beiden Feldern <b>BaugruppeVaterID <\/b>und <b>BaugruppeKindID <\/b>zusammengesetzten eindeutigen Index besitzen. Auf diese Weise verhindern wir, dass eine Kombination aus zwei Baugruppen mehrfach angelegt wird &#8211; zu diesem Zweck haben wir ja das Feld Menge hinzugef&uuml;gt.<\/p>\n<p>Weiter im Datenmodell: Neben den Baugruppen gibt es eine Tabelle mit den Daten der Einzelteile. Sie hei&szlig;t <b>tblEinzelteile <\/b>und ist in Bild 3 abgebildet.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_003.png\" alt=\"Entwurf der Tabelle tblEinzelteile\" width=\"575\" height=\"170,8571\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Entwurf der Tabelle tblEinzelteile<\/span><\/b><\/p>\n<p><b>Wo sind die Projekte<\/b><\/p>\n<p>Irgendwann f&uuml;hren alle Baugruppen und\/oder Einzelteile zu einem vollst&auml;ndigen Projekt oder Produkt. Warum also gibt es in der Datenbank keine Tabelle f&uuml;r solche Elemente Wenn Sie m&ouml;chten, k&ouml;nnen Sie nat&uuml;rlich eine solche hinzuf&uuml;gen. Allerdings ist schon jede einzelne Baugruppe ein Produkt f&uuml;r sich, und eigentlich auch jedes Einzelteil. Machen wir es uns also einfach und f&uuml;gen einfach den beiden Tabellen <b>tblBaugruppen<\/b> und <b>tblEinzelteile <\/b>ein <b>Ja\/Nein<\/b>-Feld namens <b>IstProdukt <\/b>hinzu, mit dem Sie festlegen k&ouml;nnen, ob ein solches Element nicht nur Bestandteil einer Baugruppe sein kann, sondern gleichzeitig ein Produkt. Wozu aber ben&ouml;tigen wir solche eine Unterscheidung Weil wir auf irgendeine Weise kennzeichnen wollen, welche Elemente als Hauptelemente im TreeView zur Darstellung des Aufbaus von Bauteilen dienen sollen.<\/p>\n<p><b>Beziehung zwischen Baugruppen und Einzelteilen<\/b><\/p>\n<p>Um die Einzelteile den Baugruppen zuzuordnen, ben&ouml;tigen wir wiederum eine Verkn&uuml;pfungstabelle zur Herstellung einer m:n-Beziehung. Diese hei&szlig;t <b>tblBaugruppenEinzelteile <\/b>und enth&auml;lt das Prim&auml;rschl&uuml;sselfeld <b>BaugruppeEinzelteilID<\/b>, das Fremdschl&uuml;sselfeld <b>BaugruppeID <\/b>zum Festlegen der Baugruppe aus der Tabelle <b>tblBaugruppen<\/b>, das Fremdschl&uuml;sselfeld <b>EinzelteilID <\/b>zum Festlegen des Einzelteils aus der Tabelle <b>tblEinzelteile <\/b>und das Feld <b>Menge <\/b>zur Angabe der Anzahl der Einzelteile.<\/p>\n<p>Auch f&uuml;r das Feld <b>Menge <\/b>dieser Tabelle stellen wir <b>1 <\/b>als <b>Standardwert <\/b>ein, au&szlig;erdem legen wir f&uuml;r die beiden Felder <b>BaugruppeID <\/b>und <b>EinzelteilID <\/b>einen zusammengesetzten, eindeutigen Index fest (s. Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_004.png\" alt=\"Entwurf der Tabelle tblBaugruppenEinzelteile\" width=\"650\" height=\"396,8952\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Entwurf der Tabelle tblBaugruppenEinzelteile<\/span><\/b><\/p>\n<p>Die Tabelle <b>tblEinzelteilKategorien <\/b>schlie&szlig;lich enth&auml;lt verschiedene Kategorien f&uuml;r die Einzelteile. Diese Tabelle hat den Hinterrgrund, dass vielleicht sp&auml;ter einmal die Einzelteile verschiedener Kategorien unterschiedlich rabattiert werden &#8211; gegebenenfalls auch noch in Abh&auml;ngigkeit vom jeweiligen Kunden. Die Tabelle enth&auml;lt die beiden Felder <b>EinzelteilKategorieID <\/b>(als Prim&auml;rschl&uuml;sselfeld) und <b>Einzelteilkategorie<\/b>.<\/p>\n<p>Die Tabelle <b>tblEinzelteile <\/b>ist &uuml;ber das Feld <b>EinzelteilkategorieID <\/b>mit dieser Tabelle verkn&uuml;pft.<\/p>\n<p><b>Darstellung der Baugruppen und Einzelteile<\/b><\/p>\n<p>Die L&ouml;sung soll verschiedene Darstellungen erm&ouml;glichen. Zun&auml;chst einmal wollen wir eine einfache M&ouml;glichkeit zur Eingabe der Einzelteile schaffen. Dazu legen Sie ein neues Formular namens <b>frmEinzelteile <\/b>an, das ein Unterformular <b>sfmEinzelteile <\/b>enth&auml;lt. Das Unterformular soll alle Einzelteile enthalten, das Hauptformular das aktuell im Unterformular ausgew&auml;hlte Einzelteil. Das Unterformular statten wir au&szlig;erdem mit einer M&ouml;glichkeit zum Filtern nach verschiedenen Kriterien aus.<\/p>\n<p>In der Entwurfsansicht sieht das Unterformular wie in Bild 5 aus. Das Feld <b>EinzelteilkategorieID <\/b>haben wir &uuml;ber den Kontextmen&uuml;-Eintrag <b>&auml;ndern zu|Kombinationsfeld <\/b>in ein Kombinationsfeld umgewandelt, damit die Eintr&auml;ge der Tabelle <b>tblEinzelteilkategorien <\/b>direkt nachgeschlagen werden k&ouml;nnen. Dazu haben wir die Eigenschaft <b>Datensatzherkunft <\/b>auf den folgenden Ausdruck eingestellt:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_005.png\" alt=\"Aufbau des Unterformulars sfmEinzelteile\" width=\"575\" height=\"293,4718\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Aufbau des Unterformulars sfmEinzelteile<\/span><\/b><\/p>\n<pre>SELECT EinzelteilkategorieID, Einzelteilkategorie FROM tblEinzelteilkategorien \r\nORDER BY Einzelteilkategorie;<\/pre>\n<p>Die Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>erhalten die Werte <b>2 <\/b>und <b>0cm<\/b>. Das Formular erh&auml;lt f&uuml;r die Eigenschaft <b>Standardansicht <\/b>den Wert <b>Datenblatt<\/b>.<\/p>\n<p><b>Haupt- und Unterformular synchronisieren<\/b><\/p>\n<p>Damit Haupt- und Unterformular die gleichen Datens&auml;tze markieren, muss beim Laden des Hauptformulars die folgende Prozedur ausgef&uuml;hrt werden. Diese stellt das Recordset des Hauptformulars auf das Recordset des Unterformulars ein:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n    <span style=\"color:blue;\">Set<\/span> Me.Recordset =  Me!sfmEinzelteile.Form.Recordset\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b>Einzelteilkategorie ausw&auml;hlen<\/b><\/p>\n<p>Damit neben der Auswahl der Datens&auml;tze der Tabelle <b>tblEinzelteilkategorien <\/b>im Hauptformular nicht nur die bestehenden Eintr&auml;ge gew&auml;hlt, sondern auch direkt neue Eintr&auml;ge eingef&uuml;gt werden k&ouml;nnen, f&uuml;gen Sie dem Kombinationsfeld eine Prozedur hinzu, die durch das Ereignis <b>Bei nicht in Liste <\/b>ausgel&ouml;st wird (s. Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cboEinzelteilkategorieID_NotInList(NewData<span style=\"color:blue;\"> As String<\/span>, Response<span style=\"color:blue;\"> As Integer<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">MsgBox<\/span>(\"Kategorie ''\" & NewData & \"'' anlegen\", vbYesNo) = vbYes<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n        db.Execute \"INSERT INTO tblEinzelteilkategorien(Einzelteilkategorie) VALUES(''\" \r\n            & NewData & \"'')\", dbFailOnError\r\n        Response = acDataErrAdded\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Hinzuf&uuml;gen neuer Eintr&auml;ge in die Tabelle tblEinzelteilkategorien &uuml;ber das Kombinationsfeld<\/span><\/b><\/p>\n<p>Diese Prozedur fragt den Benutzer bei der Eingabe eines noch nicht vorhandenen Wertes, ob ein neuer Eintrag in der Tabelle <b>tblEinzelteilkategorien <\/b>angelegt werden soll. Falls ja, legt die Prozedur den Datensatz gleich mit einer entsprechenden SQL-<b>INSERT INTO<\/b>-Anweisung an. Auf diese Weise sparen wir uns an dieser Stelle ein extra Formular f&uuml;r die Verwaltung der Kategorien (dieses w&uuml;rde notwendig, wenn Sie einmal Kategorien &auml;ndern oder l&ouml;schen wollen). <\/p>\n<p><b>Baugruppen verwalten<\/b><\/p>\n<p>F&uuml;r die Verwaltung der Baugruppen wollen wir ein &auml;hnliches Formular wie f&uuml;r die Einzelteile anlegen. Wir ben&ouml;tigen also wieder ein Hauptformular, diesmal namens <b>frmBaugruppen<\/b>, sowie ein Unterformular namens <b>sfmBaugruppen<\/b>.<\/p>\n<p>Allerdings weist die Tabelle <b>tblBaugruppen <\/b>im aktuellen Zustand mit <b>Baugruppe <\/b>und <b>IstProdukt <\/b>ohnehin nur zwei Felder mit Gesch&auml;ftsdaten auf. Wir m&uuml;ssen also nicht unbedingt ein Hauptformular mit den Detaildaten und ein Unterformular mit einer Listenansicht erstellen. Eine Liste im Unterformular reicht v&ouml;llig aus, das Hauptformular soll nur weitere Steuerelemente wie etwa die <b>OK<\/b>-Schaltfl&auml;che nachliefern. Im Entwurf sieht das Formular wie in Bild 6 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_006.png\" alt=\"Haupt- und Unterformular zur Darstellung von Baugruppen\" width=\"350\" height=\"238,9706\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Haupt- und Unterformular zur Darstellung von Baugruppen<\/span><\/b><\/p>\n<p>Wenn Sie nun in die Formularansicht des Formulars <b>frmBaugruppen<\/b> wechseln, erwartet Sie der Anblick auf Bild 7.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_007.png\" alt=\"Bearbeiten von Baugruppen in der Formularansicht mit einem Unterformular in der Datenblattansicht\" width=\"350\" height=\"192,6471\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Bearbeiten von Baugruppen in der Formularansicht mit einem Unterformular in der Datenblattansicht<\/span><\/b><\/p>\n<p><b>Baugruppen und Einzelteile im TreeView<\/b><\/p>\n<p>Nun wenden wir uns interessanteren Themen zu: zum Beispiel dem Formular <b>frm-StuecklisteTreeView<\/b>, welches ein <b>TreeView<\/b>-Steuerelement zur hierarchischen Anzeige der Baugruppen und Einzelteile enth&auml;lt.<\/p>\n<p>Statten Sie dazu ein neues Formular namens <b>frmStuecklisteTreeView <\/b>zun&auml;chst mit einem <b>TreeView<\/b>-Steuerelement namens <b>ctlTreeView <\/b>sowie mit einer Schaltfl&auml;che namens <b>cmdOK <\/b>aus.<\/p>\n<p>Stellen Sie die Eigenschaften <b>Horizontaler Anker <\/b>und <b>Vertikaler Anker <\/b>f&uuml;r das <b>TreeView<\/b>-Steuerelement jeweils auf <b>Beide <\/b>ein (s. Bild 8). F&uuml;r die Eigenschaft <b>Vertikaler Anker <\/b>der Schaltfl&auml;che <b>cmdOK <\/b>legen Sie den Wert <b>Unten <\/b>fest.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_008.png\" alt=\"Verankern des TreeView-Steuerelements, sodass es sowohl vertikal als auch horizontal angepasst wird\" width=\"450\" height=\"420,2679\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Verankern des TreeView-Steuerelements, sodass es sowohl vertikal als auch horizontal angepasst wird<\/span><\/b><\/p>\n<p>Auf diese Weise passen sich <b>TreeView<\/b>-Steuerelement und Schaltfl&auml;che an die Ausma&szlig;e des Formulars an &#8211; allerdings stehen diese Eigenschaften erst ab Access 2007 zur Verf&uuml;gung. Sollten Sie noch eine &auml;ltere Access-Version nutzen &#8211; dies w&auml;re ein Grund zum Wechseln.<\/p>\n<p>Legen Sie au&szlig;erdem ein <b>ImageList<\/b>-Steuerelement an, denn wir wollen die Eintr&auml;ge des <b>TreeView<\/b>-Steuerelements mit entsprechenden Icons etwas aufh&uuml;bschen. Dieses Steuerelement soll den Namen <b>ctlImageList <\/b>erhalten.<\/p>\n<p><b>ImageList-Steuerelement f&uuml;llen<\/b><\/p>\n<p>Das <b>ImageList<\/b>-Steuerelement m&uuml;ssen wir zun&auml;chst mit den ben&ouml;tigten Bildern f&uuml;llen. Wir ben&ouml;tigen eines f&uuml;r das Root-Element des <b>TreeView<\/b>-Steuerelements, eines f&uuml;r ein Projekt &#8211; in diesem Fall ein Hierarchie-Icon, eines f&uuml;r eine Baugruppe (hier durch mehrere Zahnr&auml;der abgebildet) sowie ein Icon f&uuml;r ein Einzelteil, hier ein einzelnes Zahnrad. Damit diese wie in Bild 9 in das <b>ImageList<\/b>-Steuerelement gelangen, f&uuml;gen Sie entweder selbst geeignete Bilder hinzu oder erledigen dies per VBA-Code.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_009.png\" alt=\"Hinzuf&uuml;gen der ben&ouml;tigten Icons f&uuml;r das TreeView-Steuerelement\" width=\"300\" height=\"224,8139\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Hinzuf&uuml;gen der ben&ouml;tigten Icons f&uuml;r das TreeView-Steuerelement<\/span><\/b><\/p>\n<p>In unserem Fall war das notwendig, da das <b>ImageList<\/b>-Steuerelement nicht mit dem Bildformat zurechtkam. Also lesen wir die Bilder erst in ein <b>StdPicture<\/b>-Objekt ein und speichern diese dann im <b>ImageList<\/b>-Steuerelement.<\/p>\n<p>Eine einfache Prozedur, um dies zu erledigen, finden Sie im Modul <b>mdl-ImageListFuellen <\/b>beziehungsweise in Listing 2.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ImageListFuellen(strFormular<span style=\"color:blue;\"> As String<\/span>, strImageList<span style=\"color:blue;\"> As String<\/span>, _\r\n        ParamArray strImages()<span style=\"color:blue;\"> As Variant<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>objPicture<span style=\"color:blue;\"> As <\/span>stdole.StdPicture\r\n    <span style=\"color:blue;\">Dim <\/span>strImage<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strImageName<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>objNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>objImageList<span style=\"color:blue;\"> As <\/span>MSComctlLib.ImageList\r\n    <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>frm<span style=\"color:blue;\"> As <\/span>Form\r\n    DoCmd.OpenForm strFormular, acDesign\r\n    <span style=\"color:blue;\">Set<\/span> frm = Forms(strFormular)\r\n    <span style=\"color:blue;\">Set<\/span> objImageList = frm(strImageList).Object\r\n    For i = <span style=\"color:blue;\">LBound<\/span>(strImages) To <span style=\"color:blue;\">UBound<\/span>(strImages)\r\n        strImage = strImages(i)\r\n        strImageName = <span style=\"color:blue;\">Mid<\/span>(strImage, <span style=\"color:blue;\">InStrRev<\/span>(strImage, \"\\\") + 1)\r\n        strImageName = <span style=\"color:blue;\">Left<\/span>(strImageName, <span style=\"color:blue;\">InStrRev<\/span>(strImageName, \".\") - 1)\r\n        <span style=\"color:blue;\">Set<\/span> objPicture = mdlOGL0713.LoadPictureGDIP(strImage)\r\n        objImageList.ListImages.Add , strImageName, objPicture\r\n    <span style=\"color:blue;\">Next<\/span> i\r\n    DoCmd.Close acForm, frm.Name\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Prozedur zum F&uuml;llen des ImageList-Steuerelements mit Bilddateien<\/span><\/b><\/p>\n<p>Der Aufruf dieser Prozedur sieht etwa wie folgt aus:<\/p>\n<pre>ImageListFuellen  \"frmStuecklisteTreeView\",  \"ctlImageList\",  \"c:\\gearwheel.png\", _\r\n\"c:\\gearwheels.png\",  \"c:\\home.png\",  \"c:\\elements_hierarchy.png\"<\/pre>\n<p>Die Prozedur erwartet den Namen des Formulars, in dem sich das <b>ImageList<\/b>-Steuerelement befindet, sowie den Namen des <b>ImageList<\/b>-Steuerelements als Parameter. Au&szlig;erdem k&ouml;nnen Sie eine durch Kommata getrennte Liste der hinzuzuf&uuml;genden Elemente angeben.<\/p>\n<p>Die Prozedur <b>ImageListFuellen <\/b>&ouml;ffnet das Formular im Entwurf, referenziert das <b>ImageList<\/b>-Steuerelement und durchl&auml;uft alle Elemente der Bilderliste. Dabei liest sie erst den Pfad in die Variable <b>strImage <\/b>ein und ermittelt daraus den reinen Dateinamen ohne Verzeichnis und Dateiendung. Dann erstellt sie ein <b>StdPicture<\/b>-Objekt auf Basis des in der Datei gespeicherten Bildes und f&uuml;gt dieses mit der <b>Add<\/b>-Methode der <b>ListImages<\/b>-Auflistung in das <b>ImageList<\/b>-Steuerelement ein. Schlie&szlig;lich schlie&szlig;t sie das Formular und speichert dieses gleichzeitig.<\/p>\n<p>Achtung: Die per VBA hinzugef&uuml;gten Bilder bleiben nur dauerhaft im <b>ImageList<\/b>-Steuerelement erhalten, wenn die Prozedur das Formular in der Entwurfsansicht &ouml;ffnet &#8211; in der Formularansicht gelingt dies nicht. Deswegen m&uuml;ssen zur Laufzeit hinzugef&uuml;gte Bilder auch bei jedem &ouml;ffnen des Formulars neu hinzugef&uuml;gt werden &#8211; au&szlig;er, Sie m&ouml;chten das Formular zur Laufzeit in der Entwurfsansicht &ouml;ffnen, was zum Beispiel mit der Runtime oder mit <b>.mde\/.accde<\/b>-Datenbanken nicht m&ouml;glich ist.<\/p>\n<p><b>Laden des Formulars <\/b><\/p>\n<p>Nun erstellen Sie eine Ereignisprozedur, die durch das Ereignis <b>Beim Laden <\/b>des Formulars ausgel&ouml;st wird. Dieses soll die Eigenschaften des <b>TreeView<\/b>-Steuerelements einstellen, das <b>ImageList<\/b>-Steuerelement zuweisen und eine Prozedur aufrufen, die das <b>TreeView<\/b>-Steuerelement mit den Daten f&uuml;llt.<\/p>\n<p>In Listing 3 finden Sie zun&auml;chst die Deklaration zweier Variablen zum Referenzieren der beiden Steuerelemente <b>ctlTreeView <\/b>und <b>ctlImageList<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>WithEvents objTreeView<span style=\"color:blue;\"> As <\/span>MSComctlLib.TreeView\r\n<span style=\"color:blue;\">Dim <\/span>objImageList<span style=\"color:blue;\"> As <\/span>MSComctlLib.ImageList\r\n<span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Set<\/span> objTreeView = Me!ctlTreeView.Object\r\n     <span style=\"color:blue;\">Set<\/span> objImageList = Me!ctlImageList.Object\r\n     <span style=\"color:blue;\">With<\/span> objTreeView\r\n         .Appearance = ccFlat\r\n         .BorderStyle = ccNone\r\n         .ImageList = objImageList\r\n         .LineStyle = tvwTreeLines\r\n         .OLEDragMode = ccOLEDragAutomatic\r\n         .OLEDropMode = ccOLEDropManual\r\n         .Style = tvwTreelinesPlusMinusPictureText\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     TreeViewFuellen\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Diese Prozedur passt das TreeView-Steuerelement an und startet den F&uuml;llvorgang.<\/span><\/b><\/p>\n<p>Die durch das Ereignis <b>Beim Laden <\/b>ausgel&ouml;ste Ereignisprozedur <b>Form_Load <\/b>f&uuml;llt zun&auml;chst die beiden Variablen <b>objTreeView <\/b>und <b>objImageList <\/b>mit Verweisen auf die <b>Object<\/b>-Eigenschaft der entsprechenden Steuerelemente. Dann stellt sie einige Eigenschaften des <b>Treeview<\/b>-Steuerelements ein. Dies k&ouml;nnten Sie zwar auch &uuml;ber das Eigenschaftsfenster des <b>TreeView<\/b>-Steuerelements erledigen. Wenn Sie dies allerdings per Code tun, k&ouml;nnen Sie die entsprechenden Anweisungen direkt f&uuml;r weitere <b>TreeView<\/b>-Steuerelemente &uuml;bernehmen und brauchen sich nicht durch das Eigenschaftsfenster zu klicken.<\/p>\n<p>Schlie&szlig;lich ruft die Prozedur die Routine <b>TreeViewFuellen <\/b>auf, welche die Elemente der entsprechenden Tabellen einliest.<\/p>\n<p><b>Produkte im TreeView anzeigen<\/b><\/p>\n<p>Weiter oben haben wir definiert, dass sowohl Baugruppen als auch Einzelteile als Produkte eingesetzt werden k&ouml;nnen. Die einzige Kennzeichnung, die Produkte von herk&ouml;mmlichen Baugruppen und Einzelteilen unterscheidet, ist der Wert <b>True <\/b>im Feld <b>IstProdukt <\/b>der beiden Tabellen <b>tblBaugruppen <\/b>und <b>tblEinzelteile<\/b>. Auf diese Weise erm&ouml;glichen wir es auch, dass als komplette Produkte klassifizierte Baugruppen oder Einzelteile weiterhin als Elemente einer Baugruppe verwendet werden k&ouml;nnen.<\/p>\n<p>Wir wollen nun in der Prozedur <b>TreeViewFuellen <\/b>zun&auml;chst ein Root-Objekt namens <b>Produkte <\/b>anlegen. Unterhalb dieses Objekts sollen alle Baugruppen und Einzelteile erscheinen, die als Produkt gekennzeichnet sind. Die Prozedur <b>TreeViewFuellen <\/b>ruft dann f&uuml;r jedes Produkt die rekursive Routine <b>TreeView-Fuellen_Rek <\/b>auf, welche die untergeordneten Baugruppen und Einzelteile einliest.<\/p>\n<p>Die Prozedur <b>TreeViewFuellen<\/b> erstellt zun&auml;chst ein Recordset auf Basis der Abfrage <b>qryProdukte<\/b> (s. Listing 4). Diese ist jedoch keine herk&ouml;mmliche <b>SELECT<\/b>-Abfrage, sondern eine <b>UNION<\/b>-Abfrage. Sie f&uuml;hrt die Ergebnisse der gespeicherten Abfragen <b>qryProdukteBaugruppen <\/b>und <b>qryProdukteEinzelteile <\/b>zusammen.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>TreeViewFuellen()\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>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>objNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM qryProdukte\", dbOpenDynaset)\r\n     objTreeView.Nodes.Clear\r\n     <span style=\"color:blue;\">Set<\/span> objNode = objTreeView.Nodes.Add(, , \"r0\", \"Produkte\", \"home\")\r\n     <span style=\"color:blue;\">With<\/span> objNode\r\n         .Expanded = <span style=\"color:blue;\">True<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         <span style=\"color:blue;\">Set<\/span> objNode = objTreeView.Nodes.Add(\"r0\", tvwChild, \"r0|\" & rst!Key _\r\n             & rst!ProduktID, rst!Produkt, \"elements_hierarchy\")\r\n         <span style=\"color:blue;\">If <\/span>rst!Key = \"b\"<span style=\"color:blue;\"> Then<\/span>\r\n             TreeViewFuellen_Rek db, rst!ProduktID, objNode.Key\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: F&uuml;llen der ersten und zweiten Ebene des TreeView-Steuerelements<\/span><\/b><\/p>\n<p>Die Abfrage <b>qryProdukteBaugruppen<\/b> sieht wie in Bild 10 aus, und liefert alle Datens&auml;tze der Tabelle <b>tblBaugruppen<\/b>, deren Feld <b>IstProdukt <\/b>den Wert <b>True <\/b>aufweist.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_010.png\" alt=\"Abfrage von Baugruppen, die auch als Produkt ausgezeichnet sind.\" width=\"450\" height=\"293,0636\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Abfrage von Baugruppen, die auch als Produkt ausgezeichnet sind.<\/span><\/b><\/p>\n<p>Ganz &auml;hnlich ist die Abfrage <b>qryPro-dukte-Einzelteile <\/b>aufgebaut (s. Bild 11). Allerdings liefert diese die Datens&auml;tze der Tabelle <b>tblEinzelteile<\/b>, die als Produkt gekennzeichnet sind. Die <b>UNION<\/b>-Abfrage <b>qryProdukte<\/b> fasst die Inhalte beider Abfragen zusammen. Sie enth&auml;lt den folgenden Code:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_011.png\" alt=\"Abfrage der Einzelteile, die auch als Produkt ausgezeichnet sind.\" width=\"400\" height=\"325,7996\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Abfrage der Einzelteile, die auch als Produkt ausgezeichnet sind.<\/span><\/b><\/p>\n<pre>SELECT BaugruppeID AS ProduktID, Baugruppe AS Produkt\r\nFROM qryProdukteBaugruppen\r\nUNION\r\nSELECT EinzelteilID AS ProduktID, Einzelteil AS Produkt\r\nFROM qryProdukteEinzelteile\r\nORDER BY Produkt;<\/pre>\n<p>Hier ist zu beachten, dass Sie den jeweiligen Feldern der beiden Tabellen per <b>AS<\/b>-Schl&uuml;sselwort den gleichen Spaltennamen zuweisen m&uuml;ssen.<\/p>\n<p>Zur&uuml;ck zur Prozedur <b>TreeViewFuellen<\/b>: Diese erstellt nun zun&auml;chst das Root-Element mit der Bezeichnung <b>Produkte <\/b>und dem Bild, das im <b>ImageList<\/b>-Steuerelement unter dem <b>Key <\/b>mit dem Wert <b>home <\/b>gespeichert ist. Das neue Element erh&auml;lt als <b>Key <\/b>den Wert <b>r0<\/b>. Au&szlig;erdem stellt die Prozedur die Eigenschaft <b>Expanded <\/b>auf <b>True <\/b>ein, damit das Element immer aufgeklappt ist.<\/p>\n<p>Nun f&uuml;gt die Prozedur alle Elemente der Tabellen <b>tblBaugruppen <\/b>und <b>tblEinzelteile <\/b>zur zweiten Ebene des <b>TreeView<\/b>-Steuerelements hinzu, die als Produkte gekennzeichnet sind. Dazu durchl&auml;uft sie alle Datens&auml;tze des Recordsets <b>rstProdukte <\/b>und legt jeweils ein neues <b>Node<\/b>-Element an. Das bereits vorhandene Element <b>r0 <\/b>wird als &uuml;bergeordnetes Element angegeben. Die Elemente selbst erhalten als <b>Key<\/b>-Wert den Buchstaben <b>p <\/b>(f&uuml;r Produkt) und den Wert des Prim&auml;rschl&uuml;sselfeldes.<\/p>\n<p><b>Keine eindeutigen Werte<\/b><\/p>\n<p>Ups &#8211; das klappt ja gar nicht! Wir verwenden ja eine <b>UNION<\/b>-Tabelle, die Daten aus zwei verschiedenen Tabellen zusammenf&uuml;hrt. Da beide Tabellen Prim&auml;rschl&uuml;sselwerte aus dem gleichen Zahlenbereich verwenden, wird es fr&uuml;her oder sp&auml;ter geschehen, dass ein als Produkt gekennzeichnetes Bauteil und ein solches Einzelteil den gleichen Prim&auml;rschl&uuml;sselwert aufweisen &#8211; was einen Fehler ausl&ouml;st.<\/p>\n<p>Und wenn man noch einen Schritt weiter denkt, f&auml;llt einem auf, dass &auml;hnliche Probleme auch bei Hinzuf&uuml;gen der untergeordneten Elemente zu erwarten sind: Selbst wenn wir hier die Baugruppen jeweils mit dem Buchstaben <b>b <\/b>und die Einzelteile mit dem Buchstaben <b>e <\/b>als erstem Zeichen ausstatten und im &uuml;brigen den Prim&auml;rschl&uuml;sselwert hinzuf&uuml;gen, sind doppelte <b>Key<\/b>-Werte zu erwarten.<\/p>\n<p>Der Grund ist, dass die Baugruppen und Einzelteile nicht nur einer, sondern auch mehreren Baugruppen zugeordnet werden k&ouml;nnen.<\/p>\n<p>Wie aber erhalten wir eine eindeutige Bezeichnung der Elemente des <b>TreeView<\/b>-Steuerelements Sie k&ouml;nnen nat&uuml;rlich den Key etwa mit einem GUID-Wert f&uuml;llen. Allerdings wollen wir ja, wenn der Benutzer auf ein Element klickt, um beispielsweise dessen Details anzuzeigen oder ein Kontextmen&uuml; einzublenden, auch identifizieren, welches Element er soeben angeklickt hat. Und das gelingt nur, wenn wir den Prim&auml;rschl&uuml;sselwert und einen Buchstaben als Kennzeichen der Herkunftstabelle im <b>Key<\/b>-Wert unterbringen.<\/p>\n<p>Dies gelingt im <b>TreeView<\/b>-Steuerelement am einfachsten, indem wir dem <b>Key<\/b>-Wert jeweils die <b>Key<\/b>-Werte der &uuml;bergeordneten Elemente voranstellen. Das Produkt auf Basis der Baugruppe mit dem Prim&auml;rschl&uuml;sselwert <b>12 <\/b>w&uuml;rde also den <b>Key<\/b>-Wert <b>b12 <\/b>erhalten. Wenn die Baugruppe mit der ID <b>12 <\/b>nun etwa eine weitere Baugruppe mit der ID <b>24 <\/b>enth&auml;lt, wird diese mit dem <b>Key<\/b>-Wert <b>b12|b24 <\/b>ausgezeichnet. Besteht diese Baugruppe aus den Einzelteilen <b>7 <\/b>und <b>14<\/b>, erhalten diese im <b>TreeView<\/b>-Steuerelement die <b>Key<\/b>-Werte <b>b12|b24|e7 <\/b>und <b>b12|b24|e14<\/b>.<\/p>\n<p>Wenn wir dann etwa beim Anklicken eines Elements ermitteln wollen, um welches Element es sich handelt, m&uuml;ssen wir nur per Zeichenkettenfunktion den Teil hinter dem ersten Pipe-Zeichen (<b>|<\/b>) von hinten ermitteln und dann anhand des Buchstabens die Herkunftstabelle und anhand der Zahl den Prim&auml;rschl&uuml;sselwert ermitteln.<\/p>\n<p>&auml;ndern wir also die <b>UNION<\/b>-Abfrage so, dass diese den f&uuml;r den <b>Key <\/b>zu verwendenden Buchstaben mitliefert. F&uuml;r die Tabelle <b>tblBaugruppen <\/b>f&uuml;gen wir also das Feld <b>&#8220;b&#8220; AS Key <\/b>hinzu und f&uuml;r die Tabelle <b>tblEinzelteile <\/b>das Feld <b>&#8220;e&#8220; AS Key<\/b>:<\/p>\n<pre>SELECT BaugruppeID AS ProduktID, Baugruppe AS Produkt, \r\n''b'' AS Key FROM qryProdukteBaugruppen\r\nUNION \r\nSELECT EinzelteilID AS ProduktID, Einzelteil AS Produkt, ''e'' AS Key\r\nFROM qryProdukteEinzelteile ORDER BY Produkt;<\/pre>\n<p>Au&szlig;erdem passen Sie die Zeile zum Hinzuf&uuml;gen der Produkte zum <b>TreeView<\/b>-Steuerelement wie folgt an &#8211; statt dem fixen <b>Key<\/b>-Buchstaben <b>p <\/b>verwenden wir den Wert des Feldes <b>rst!Key<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> objNode = objTreeView.Nodes.Add\r\n(\"r0\", tvwChild, rst!Key & rst!ProduktID, rst!Produkt, \"elements_hierarchy\")<\/pre>\n<p>Wenn Sie das Formular nun &ouml;ffnen, sieht das <b>TreeView<\/b>-Steuerelement wie in Bild 12 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_012.png\" alt=\"Das TreeView-Steuerelement mit den ersten Elementen\" width=\"350\" height=\"118,7783\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Das TreeView-Steuerelement mit den ersten Elementen<\/span><\/b><\/p>\n<p><b>Wie geht es weiter<\/b><\/p>\n<p>Wir haben nun die ersten beiden Ebenen des <b>TreeView<\/b>-Steuerelements gef&uuml;llt. Nun ginge es eigentlich mit den weiteren Ebenen weiter &#8211; aber wir haben noch gar keine Daten f&uuml;r diese Ebenen eingegeben! Und um ehrlich zu sein: Ich erledige dies nur ungern, indem ich blindw&uuml;tig Beispieldatens&auml;tze in die Tabellen eingebe. Besser, Sie nutzen dazu direkt die Beispielformulare. Mit Beispieldaten allein ist es hier aber nicht getan: Wir ben&ouml;tigen auch noch eine M&ouml;glichkeit, einem Produkt oder einer Baugruppe weitere Baugruppen oder Einzelteile unterzuordnen. Dies sollte der Benutzerfreundlichkeit halber direkt im <b>TreeView<\/b>-Steuerelement geschehen.<\/p>\n<p>Zur Steuerung der Elemente des TreeViews haben sich Kontextmen&uuml;s bew&auml;hrt. Aber welche Kontextmen&uuml;-Eintr&auml;ge ben&ouml;tigen wir hier Normalerweise gibt es ja Befehle wie <b>Element l&ouml;schen<\/b>, <b>Element bearbeiten <\/b>oder <b>Element hinzuf&uuml;gen<\/b>. Auch hier ben&ouml;tigen wir diese Eintr&auml;ge, allerdings haben sie eine andere Bedeutung: Wenn Sie etwa den Kontextmen&uuml;-Eintrag <b>Element l&ouml;schen <\/b>einer Baugruppe verwenden, soll ja nicht der Baugruppen-Datensatz aus der Tabelle <b>tblBaugruppen <\/b>gel&ouml;scht werden, sondern nur diese Baugruppe soll nicht mehr der &uuml;bergeordneten Baugruppe oder dem Produkt untergeordnet sein &#8211; das hei&szlig;t, wir entfernen lediglich einen Eintrag aus einer der Verkn&uuml;pfungstabellen <b>tblBaugruppenZuordnungen <\/b>oder <b>tblBaugruppenEinzelteile<\/b>.<\/p>\n<p>Das Gleiche gilt f&uuml;r das Hinzuf&uuml;gen: Wir wollen mit dem Eintrag <b>Element hinzuf&uuml;gen <\/b>kein neues Element erzeugen, sondern nur eine der bestehenden Baugruppen oder Einzelteile zu einer Baugruppe hinzuf&uuml;gen.<\/p>\n<p>Das eigentliche Hinzuf&uuml;gen, Bearbeiten oder L&ouml;schen von Baugruppen oder Einzelteilen sollte direkt in den beiden Formularen <b>frmBaugruppen <\/b>oder <b>frmEinzelteile<\/b> erfolgen.<\/p>\n<p>Allerdings ist es nat&uuml;rlich schon sinnvoll, ein neues Element direkt vom Kontextmen&uuml; eines <b>Node<\/b>-Elements aus anzulegen und dieses dann gleich als untergeordnetes Element zu &uuml;bernehmen.<\/p>\n<p>Da dies doch etwas komplizierter als gedacht ist, legen wir doch erst einmal einige wenige Beispieldatens&auml;tze in den Tabellen <b>tblBaugruppen<\/b>, <b>tblEinzelteile<\/b>, <b>tblBaugruppenZuordnung <\/b>und <b>tblEinzelteileBaugruppen <\/b>an.<\/p>\n<p><b>Rekursives F&uuml;llen des TreeView-Steuerelements<\/b><\/p>\n<p>Nun k&uuml;mmern wir uns um das F&uuml;llen der darunter liegenden Ebenen. Dies erledigen wir mit der Prozedur <b>TreeViewFuellen_Rek<\/b> (s. Listing 5). Sie erwartet als Parameter den Verweis auf das aktuelle <b>Database<\/b>-Objekt sowie den Prim&auml;rschl&uuml;sselwert des &uuml;bergeordneten Elements und den Pfad des Elements &#8211; also die oben beschriebene, durch das Pipe-Zeichen getrennte Abfolge der <b>Key<\/b>-Werte (zum Beispiel <b>b1|b2|e6<\/b>).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>TreeViewFuellen_Rek(db<span style=\"color:blue;\"> As <\/span>DAO.Database, lngID<span style=\"color:blue;\"> As Long<\/span>, strPath<span style=\"color:blue;\"> As String<\/span>)\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>objNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>strKey<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM qryBaugruppenRek WHERE BaugruppeVaterID = &quot; _\r\n        & lngID, dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n        strKey = strPath & \"|b\" & rst!BaugruppeID\r\n        <span style=\"color:blue;\">Set<\/span> objNode = objTreeView.Nodes.Add(strPath, tvwChild, strKey, _\r\n           rst!Baugruppe, \"gearwheels\")\r\n        TreeViewFuellen_Rek db, rst!BaugruppeID, strKey\r\n        rst.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM qryEinzelteileRek &quot; _\r\n        &amp; &quot;WHERE qryEinzelteileRek.BaugruppeID = \" & lngID, dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n        strKey = strPath & \"|e\" & rst!EinzelteilID\r\n        <span style=\"color:blue;\">Set<\/span> objNode = objTreeView.Nodes.Add(strPath, tvwChild, strPath & \"|e\" _\r\n            & rst!EinzelteilID, rst!Einzelteil, \"gearwheel\")\r\n        rst.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Diese Prozedur f&uuml;llt die untergeordneten Elemente und ruft sich selbst gegebenenfalls rekursiv auf.<\/span><\/b><\/p>\n<p>Die Prozedur erstellt dann zun&auml;chst ein Recordset, das alle Datens&auml;tze einer Abfrage namens <b>qryBaugruppenRek <\/b>enth&auml;lt, deren Feld <b>BaugruppeVaterID <\/b>den Prim&auml;rschl&uuml;sselwert der &uuml;bergeordneten Baugruppe im <b>TreeView<\/b>-Steuerelement enth&auml;lt. Die Abfrage <b>qryBaugruppenRek <\/b>sieht wie in Bild 13 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_013.png\" alt=\"Die Abfrage qryBaugruppenRek liefert alle Baugruppen, die einer anderen Baugruppe untergeordnet sind.\" width=\"400\" height=\"235,1304\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 13: Die Abfrage qryBaugruppenRek liefert alle Baugruppen, die einer anderen Baugruppe untergeordnet sind.<\/span><\/b><\/p>\n<p>Nach dem &ouml;ffnen des Recordsets durchl&auml;uft die Prozedur eine <b>Do While<\/b>-Schleife &uuml;ber alle darin enthaltenen Datens&auml;tze. Innerhalb der Schleife ermittelt die Prozedur zun&auml;chst den <b>Key<\/b>-Buchstaben f&uuml;r das einzuf&uuml;gende Element, indem es die mit dem Parameter <b>strPath <\/b>&uuml;bergebene Zeichenkette um ein Pipe-Zeichen, den Buchstaben <b>b <\/b>und den Prim&auml;rschl&uuml;sselwert der abzubildenden Baugruppe erg&auml;nzt. Dann legt sie ein neues <b>Node<\/b>-Element im <b>TreeView<\/b>-Steuerelement an, wobei das Element unter dem <b>Node<\/b>-Element mit <b>strPath <\/b>&uuml;bergebenen <b>Key<\/b>-Wert angelegt wird. Als <b>Key <\/b>verwendet die Prozedur den soeben ermittelten Wert aus <b>strKey<\/b>, als <b>Text <\/b>den Wert des Feldes <b>Baugruppe <\/b>der zugrunde liegenden Abfrage.<\/p>\n<p>Schlie&szlig;lich ruft die Prozedur f&uuml;r jedes neu angelegte Baugruppen-Element wieder die Prozedur <b>TreeViewFuellen_Rek <\/b>auf und &uuml;bergibt die entsprechenden Parameter.<\/p>\n<p>Nachdem alle der mit <b>lngID <\/b>bezeichneten Baugruppe untergeordneten Baugruppen angelegt sind, wendet die Prozedur sich den Einzelteilen zu. Auch f&uuml;r diese haben wir eine eigene Abfrage angelegt, die <b>qryEinzelteileRek<\/b> hei&szlig;t und in Bild 14 abgebildet ist. Mit einem weiteren Recordset referenziert die Prozedur alle Eintr&auml;ge dieser Abfrage, deren Feld <b>BaugruppeID <\/b>(das aus der Verkn&uuml;pfungstabelle <b>tblEinzelteileBaugruppe <\/b>stammt) den mit dem Parameter <b>lngID <\/b>&uuml;bergebenen Wert enth&auml;lt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_014.png\" alt=\"Die Abfrage qryEinzelteileRek liefert alle Einzelteile, die einer Baugruppe untergeordnet sind.\" width=\"400\" height=\"300,7813\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 14: Die Abfrage qryEinzelteileRek liefert alle Einzelteile, die einer Baugruppe untergeordnet sind.<\/span><\/b><\/p>\n<p>Auch hier durchl&auml;uft die Prozedur eine <b>Do While<\/b>-Schleife &uuml;ber alle Datens&auml;tze und legt in &auml;hnlicher Weise wie bei den Baugruppen die entsprechenden <b>Node<\/b>-Elemente an. Die Unterschiede sind, dass zur Erg&auml;nzung des <b>Key<\/b>-Wertes nicht der Buchstabe <b>b <\/b>(f&uuml;r Bauteil), sondern <b>e <\/b>(f&uuml;r Einzelteil) an den mit <b>strPath <\/b>&uuml;bergebenen <b>Key<\/b>-Wert des &uuml;bergeordneten Elements verwendet wird.<\/p>\n<p>Au&szlig;erdem verwendet die <b>Add<\/b>-Methode der <b>Nodes<\/b>-Auflistung hier den Namen eines anderen Bildes aus dem <b>ImageList<\/b>-Steuerelement, n&auml;mlich <b>gearwheel<\/b>.<\/p>\n<p>Schlie&szlig;lich ist beim Anlegen der <b>Node<\/b>-Elemente f&uuml;r die Einzelteile kein weiterer Aufruf der <b>TreeViewFuellen_Rek<\/b>-Methode n&ouml;tig, denn ein Einzelteil soll ja im Gegensatz zu einer Baugruppe nicht aus weiteren Einzelteilen bestehen. Das Ergebnis sieht schlie&szlig;lich wie in Bild 15 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_015.png\" alt=\"Die Baugruppen und Einzelteile werden korrekt eingelesen und angezeigt.\" width=\"400\" height=\"202,2813\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 15: Die Baugruppen und Einzelteile werden korrekt eingelesen und angezeigt.<\/span><\/b><\/p>\n<p><b>Kontextmen&uuml;s des TreeView-Steuerelements<\/b><\/p>\n<p>Als N&auml;chstes wollen wir Kontextmen&uuml;s zum <b>TreeView<\/b>-Steuerelement hinzuf&uuml;gen. Dazu &uuml;berlegen wir zun&auml;chst, welche Eintr&auml;ge wir f&uuml;r welche Elemente ben&ouml;tigen. F&uuml;r das Root-Element brauchen wir:<\/p>\n<ul>\n<li><b>Baugruppen|Neue Baugruppe<\/b>: Zeigt einen Dialog zum Erstellen einer neuen Baugruppe an und speichert den Datensatz. Dann soll die neue Baugruppe zum <b>TreeView<\/b>-Steuerelement hinzugef&uuml;gt werden (<b>IstProdukt <\/b>wird auf <b>True <\/b>eingestellt &#8211; gilt auch f&uuml;r die folgenden Eintr&auml;ge).<\/li>\n<li><b>Bau-grup-pen|<Auf-lis-tung vorhandener Baugruppen><\/b>: Listet alle vorhandenen Baugruppen auf und f&uuml;gt das angeklickte Element als neues Produkt ein.<\/li>\n<li><b>Einzelteile|Neues Ein-zelteil<\/b>: &ouml;ffnet das Formular zum Anlegen eines neuen Einzelteils und f&uuml;gt dieses nach dem Speichern zum <b>TreeView<\/b>-Steuerelement hinzu.<\/li>\n<li><b>Ein-zel-tei-le|<Auf-lis-tung vorhander Einzelteile><\/b>: F&uuml;gt das ausgew&auml;hlte Einzelteil als Produkt zur ersten Ebene des <b>TreeView<\/b>-Steuerelements hinzu.<\/li>\n<\/ul>\n<p>Der Benutzer soll also sowohl neue als auch vorhandene Baugruppen und Einzelteile in der obersten Ebene anlegen k&ouml;nnen.<\/p>\n<p>F&uuml;r die Baugruppen (sowohl die in der obersten Ebene, also die Produkte auf Basis von Baugruppen) sollen folgende Kontextmen&uuml;-Eintr&auml;ge vorgesehen werden:<\/p>\n<ul>\n<li><b>Baugruppe entfernen<\/b><\/li>\n<li><b>Baugruppe kopieren<\/b><\/li>\n<li><b>Baugruppe verschieben<\/b><\/li>\n<li><b>Baugruppen|Neue Baugruppe<\/b><\/li>\n<li><b>Baugruppen|<Auflistung vorhander Baugruppen><\/b><\/li>\n<li><b>Einzelteile|Neues Einzelteil<\/b><\/li>\n<li><b>Einzelteile|<Auflistung vorhander Einzelteile><\/b><\/li>\n<\/ul>\n<p>Die ersten drei Eintr&auml;ge sind selbsterkl&auml;rend, die &uuml;brigen entsprechen denen f&uuml;r das Root-Element.<\/p>\n<p>F&uuml;r ein Einzelteil-Element soll das Kontextmen&uuml; folgende Eintr&auml;ge bereithalten:<\/p>\n<ul>\n<li><b>Einzelteil entfernen<\/b><\/li>\n<li><b>Einzelteil kopieren<\/b><\/li>\n<li><b>Einzelteil verschieben<\/b><\/li>\n<\/ul>\n<p><b>Ereignis bei Rechtsklick implementieren<\/b><\/p>\n<p>Im <b>TreeView<\/b>-Steuerelement rufen wir ein Kontextmen&uuml; hervor, indem wir das Ereignis <b>Bei Maustaste ab <\/b>des <b>TreeView<\/b>-Steuerelements implementieren.<\/p>\n<p>Die Ereignisprozedur aus Listing 6 liefert mit dem <b>Button<\/b>-Parameter einen Wert, mit dem wir ermitteln k&ouml;nnen, welche Maustaste der Benutzer soeben gedr&uuml;ckt hat. In diesem Fall gleichen wir den Wert mit der Konstanten <b>acRightButton <\/b>ab. Auch die beiden Parameter <b>x <\/b>und <b>y<\/b> des Prozeduraufrufs k&ouml;nnen wir verwenden, und zwar gleich in der folgenden Anweisung: Dort ermitteln wir mit der <b>HitTest<\/b>-Methode des <b>TreeView<\/b>-Steuerelements, welches <b>Node<\/b>-Objekt sich an der mit <b>x <\/b>und <b>y <\/b>markierten Position befindet, und speichern einen Verweis darauf in der Variablen <b>objNode<\/b>.  Sollte der Benutzer auf einen der Eintr&auml;ge geklickt haben und nicht in den leeren Bereich des <b>TreeView<\/b>-Steuerelements, ergibt <b>objNode Is Nothing <\/b>danach den Wert <b>False <\/b>und wir k&ouml;nnen das angeklickte <b>Node<\/b>-Element untersuchen. Als Erstes schauen wir uns dabei den Inhalt der <b>Key<\/b>-Eigenschaft des <b>Node<\/b>-Elements an. Diese enth&auml;lt ja einen Eintrag, der mehrere mit dem Pipe-Zeichen (<b>|<\/b>) getrennte Ausdr&uuml;cke enth&auml;lt. Die ersten geben die &uuml;bergeordneten Elemente der Hierarchie an, das letzte liefert Informationen &uuml;ber das angeklickte <b>Node<\/b>-Element selbst. Deshalb ermitteln wir dieses letzte Element, indem wir die Position des ersten Pipe-Zeichens von hinten suchen und alle Zeichen ab dieser Position in der Variablen <b>strKey <\/b>speichern.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objTreeView_MouseDown(ByVal Button<span style=\"color:blue;\"> As Integer<\/span>, ByVal Shift<span style=\"color:blue;\"> As Integer<\/span>, _\r\n        ByVal x<span style=\"color:blue;\"> As <\/span>stdole.OLE_XPOS_PIXELS, ByVal y<span style=\"color:blue;\"> As <\/span>stdole.OLE_YPOS_PIXELS)\r\n    <span style=\"color:blue;\">Dim <\/span>objNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>strTyp<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strKey<span style=\"color:blue;\"> As String<\/span>\r\n    Select Case Button\r\n        <span style=\"color:blue;\">Case <\/span>acRightButton\r\n            <span style=\"color:blue;\">Set<\/span> objNode = objTreeView.HitTest(x, y)\r\n            <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                strKey = <span style=\"color:blue;\">Mid<\/span>(objNode.Key, <span style=\"color:blue;\">InStrRev<\/span>(objNode.Key, \"|\") + 1)\r\n                strTyp = <span style=\"color:blue;\">Left<\/span>(strKey, 1)\r\n                lngID = <span style=\"color:blue;\">Mid<\/span>(strKey, 2)\r\n                Select Case strTyp\r\n                    <span style=\"color:blue;\">Case <\/span>\"r\"\r\n                        KontextmenueRoot\r\n                    <span style=\"color:blue;\">Case <\/span>\"b\"\r\n                        KontextmenueBaugruppe lngID\r\n                    <span style=\"color:blue;\">Case <\/span>\"e\"\r\n                        KontextmenueEinzelteil lngID\r\n                <span style=\"color:blue;\">End Select<\/span>\r\n            <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Anzeige der Kontextmen&uuml;s beim Anklicken eines Elements im TreeView-Steuerelement<\/span><\/b><\/p>\n<p>Aus diesem Ausdruck entnehmen wir mit der <b>Left<\/b>-Funktion den Typ des <b>Node<\/b>-Elements, also <b>r <\/b>f&uuml;r Root, <b>b <\/b>f&uuml;r Bauteil oder <b>e <\/b>f&uuml;r Einzelteil, und speichern dieses Zeichen in der Variablen <b>strTyp<\/b>. Die <b>Mid<\/b>-Funktion mit dem zweiten Parameter <b>2 <\/b>liefert alle Zeichen des in <b>strKey <\/b>befindlichen Ausdrucks ab dem zweiten Zeichen, was der im <b>Key <\/b>gespeicherte Prim&auml;rschl&uuml;sselwert der zugrunde liegenden Tabelle f&uuml;r das aktuelle Element entspricht. Diesen Zahlenwert speichern wir wiederum in der Variablen <b>lngID<\/b>.<\/p>\n<p>Schlie&szlig;lich folgt eine <b>Select Case<\/b>-Bedingung, die den Inhalt der Variablen <b>strTyp <\/b>unterscheidet und je nach Wert eine der drei Prozeduren <b>Kontextmenue-Root<\/b>, <b>KontextmenueBaugruppe <\/b>oder <b>KontextmenueEinzelteil <\/b>aufruft &#8211; bei den beiden Letzteren unter &uuml;bergabe des Wertes aus <b>lngID<\/b>.<\/p>\n<p>Um zu pr&uuml;fen, ob der Rechtsklick mit dieser Prozedur wie gew&uuml;nscht funktioniert, k&ouml;nnen Sie zun&auml;chst die Prozedurk&ouml;pfe wie im folgenden Beispiel anlegen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>KontextmenueBaugruppe( lngID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">MsgBox<\/span> \"Kontextmenue Baugruppe \" & lngID\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b>Kontextmen&uuml;s einblenden<\/b><\/p>\n<p>Nach einem kurzen Test k&uuml;mmern wir uns dann um die Anzeige der entsprechenden Kontextmen&uuml;s. Bevor Sie mit der Programmierung der Kontextmen&uuml;s beginnen, sollten Sie noch einen Verweis auf die Bibliothek <b>Microsoft Office x.0 Object Library <\/b>zum aktuellen Projekt hinzuf&uuml;gen, da dieses die ben&ouml;tige Objekte wie <b>CommandBar <\/b>et cetera enth&auml;lt.<\/p>\n<p><b>Kontextmen&uuml; f&uuml;r das Root-Element<\/b><\/p>\n<p>Dann programmieren wir zun&auml;chst die Prozedur, die beim Aufrufen des Kontextmen&uuml;s f&uuml;r das Root-Element ausgel&ouml;st wird. Dieses soll zwei Untermen&uuml;s namens <b>Baugruppen <\/b>und <b>Einzelteile <\/b>enthalten. <b>Baugruppen <\/b>bietet als Befehle einen Eintrag namens <b>Neue Baugruppe <\/b>an und die Auswahl aller vorhandenen Baugruppen, die noch nicht als Produkt angelegt wurden, <b>Einzelteile <\/b>bietet ebenfalls einen Eintrag zum Anlegen neuer Einzelteile an (<b>Neues Einzelteil<\/b>) sowie die noch nicht als Produkt angegebenen Einzelteile.<\/p>\n<p>Die Prozedur aus Listing 7 l&ouml;scht zun&auml;chst bei deaktivierter Fehlerbehandlung ein eventuell vorhandenes Kontextmen&uuml; namens <b>TreeView_Root<\/b>. Dann erstellt sie dieses neu und referenziert es mit der Variablen <b>cbr<\/b>. Das Element namens <b>Baugruppen <\/b>f&uuml;gt die Prozedur mit der <b>Add<\/b>-Methode der <b>Controls<\/b>-Auflistung mit dem Typ <b>msoControlButton <\/b>zum Steuerelement hinzu. Darunter folgt das Element mit der Beschriftung <b>Neue Baugruppe<\/b> (siehe Bild 16). Als <b>OnAction<\/b>-Eigenschaft legt sie dabei den Wert <b>=NeueBaugruppe(0) <\/b>fest.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_011.png\" alt=\"Hinzuf&uuml;gen einer neuen Baugruppe oder einer bestehenden Baugruppe unter dem Produkte-Element\" width=\"500\" height=\"223,3841\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 16: Hinzuf&uuml;gen einer neuen Baugruppe oder einer bestehenden Baugruppe unter dem Produkte-Element<\/span><\/b><\/p>\n<p>Warum wird der Wert <b>0 <\/b>als Parameter &uuml;bergeben Weil f&uuml;r Funktionen, die von Kontextmen&uuml;s aus aufgerufen werden, keine optionalen Parameter verwendet werden k&ouml;nnen. Die Funktion <b>NeueBaugruppe <\/b>m&ouml;chten wir aber sp&auml;ter auch noch f&uuml;r die im <b>TreeView<\/b>-Steuerelement enthaltenen Baugruppen aufrufen, wobei wir in jedem Fall den Wert der &uuml;bergeordneten Baugruppe als Parameter &uuml;bergeben m&uuml;ssen.<\/p>\n<p>Anschlie&szlig;end &ouml;ffnet die Prozedur ein Recordset auf Basis der Tabelle <b>tblBaugruppen<\/b>. Hier verwendet sie allerdings nur solche Datens&auml;tze, deren Feld <b>IstProdukt <\/b>den Wert <b>False <\/b>enth&auml;lt. Der Hintergrund ist, dass jede Baugruppe und auch jedes Produkt einzigartig ist und dementsprechend auch nur einmal als Produkt im <b>TreeView<\/b>-Steuerelement angezeigt werden soll. Diese Datensatzgruppe durchl&auml;uft die Prozedur dann und f&uuml;gt f&uuml;r jeden Datensatz eine neue Schaltfl&auml;che unterhalb des Elements <b>Baugruppen <\/b>hinzu. Als Beschriftung erhalten die Elemente den im Feld <b>Baugruppe <\/b>gespeicherten Wert, als VBA-Funktion hinterlegt die Prozedur einen Ausdruck wie <b>=BaugruppeHinzufuegen(123)<\/b>, wobei der hier beispielhaft als <b>BaugruppeID <\/b>verwendet Wert <b>123 <\/b>aus dem Feld <b>BaugruppeID <\/b>des Recordsets ausgelesen wird.<\/p>\n<p>Dann legt die Prozedur ein <b>msoControlPopup<\/b>-Element mit der Beschriftung <b>Einzelteile <\/b>an. Unterhalb dieses Elements folgt der Eintrag <b>Neues Einzelteil<\/b> mit dem Befehl <b>=NeuesEinzelteil(0)<\/b>. Der Parameter erh&auml;lt hier aus den bereits oben erw&auml;hnten Gr&uuml;nden den Wert <b>0<\/b>.<\/p>\n<p>Au&szlig;erdem f&uuml;gt die Prozedur auch hier f&uuml;r jeden Datensatz der Tabelle <b>tblEinzelteile<\/b>, dessen Feld <b>IstProdukt <\/b>den Wert <b>False <\/b>enth&auml;lt, den Namen des jeweiligen Einzelteils hinzu. Der Funktionsaufruf f&uuml;r <b>OnAction <\/b>lautet hier etwa <b>=EinzelteilHinzufuegen(234)<\/b>.<\/p>\n<p>Schlie&szlig;lich sorgt die Methode <b>ShopPopup <\/b>des neu erstellten und mit <b>cbr <\/b>referenzierten Kontextmen&uuml;s f&uuml;r dessen Anzeige.<\/p>\n<p><b>Vorhandene Baugruppe als Produkt hinzuf&uuml;gen<\/b><\/p>\n<p>Die f&uuml;r den Kontextmen&uuml;-Eintrag <b>Baugruppen|Baugruppe hinzuf&uuml;gen <\/b>angegebene Funktion implementieren wir wie in Listing 8. Die Funktion erwartet den Parameter <b>lngBaugruppeID<\/b>. Sie f&uuml;llt ein <b>Database<\/b>-Objekt namens <b>db <\/b>mit einem Verweis auf die aktuelle Datenbank und f&uuml;hrt dann eine <b>UPDATE<\/b>-Abfrage aus. Diese stellt f&uuml;r den Datensatz der Tabelle <b>tblBaugruppen <\/b>mit dem mit <b>lngBaugruppeID <\/b>&uuml;bergebenen Prim&auml;rschl&uuml;sselwert das Feld <b>IstProdukt <\/b>auf den Wert <b>True <\/b>ein.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>BaugruppeHinzufuegen(lngBaugruppeID<span style=\"color:blue;\"> As Long<\/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>strBaugruppe<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    db.Execute \"UPDATE tblBaugruppen SET IstProdukt = <span style=\"color:blue;\">True<\/span> WHERE BaugruppeID = \" _\r\n        & lngBaugruppeID, dbFailOnError\r\n    strBaugruppe = DLookup(\"Baugruppe\", \"tblBaugruppen\", \"BaugruppeID = \" & lngBaugruppeID)\r\n    objTreeView.Nodes.Add \"r0\", tvwChild, \"r0|b\" & lngBaugruppeID, strBaugruppe, \"gearwheels\"\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Hinzuf&uuml;gen einer vorhandenen Baugruppe als Produkt<\/span><\/b><\/p>\n<p>Wenn Sie das <b>TreeView<\/b>-Steuerelement nun mit der Funktion <b>TreeViewFuellen <\/b>neu f&uuml;llen w&uuml;rden, erschiene diese Baugruppe nun automatisch direkt unter dem Root-Element <b>Produkte<\/b>. Allerdings kann dies je nach der Anzahl der enthaltenen Elemente eine Weile dauern, weshalb wir das Element separat hinzuf&uuml;gen.<\/p>\n<p>Dazu ben&ouml;tigen wir zun&auml;chst den Namen der Baugruppe, den die Funktion mit einer entsprechenden <b>DLookup<\/b>-Anweisung ermittelt und in der Variablen <b>strBauteil <\/b>speichert. Damit legt die Funktion nun &uuml;ber die <b>Add<\/b>-Methode ein neues Element etwa mit dem Schl&uuml;ssel <b>r0|b123 <\/b>unterhalb des Root-Elements mit dem <b>Key<\/b>-Wert <b>r0 <\/b>an.<\/p>\n<p><b>Vorhandenes Einzelteil als Produkt hinzuf&uuml;gen<\/b><\/p>\n<p>Das Hinzuf&uuml;gen eines Einzelteils als Produkt direkt unterhalb des Root-Elements <b>Produkte <\/b>funktioniert genauso wie das Hinzuf&uuml;gen eines Produkts.<\/p>\n<p>Die Funktion <b>EinzelteilHinzufuegen <\/b>finden Sie im Klassenmodul des Formulars <b>frmStuecklisteTreeView<\/b>.<\/p>\n<p><b>Neues Bauteil als Produkt hinzuf&uuml;gen<\/b><\/p>\n<p>Wenn der Benutzer den Eintrag <b>Baugruppen|Neue Baugruppe <\/b>des Kontextmen&uuml;s ausw&auml;hlt, gibt es zwei M&ouml;glichkeiten:<\/p>\n<ul>\n<li>Sie legen einen neuen, leeren Eintrag unterhalb des Produkte-Elements an und erlauben dem Benutzer, dort den Namen des neuen Bauteils einzutragen. Nach dem Eintragen muss das Bauteil noch zur Tabelle <b>tblBauteile <\/b>hinzugef&uuml;gt werden.<\/li>\n<li>Sie zeigen eine <b>InputBox <\/b>an, mit welcher der Benutzer den Namen des neuen Elements angeben kann. Danach f&uuml;gen Sie das Element zum TreeView-Steuerelement hinzu und speichern den entsprechenden Datensatz in der Tabelle.<\/li>\n<\/ul>\n<p><b>Neues Einzelteil als Produkt hinzuf&uuml;gen<\/b><\/p>\n<p>Im Beitrag <b>TreeView: Neue Elemente anlegen <\/b>(<b>www.access-im-unternehmen.de\/919<\/b>) liefern wir einige Beispiele f&uuml;r das Anlegen neuer Elemente im <b>TreeView<\/b>-Steuerelement, wobei hier die Bindung an eine Datenherkunft im Mittelpunkt steht.<\/p>\n<p>Praktischerweise verwenden wir dort das Beispiel der St&uuml;ckliste, weshalb wir an dieser Stelle auf diesen Artikel verweisen, wenn es um das Anlegen neuer Einzelteile sowohl als Produkt als auch als Teile einer Baugruppe geht.<\/p>\n<p>Die dortigen Prozeduren werden allesamt &uuml;ber Schaltfl&auml;chen aktiviert, welche das aktuelle <b>Node<\/b>-Element im <b>TreeView<\/b>-Steuerelement auslesen und in Abh&auml;ngigkeit davon das neue Element anlegen und die entsprechenden Datens&auml;tze in die Tabellen <b>tblBaugruppen<\/b>, <b>tblEinzelteile<\/b>, <b>tblBaugruppenZuordnungen <\/b>und <b>tblBaugruppenEinzelteile <\/b>eintragen. Die Routine <b>NeuesEinzelteil <\/b>braucht also nur noch die Ereignisprozedur aufzurufen, die auch durch die entsprechende Schaltfl&auml;che ausgel&ouml;st wird:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>NeuesEinzelteil( <span style=\"color:blue;\">Optional<\/span> lngBaugruppeID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Call<\/span> cmdNeuesEinzelteilI_Click\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>In diesem Fall zeigt die Auswahl des Kontextmen&uuml;-Eintrags <b>Neues Einzelteil <\/b>einen modalen Dialog an, mit dem Sie das neue Einzelteil anlegen k&ouml;nnen (siehe Bild 17). Sie k&ouml;nnen auch die zweite im Beitrag <b>TreeView: Neue Elemente anlegen <\/b>vorgestellte Variante w&auml;hlen, wo das Anlegen direkt in einem Unterformular im Formular des <b>TreeView<\/b>-Steuerelements erfolgt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_923_016.png\" alt=\"Hinzuf&uuml;gen eines neuen Einzelteils per Popup-Formular\" width=\"650\" height=\"288,9853\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 17: Hinzuf&uuml;gen eines neuen Einzelteils per Popup-Formular<\/span><\/b><\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Im ersten Teil dieser Beitragsreihe haben wir das <b>TreeView<\/b>-Steuerelement mit den Baugruppen und Einzelteilen gef&uuml;llt und eine Ebene eingef&uuml;gt.<\/p>\n<p>Au&szlig;erdem k&ouml;nnen Sie bereits Kontextmen&uuml;-Eintr&auml;ge zum Anlegen der verschiedenen Elemente nutzen. Es fehlen noch weitere Kontextmen&uuml;-Eintr&auml;ge, um Baugruppen oder Einzelteile zu l&ouml;schen oder auszuschneiden, zu kopieren und an anderer Stelle einzuf&uuml;gen. Letztere Techniken sollen auch per Drag and Drop erm&ouml;glicht werden. Sie sehen: Es ist noch viel zu tun!<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Stueckliste.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{D36269E1-68C7-4D72-BC28-1C1F29F51A64}\/aiu_923.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>St&uuml;cklisten dienen dazu, die Einzelteile eines Objekts strukturiert darzustellen. Strukturiert bedeutet dabei, dass die Einzelteile jeweils zu Baugruppen zusammengefasst werden. Ein Objekt besteht also aus Baugruppen und\/oder Einzelteilen, wobei jede Baugruppe wieder aus Baugruppen und\/oder Einzelteilen besteht &#8211; bis am Ende jede Baugruppe in ihre Einzelteile aufgel&ouml;st ist. Einzelteile sind die kleinsten Einheiten in der St&uuml;ckliste, sie k&ouml;nnen nicht weiter aufgeteilt werden.Dieser Beitrag soll zeigen, wie Sie St&uuml;cklisten mit Access verwalten. Dabei spielt das TreeView-Steuerelement eine gro&szlig;e Rolle.<\/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":[66012014,662014,44000027],"tags":[],"class_list":["post-55000923","post","type-post","status-publish","format-standard","hentry","category-66012014","category-662014","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>St&uuml;cklisten, Teil I - 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\/Stuecklisten_Teil_I\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"St&uuml;cklisten, Teil I\" \/>\n<meta property=\"og:description\" content=\"St&uuml;cklisten dienen dazu, die Einzelteile eines Objekts strukturiert darzustellen. Strukturiert bedeutet dabei, dass die Einzelteile jeweils zu Baugruppen zusammengefasst werden. Ein Objekt besteht also aus Baugruppen und\/oder Einzelteilen, wobei jede Baugruppe wieder aus Baugruppen und\/oder Einzelteilen besteht - bis am Ende jede Baugruppe in ihre Einzelteile aufgel&ouml;st ist. Einzelteile sind die kleinsten Einheiten in der St&uuml;ckliste, sie k&ouml;nnen nicht weiter aufgeteilt werden.Dieser Beitrag soll zeigen, wie Sie St&uuml;cklisten mit Access verwalten. Dabei spielt das TreeView-Steuerelement eine gro&szlig;e Rolle.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T21:19:13+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/ac3a102298f54458b887e18af009bc73\" \/>\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=\"31\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"St&uuml;cklisten, Teil I\",\"datePublished\":\"2020-05-22T21:19:13+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/\"},\"wordCount\":5642,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/ac3a102298f54458b887e18af009bc73\",\"articleSection\":[\"1\\\/2014\",\"2014\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/\",\"name\":\"St&uuml;cklisten, Teil I - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/ac3a102298f54458b887e18af009bc73\",\"datePublished\":\"2020-05-22T21:19:13+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/ac3a102298f54458b887e18af009bc73\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/ac3a102298f54458b887e18af009bc73\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Stuecklisten_Teil_I\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"St&uuml;cklisten, Teil I\"}]},{\"@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":"St&uuml;cklisten, Teil I - 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\/Stuecklisten_Teil_I\/","og_locale":"de_DE","og_type":"article","og_title":"St&uuml;cklisten, Teil I","og_description":"St&uuml;cklisten dienen dazu, die Einzelteile eines Objekts strukturiert darzustellen. Strukturiert bedeutet dabei, dass die Einzelteile jeweils zu Baugruppen zusammengefasst werden. Ein Objekt besteht also aus Baugruppen und\/oder Einzelteilen, wobei jede Baugruppe wieder aus Baugruppen und\/oder Einzelteilen besteht - bis am Ende jede Baugruppe in ihre Einzelteile aufgel&ouml;st ist. Einzelteile sind die kleinsten Einheiten in der St&uuml;ckliste, sie k&ouml;nnen nicht weiter aufgeteilt werden.Dieser Beitrag soll zeigen, wie Sie St&uuml;cklisten mit Access verwalten. Dabei spielt das TreeView-Steuerelement eine gro&szlig;e Rolle.","og_url":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T21:19:13+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/ac3a102298f54458b887e18af009bc73","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"31\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"St&uuml;cklisten, Teil I","datePublished":"2020-05-22T21:19:13+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/"},"wordCount":5642,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/ac3a102298f54458b887e18af009bc73","articleSection":["1\/2014","2014","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/","url":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/","name":"St&uuml;cklisten, Teil I - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/ac3a102298f54458b887e18af009bc73","datePublished":"2020-05-22T21:19:13+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/ac3a102298f54458b887e18af009bc73","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/ac3a102298f54458b887e18af009bc73"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Stuecklisten_Teil_I\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"St&uuml;cklisten, Teil I"}]},{"@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\/55000923","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=55000923"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000923\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}