{"id":55001244,"date":"2020-08-01T00:00:00","date_gmt":"2020-08-05T10:25:23","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1244"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"TreeView_mit_RibbonEintraegen","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/","title":{"rendered":"TreeView mit Ribbon-Eintr&auml;gen"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/973f7a55989f44a69836d217e6b1c653\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Die Programmierung des TreeView-Steuerelements haben wir bereits in vielen Beitr&auml;gen dokumentiert. Dort haben wir auch gezeigt, wie Sie Befehle f&uuml;r spezielle Elementtypen im TreeView in Kontextmen&uuml;s unterbringen, die beim Rechtsklick auf die jeweiligen Elemente angezeigt werden. Es gibt noch eine andere M&ouml;glichkeit, solche Befehle abh&auml;ngig vom Elementtyp abzubilden: als Ribbon-Eintr&auml;ge. Wie das gelingt, zeigt der vorliegende Beitrag.<\/b><\/p>\n<p><b>Beispieldatenbank<\/b><\/p>\n<p>Im Beitrag <b>TreeView mit Kontextmen&uuml; <\/b>(<b>www.access-im-unternehmen.de\/1243<\/b>) haben wir bereits Vorarbeiten f&uuml;r diesen Beitrag geleistet und ein funktionsf&auml;higes <b>TreeView<\/b>-Steuerelement mit den Daten aus den beiden Tabellen <b>tblKunden <\/b>und <b>tblProjekte <\/b>gef&uuml;llt.<\/p>\n<p>Dort haben wir beschrieben, wie Sie die Daten im TreeView mit Kontextmen&uuml;-Eintr&auml;gen anpassen k&ouml;nnen. Im vorliegenden Beitrag wollen wir nun zeigen, wie Sie die entsprechenden Befehle in einem Ribbon unterbringen, das nur dann angezeigt wird, wenn der Benutzer auf ein Element eines bestimmten Typs klickt &#8211; also beispielsweise auf ein Kunden-Element oder ein Projekt-Element.<\/p>\n<p>Das Ribbon soll dann die gleichen Befehle anzeigen, die auch das Kontextmen&uuml; zu dem entsprechenden Eintrag anzeigt und die gleichen Funktionen ausl&ouml;sen (siehe Bild 1). Wir beginnen mit der Beispieldatenbank <b>TreeViewMitRibbon.accdb<\/b>.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_001.png\" alt=\"Die Befehle dieses Kontextmen&uuml;s wollen wir im Ribbon anzeigen, wenn der Benutzer einen der Eintr&auml;ge im TreeView anklickt.\" width=\"424,7115\" height=\"385,4525\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Die Befehle dieses Kontextmen&uuml;s wollen wir im Ribbon anzeigen, wenn der Benutzer einen der Eintr&auml;ge im TreeView anklickt.<\/span><\/b><\/p>\n<p><b>Tabelle f&uuml;r die Ribbon-Definitionen anlegen<\/b><\/p>\n<p>Wenn Sie Ribbons anzeigen m&ouml;chten, ben&ouml;tigen Sie eine Tabelle namens <b>USysRibbons<\/b>, die nach einem bestimmten Schema aufgebaut ist und die Ribbon-Definitionen aufnimmt. Diese Tabelle enth&auml;lt die folgenden drei Felder:<\/p>\n<ul>\n<li><b>ID<\/b>: Prim&auml;rschl&uuml;sselfeld der Tabelle mit Autowert-Funktion<\/li>\n<li><b>Ribbonname<\/b>: Name des Ribbons<\/li>\n<li><b>RibbonXML<\/b>: XML-Definition des Ribbons<\/li>\n<\/ul>\n<p>Die Tabelle mit dem Namen <b>USysRibbons <\/b>wird aufgrund des Pr&auml;fixes <b>USys&#8230;<\/b> als Systemobjekt erkannt und wird nur angezeigt, wenn Sie in den Navigationsoptionen von Access die Option <b>Systemobjekte anzeigen <\/b>aktivieren. <\/p>\n<p>Diese Tabelle f&uuml;llen wir dann gleich mit den gew&uuml;nschten Ribbon-Definitionen (siehe Bild 2). Mit der ersten m&ouml;chten wir erreichen, dass beim Anklicken eines der <b>Kunde<\/b>-Elemente im <b>TreeView<\/b>-Steuerelement ein kontextabh&auml;ngiges Ribbon-Tab zum Ribbon hinzugef&uuml;gt wird.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_002.png\" alt=\"Die Tabelle USysRibbons mit den Ribbon-Definitionen\" width=\"649,559\" height=\"407,0569\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Die Tabelle USysRibbons mit den Ribbon-Definitionen<\/span><\/b><\/p>\n<p>Deshalb deklarieren wir dieses wie in Listing 1. Das Element <b>customUI <\/b>enth&auml;lt zwei Callback-Attribute:<\/p>\n<pre>&lt;xml version=\"1.0\"&gt;\r\n&lt;customUI xmlns=\"http:\/\/schemas.microsoft.com\/office\/2009\/07\/customui\" onLoad=\"OnLoad_RibbonKunde\"\r\n      loadImage=\"loadImage\"&gt;\r\n   &lt;ribbon&gt;\r\n     &lt;contextualTabs&gt;\r\n       &lt;tab<span style=\"color:blue;\">Set<\/span> idMso=\"TabSetFormReportExtensibility\"&gt;\r\n         &lt;tab id=\"tabKunde\" label=\"Kunden\"&gt;\r\n           &lt;group id=\"grpKunde\" label=\"Kunde\"&gt;\r\n             &lt;button image=\"user_delete_32\" label=\"Kunde l&ouml;schen\" id=\"btnKundeLoeschen\" onAction=\"onAction\" \r\n                 size=\"large\"\/&gt;\r\n             &lt;button image=\"folder2_plus_32\" label=\"Neues Projekt\" id=\"btnNeuesProjekt\" onAction=\"onAction\" \r\n                 size=\"large\"\/&gt;\r\n             &lt;button onAction=\"onAction\" size=\"large\" image=\"edit_32\" label=\"Umbenennen\" id=\"btnKundeUmbenennen\"\/&gt;\r\n           &lt;\/group&gt;\r\n           &lt;group id=\"grpZwischenablage\" label=\"Zwischenablage\"&gt;\r\n             &lt;button id=\"btnAusschneiden\" image=\"cut_32\" label=\"Ausschneiden\" onAction=\"onAction\" size=\"large\"\/&gt;\r\n             &lt;button id=\"btnKopieren\" image=\"copy_32\" label=\"Kopieren\" onAction=\"onAction\" size=\"large\"\/&gt;\r\n             &lt;button image=\"clipboard_paste_32\" label=\"Einf&uuml;gen\" id=\"btnEinfuegen\" onAction=\"onAction\" size=\"large\"\/&gt;\r\n           &lt;\/group&gt;\r\n         &lt;\/tab&gt;\r\n       &lt;\/tabSet&gt;\r\n     &lt;\/contextualTabs&gt;\r\n   &lt;\/ribbon&gt;\r\n&lt;\/customUI&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Definition des ersten Ribbons, das beim Anklicken eines Kunden angezeigt werden soll<\/span><\/b><\/p>\n<ul>\n<li><b>onLoad<\/b>: Dieses Callback wird einmalig beim Laden der Ribbon-Definition ausgef&uuml;hrt. Die Callback-Funktion dient meist dazu, eine Variable des Typs <b>IRibbonUI <\/b>mit einem Verweis auf die Ribbon-Definition zu f&uuml;llen, was auch hier der Fall ist.<\/li>\n<li><b>loadImage<\/b>: Dieses Callback wird ausgel&ouml;st, wenn die Ribbon-Definition Elemente enth&auml;lt, f&uuml;r die das Attribut <b>image<\/b> auf ein anzuzeigendes Bild eingestellt ist. Sie muss durch den Entwickler gef&uuml;llt werden, damit das Ribbon-Element das gew&uuml;nschte Bild anzeigt.<\/li>\n<\/ul>\n<p>Das ribbon-Element k&ouml;nnte man mit dem Attribut <b>startFromScratch=&#8220;true&#8220;<\/b> ausstatten, wenn man m&ouml;chte, dass alle anderen und eingebauten Elemente des Ribbons beim Anzeigen ausgeblendet werden. Wir wollen dem Benutzer aber hier die M&ouml;glichkeit geben, dennoch die Befehle in den &uuml;brigen Ribbon-Tabs zu verwenden.<\/p>\n<p>Um Ribbon-Tabs so anzuzeigen, dass sie nur im Kontext mit einem bestimmten Formular oder Element erscheinen,  verwenden wir nicht die &uuml;blicherweise genutzte <b>tabs<\/b>-Auflistung, sondern das Element <b>contextualTabs<\/b>. Dieses geht meist einher mit dem untergeordneten Element <b>tabSet<\/b>, dem wir &uuml;ber das Attribut <b>idMso <\/b>mit dem Wert <b>TabSetFormReportExtensibility <\/b>die Information mitgeben, dass es gemeinsam mit Formularen oder Berichten angezeigt wird.<\/p>\n<p>Danach folgt ein herk&ouml;mmliches <b>tab<\/b>-Element mit der Beschriftung <b>Kunden<\/b>, darunter zwei <b>group<\/b>-Elemente. Das erste erh&auml;lt die Beschriftung <b>Kunde<\/b>, das zweite die Beschriftung <b>Zwischenablage<\/b>. Die erste Gruppe enth&auml;lt die drei Befehle <b>Kunde l&ouml;schen<\/b>, <b>Neues Projekt <\/b>und <b>Umbenennen<\/b>. F&uuml;r alle <b>button<\/b>-Elemente legen wir &uuml;ber das Attribut <b>image <\/b>den Namen des f&uuml;r diese Schaltfl&auml;che anzuzeigenden Bildes fest.<\/p>\n<p>Au&szlig;erdem stellen wir mit <b>size=&#8220;large&#8220; <\/b>ein, dass gro&szlig;e Schaltfl&auml;chen angezeigt werden sollen. Schlie&szlig;lich erhalten alle Schaltfl&auml;chen das Attribut <b>onAction <\/b>mit dem Namen der Callback-Funktion, die beim Anklicken der Schaltfl&auml;che aufgerufen werden soll. Warum erhalten alle Schaltfl&auml;chen den Aufruf der gleichen Callback-Funktion namens <b>onAction<\/b> Weil diese als Parameter den Namen des aufrufenden Elements erh&auml;lt und wir in dieser Prozedur pr&uuml;fen, von welchem Element der Aufruf kommt und die entsprechenden Befehle ausf&uuml;hren.<\/p>\n<p>Dies soll ein Ribbon wie in Bild 3 ergeben. In den folgenden Abschnitten sehen wir uns an, wie wir das realisieren.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_003.png\" alt=\"Das Ribbon zu den Kundeneintr&auml;gen im TreeView-Steuerelement\" width=\"599,593\" height=\"452,5589\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Das Ribbon zu den Kundeneintr&auml;gen im TreeView-Steuerelement<\/span><\/b><\/p>\n<p><b>Ribbon-Verweis speichern<\/b><\/p>\n<p>Wie oben erw&auml;hnt, soll beim Laden des Ribbons ein Verweis auf die Ribbon-Definition in einer Variablen gespeichert werden. F&uuml;r diesen und anderen Ribbon-relevanten Code legen wir ein neues Modul namens <b>mdlRibbons <\/b>an. Diesem f&uuml;gen wir als Erstes eine Variable f&uuml;r unser soeben definiertes Ribbon hinzu:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>objRibbon_RibbonKunde<span style=\"color:blue;\"> As <\/span>IRibbonUI<\/pre>\n<p>Dann k&ouml;nnen wir auch schon die Callback-Funktion implementieren, die wir f&uuml;r das Attribut <b>onLoad <\/b>des <b>customUI<\/b>-Elements der Ribbon-Definition angegeben haben. Diese sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>onLoad_RibbonKunde(ribbon<span style=\"color:blue;\"> As <\/span>IRibbonUI)\r\n     <span style=\"color:blue;\">Set<\/span> objRibbon_RibbonKunde = ribbon\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b>Callback zum Zuweisen von Bildern<\/b><\/p>\n<p>Danach legen wir die Callback-Prozedur an, die wir f&uuml;r das Callback-Attribut <b>loadImage <\/b>hinterlegt haben. Diese finden Sie in Listing 2. Die Prozedur erh&auml;lt den f&uuml;r das Attribut image des jeweiligen Steuerelements angegebenen Namen des Bildes.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>loadImage(control, ByRef image)\r\n     <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     lngID = Nz(DLookup(\"ID\", \"MSysResources\", \"Name = '\" & control & \"'\"), 0)\r\n     <span style=\"color:blue;\">If <\/span>Err.Number = 3078<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Tabelle 'MSysResources' mit den Images f&uuml;r die Anzeige im Ribbon fehlt.\" & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n             & \"F&uuml;gen Sie die Images mit dem Ribbon-Admin hinzu\", vbOKOnly + vbExclamation, _\r\n                 \"Tabelle MSysResources fehlt\"\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     <span style=\"color:blue;\">If <\/span>lngID = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Das Image '\" & control & \"' ist nicht in der Tabelle MSysResources vorhanden. \" & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n             & \"F&uuml;gen Sie dieses &uuml;ber den Kontextmen&uuml;eintrag 'Benutzerdefiniertes Image hinzuf&uuml;gen' \" & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n             & \"des image-Attributs des entsprechenden Ribbon-Steuerelements hinzu.\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> image = PicFromSharedResource_Ribbon(CStr(control))\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Callback-Prozedur zum Laden der Bilder in die Ribbon-Schaltfl&auml;chen<\/span><\/b><\/p>\n<p>Sie wird f&uuml;r jedes Steuer-element, das dieses Attribut enth&auml;lt, einmal aufgerufen. Die Prozedur greift auf Bilddateien zu, die in der Tabelle <b>MSysResources <\/b>hinterlegt sein m&uuml;ssen. Wie Sie diese dort hinterlegen, haben wir bereits im Beitrag <b>TreeView mit Kontextmen&uuml; <\/b>(<b>www.access-im-unternehmen.de\/1243<\/b>) kurz beschrieben &#8211; in diesem Fall verwenden wir allerdings Bilder im Format 32 x 32 statt 16 x 16.<\/p>\n<p>Die Funktion pr&uuml;ft mit einem Aufruf der <b>DLookup<\/b>-Funktion, ob sich in der Tabelle <b>MSysResources <\/b>ein Datensatz befindet, dessen Feld <b>Name <\/b>den Namen des Bildes aufweist und schreibt den gegebenenfalls gefundenen Prim&auml;rschl&uuml;sselwert in die Variable <b>lngID<\/b>. Die Datens&auml;tze in der Tabelle <b>MSysResources <\/b>sehen etwa wie in Bild 4 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_004.png\" alt=\"Die Tabelle MSysResources mit den Bildern f&uuml;r das Ribbon\" width=\"499,6607\" height=\"401,1486\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Die Tabelle MSysResources mit den Bildern f&uuml;r das Ribbon<\/span><\/b><\/p>\n<p>Hier kann es zu einem Fehler kommen, wenn die Tabelle <b>MSysResources <\/b>gar nicht vorhanden ist. Der Fehler hat die Nummer <b>3078<\/b>. Tritt dieser Fehler auf, zeigt die Prozedur eine entsprechende Fehlermeldung an und die Prozedur wird beendet.<\/p>\n<p> Anderenfalls pr&uuml;ft die Prozedur, ob <b>lngID <\/b>den Wert <b>0 <\/b>hat. Das ist der Fall, falls die <b>DLookup<\/b>-Funktion keinen passenden Datensatz gefunden hat.<\/p>\n<p>Auch in diesem Fall erscheint eine Meldung, die tunlichst w&auml;hrend der Entwicklung der Anwendung auftreten sollte, damit der Entwickler die fehlenden Bilddateien zur Tabelle <b>MSysResources<\/b> hinzuf&uuml;gen kann.<\/p>\n<p>Ist <b>lngID <\/b>jedoch nicht <b>0<\/b>, dann wurde ein passender Datensatz gefunden. Dann &uuml;bergeben wir den Namen des Steuerelements an die Funktion <b>PicFromSharedResource_Ribbon<\/b>, welche ein Objekt des Typs <b>StdPicture <\/b>zur&uuml;ckgibt. Dieses wird dann als Ergebnis der Callback-Funktion dem ausl&ouml;senden Steuer-element zugewiesen.<\/p>\n<p><!--30percent--><\/p>\n<p>Die Funktion <b>PicFromSharedResource_Ribbon <\/b>und einige andere n&uuml;tzliche Bildfunktionen finden Sie im Modul <b>mdlRibbonImages<\/b>.<\/p>\n<p>Damit haben wir nun folgende Dinge erledigt:<\/p>\n<ul>\n<li>Das Ribbon wird beim Aufruf &uuml;ber die Prozedur <b>onLoad <\/b>mit der Variablen <b>objRibbon_RibbonKunde <\/b>referenziert und <\/li>\n<li>die Steuer-elemente werden durch die Funktion <b>load-Image <\/b>mit den zugeordneten Bildern gef&uuml;llt.<\/li>\n<\/ul>\n<p><b>Ribbon anzeigen, wenn Kunde den Fokus im TreeView-Steuerelement erh&auml;lt<\/b><\/p>\n<p>Nun geht es weiter. Wir m&uuml;ssen daf&uuml;r sorgen, dass dieses Ribbon angezeigt wird, sobald der Benutzer im <b>TreeView<\/b>-Steuerelement des Formulars <b>frmKundenProjekte <\/b>auf eines der <b>Kunden<\/b>-Elemente klickt.<\/p>\n<p>Aber wie wollen wir das erledigen Immerhin gibt es nur die folgenden beiden M&ouml;glichkeiten, &uuml;berhaupt f&uuml;r die Anzeige von Ribbons zu sorgen, deren Definitionen in der Tabelle <b>USysRibbons <\/b>gespeichert sind:<\/p>\n<ul>\n<li>Durch Zuweisen des Namens des Ribbons an die Option <b>Name des Men&uuml;-bands <\/b>im Dialog <b>Access-Optionen <\/b>(siehe Bild 5) &#8211; dies stellt das Ribbon ein, das direkt nach dem Start von Access angezeigt werden soll -, oder<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_005.png\" alt=\"Einstellen des Anwendungsribbons\" width=\"549,6265\" height=\"313,278\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Einstellen des Anwendungsribbons<\/span><\/b><\/p>\n<li>durch Zuweisen des Namens des Ribbons an die Eigenschaft <b>Name des Men&uuml;bands <\/b>eines Formulars oder Berichts. Dies stellt ein, welches Ribbon angezeigt werden soll, wenn das Formular ge&ouml;ffnet wird.<\/li>\n<\/ul>\n<p>Die erste Option f&auml;llt flach, weil man diese zwar zur Laufzeit neu einstellen kann, die &Auml;nderung aber erst nach einem Neustart der Access-Anwendung wirksam wird.<\/p>\n<p>Bleibt die zweite Option &#8211; k&ouml;nnen wir damit mehr anfangen Ja, denn das Ribbon eines Formulars oder Berichts kann man auch zur Laufzeit &auml;ndern. Stellt man per VBA die Eigenschaft <b>RibbonName<\/b> eines Formulars oder Berichts auf einen neuen Wert ein, dann wird die angegebene Ribbon-Definition auch direkt angewendet.<\/p>\n<p>Nun z&auml;hlen wir eins und eins zusammen und probieren es so, dass wir das Ereignis abfangen, das beim Anklicken eines <b>TreeView<\/b>-Elements ausgel&ouml;st wird, dort pr&uuml;fen, welchen Elementtyp der Benutzer gerade angeklickt hat und in Abh&auml;ngigkeit davon das entsprechende Ribbon anzeigen &#8211; indem wir die Eigenschaft <b>RibbonName <\/b>anpassen.<\/p>\n<p><b>Zweites Ribbon hinzuf&uuml;gen<\/b><\/p>\n<p>Bevor wir das erledigen, f&uuml;gen wir noch das zweite Ribbon hinzu, das beim Anklicken eines Projekts angezeigt werden soll. Wenn wir nur einen Elementtyp im <b>TreeView<\/b>-Steuerelement haben, brauchen wir den ganzen Aufwand gar nicht in dieser Form zu betreiben.<\/p>\n<p>Die Definition des zweiten Ribbons f&uuml;r die Projekte finden Sie in Listing 3.<\/p>\n<pre>&lt;xml version=\"1.0\"&gt;\r\n&lt;customUI xmlns=\"http:\/\/schemas.microsoft.com\/office\/2009\/07\/customui\" onLoad=\"OnLoad_RibbonProjekt\" \r\n     loadImage=\"loadImage\"&gt;\r\n   &lt;ribbon&gt;\r\n     &lt;contextualTabs&gt;\r\n       &lt;tab<span style=\"color:blue;\">Set<\/span> idMso=\"TabSetFormReportExtensibility\"&gt;\r\n         &lt;tab id=\"tabProjekte\" label=\"Projekte\"&gt;\r\n           &lt;group id=\"grpProjekt\" label=\"Projekt\"&gt;\r\n             &lt;button id=\"btnProjektLoeschen\" image=\"folder2_delete_32\" getEnabled=\"getEnabled\" \r\n                 label=\"Projekt l&ouml;schen\" onAction=\"onAction\" size=\"large\"\/&gt;\r\n             &lt;button id=\"btnProjektUmbenennen\" image=\"edit_32\" label=\"Projekt umbenennen\" onAction=\"onAction\" \r\n                 size=\"large\"\/&gt;\r\n           &lt;\/group&gt;\r\n           &lt;group id=\"grpZwischenablage\" label=\"Zwischenablage\"&gt;\r\n             &lt;button id=\"btnAusschneiden\" image=\"cut_32\" label=\"Ausschneiden\" onAction=\"onAction\" size=\"large\"\/&gt;\r\n             &lt;button id=\"btnKopieren\" image=\"copy_32\" label=\"Kopieren\" onAction=\"onAction\" size=\"large\"\/&gt;\r\n             &lt;button id=\"btnEinfuegen\" image=\"clipboard_paste_32\" label=\"Einf&uuml;gen\" onAction=\"onAction\" size=\"large\"\/&gt;\r\n           &lt;\/group&gt;\r\n         &lt;\/tab&gt;\r\n       &lt;\/tabSet&gt;\r\n     &lt;\/contextualTabs&gt;\r\n   &lt;\/ribbon&gt;\r\n&lt;\/customUI&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Dieses Ribbon soll angezeigt werden, wenn der Benutzer ein Element des Typs Projekt anklickt.<\/span><\/b><\/p>\n<p>Ein wichtiger Unterschied zwischen den beiden Ribbon-Definitionen ist, dass die zweite eine andere Callback-Methode f&uuml;r das Callback-Attribut <b>onLoad <\/b>festlegt, n&auml;mlich in diesem Fall <b>OnLoad_RibbonProjekt<\/b>.<\/p>\n<p>F&uuml;r die zweite Ribbon-Definition m&uuml;ssen wir n&auml;mlich eine zweite Variable mit einem Verweis f&uuml;llen, damit wir unabh&auml;ngig auf die beiden Ribbons zugreifen k&ouml;nnen. Die Variable deklarieren wir wie folgt: <\/p>\n<pre><span style=\"color:blue;\">Public <\/span>objRibbon_RibbonProjekt<span style=\"color:blue;\"> As <\/span>IRibbonUI<\/pre>\n<p>Als Callback-Methode definieren wir diese Prozedur, welche die Variable <b>objRibbon_RibbonProjekt <\/b>mit dem <b>IRibbonUI<\/b>-Objekt f&uuml;llt:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>onLoad_RibbonProjekt(ribbon<span style=\"color:blue;\"> As <\/span>IRibbonUI)\r\n     <span style=\"color:blue;\">Set<\/span> objRibbon_RibbonProjekt = ribbon\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b>Ribbons scharf schalten<\/b><\/p>\n<p>Wenn Sie die beiden Ribbon-Definitionen in die Tabelle <b>USysRibbons <\/b>eingetragen haben, sind diese noch nicht verf&uuml;gbar. Das hei&szlig;t, wenn Sie nun einen der beiden Ribbon-Namen <b>RibbonKunde <\/b>oder <b>RibbonProjekt <\/b>f&uuml;r die Eigenschaft <b>Name des Men&uuml;bands <\/b>des Formulars eintragen, wird dieses beim &Ouml;ffnen des Formulars noch nicht angezeigt. Der Grund ist, dass die Ribbon-Definitionen aus der Tabelle einmal &#8222;scharf geschaltet&#8220; werden m&uuml;ssen, und das geschieht beim Start der Anwendung.<\/p>\n<p>Zu diesem Zeitpunkt durchsucht Access die Tabelle <b>USysRibbons <\/b>und h&auml;lt die Eintr&auml;ge f&uuml;r die Auswahl in den Access-Optionen und f&uuml;r die Eigenschaft <b>Name des Men&uuml;bands <\/b>bereit. Erst dann k&ouml;nnen Sie diese Eintr&auml;ge auch f&uuml;r die Eigenschaft ausw&auml;hlen.<\/p>\n<p>Damit k&ouml;nnen wir uns nun darum k&uuml;mmern, dass die Ribbons beim Anklicken der entsprechenden Elemente des <b>TreeView<\/b>-Steuerelements aktiviert und angezeigt werden.<\/p>\n<p><b>Ribbon, wechsle dich<\/b><\/p>\n<p>Das richtige Ereignis f&uuml;r diesen Zweck ist das <b>Click<\/b>-Ereignis des <b>TreeView<\/b>-Steuerelements. Dieses legen Sie an, indem Sie das Klassenmodul des Formulars &ouml;ffnen und im Codefenster im linken Kombinationsfeld den Eintrag <b>ctlTreeView <\/b>ausw&auml;hlen und im rechten Kombinationsfeld den Eintrag <b>Click<\/b>. Dies legt automatisch die Ereignisprozedur <b>ctlTreeView_Click<\/b> an (siehe Bild 6). <\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_006.png\" alt=\"Anlegen der Ereignisprozedur ctlTreeView_Click\" width=\"649,559\" height=\"285,7297\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Anlegen der Ereignisprozedur ctlTreeView_Click<\/span><\/b><\/p>\n<p>Die so angelegte Prozedur f&uuml;llen wir wie in Listing 4 mit Code. Die Prozedur referenziert zun&auml;chst &uuml;ber die Eigenschaft <b>SelectedItem <\/b>das aktuell markierte Element und speichert den Verweis in der Objektvariablen <b>objNode<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ctlTreeview_Click()\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> objNode = objTreeView.SelectedItem\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         Select Case <span style=\"color:blue;\">Left<\/span>(objNode.Key, 1)\r\n             <span style=\"color:blue;\">Case <\/span>\"k\"\r\n                 Me.RibbonName = \"RibbonKunde\"\r\n                 objRibbon_RibbonKunde.ActivateTab \"tabKunde\"\r\n             <span style=\"color:blue;\">Case <\/span>\"p\"\r\n                 Me.RibbonName = \"RibbonProjekt\"\r\n                 objRibbon_RibbonProjekt.ActivateTab \"tabProjekte\"\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         Me.RibbonName = \"\"\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 4: Das Click-Ereignis stellt die RibbonName-Eigenschaft auf das gew&uuml;nschte Ribbon ein.<\/span><\/b><\/p>\n<p>Dann pr&uuml;ft sie, ob &uuml;berhaupt ein Element markiert ist. Das ist eigentlich nur der Fall, wenn die zugrunde liegende Tabelle <b>tblKunden <\/b>keine Datens&auml;tze enth&auml;lt &#8211; aber wir wollen den Fall dennoch abbilden. In diesem Fall wird der <b>Else<\/b>-Zweig der <b>If&#8230;Then<\/b>-Bedingung ausgef&uuml;hrt und die Eigenschaft <b>RibbonName <\/b>des Formulars auf eine leere Zeichenkette eingestellt.<\/p>\n<p>Anderenfalls kann das aktuell markierte Element des <b>TreeView<\/b>-Steuerelements entweder ein Kunden- oder ein Projekt-Element sein. Das pr&uuml;fen wir anhand des ersten Buchstabens der <b>Key<\/b>-Eigenschaft. Entspricht dieser dem Buchstaben <b>k<\/b>, handelt es sich um einen Kunden, im Falle von <b>p <\/b>um ein Projekt.<\/p>\n<p>Im Falle eines Kunden-Elements stellt die Prozedur die Eigenschaft <b>RibbonName <\/b>auf den Wert <b>RibbonKunde <\/b>ein. Und es folgt noch eine weitere Anweisung, die schlie&szlig;lich erkl&auml;rt, warum wir einen Verweis auf das Ribbon in der Variablen <b>objRibbon_RibbonKunde <\/b>gespeichert haben: Weil wir dessen Methode <b>ActivateTab <\/b>nutzen m&uuml;ssen, um das nun eingeblendete Ribbon-Tab auch zum aktiven Ribbon-Tab zu machen.<\/p>\n<p>Wenn wir das nicht erledigen w&uuml;rden, s&auml;he das Ribbon nach der einfachen Einstellung der Eigenschaft wie in Bild 7 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_007.png\" alt=\"Ribbon nur nach Einblendung des kontextsensitiven Ribbon-Tabs ...\" width=\"549,6265\" height=\"167,9415\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Ribbon nur nach Einblendung des kontextsensitiven Ribbon-Tabs &#8230;<\/span><\/b><\/p>\n<p>Nach dem Aufruf der Methode <b>ActivateTab <\/b>mit dem Namen des Ribbon-Tabs aus der Ribbon-Definition sieht das Ribbon jedoch wie gew&uuml;nscht aus &#8211; siehe Bild 8.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_008.png\" alt=\"... und nach dem Aktivieren dieses Tabs.\" width=\"549,6265\" height=\"167,0714\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: &#8230; und nach dem Aktivieren dieses Tabs.<\/span><\/b><\/p>\n<p>Auf die gleiche Weise verl&auml;uft der zweite Zweig der <b>Select Case<\/b>-Bedingung, die das Ribbon f&uuml;r die <b>Projekt<\/b>-Elemente aufruft. Dieses Ribbon sieht nach der Aktivierung schlie&szlig;lich wie in Bild 9 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_009.png\" alt=\"Das Ribbon f&uuml;r die Projekt-Elemente\" width=\"549,6265\" height=\"165,7307\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Das Ribbon f&uuml;r die Projekt-Elemente<\/span><\/b><\/p>\n<p><b>Optimierung<\/b><\/p>\n<p>Nun kommt es in manchen Access-Versionen dazu, dass das <b>IRibbonUI<\/b>-Objekt nicht gefunden werden kann. Offenbar geschieht das F&uuml;llen des Objekts &uuml;ber die Callback-Methode (zum Beispiel <b>onLoad_RibbonKunde<\/b>) nicht schnell genug, sodass wir direkt nach dem F&uuml;llen noch nicht auf die Methode <b>ActivateTab <\/b>dieses Objekts zugreifen k&ouml;nnen.<\/p>\n<p>F&uuml;r diesen Fall haben wir eine kleine Optimierung vorgesehen, die vor dem Aufruf der <b>ActivateTab<\/b>-Methode mit <b>On Error Resume Next <\/b>die Fehlerbehandlung deaktiviert (siehe Listing 5). Auf diese Weise wirft die <b>ActivateTab<\/b>-Methode auch dann keinen Fehler, wenn <b>objRibbon_RibbonKunde <\/b>noch nicht vorhanden ist.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ctlTreeview_Click()\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> objNode = objTreeView.SelectedItem\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         Select Case <span style=\"color:blue;\">Left<\/span>(objNode.Key, 1)\r\n             <span style=\"color:blue;\">Case <\/span>\"k\"\r\n                 Me.RibbonName = \"RibbonKunde\"\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 objRibbon_RibbonKunde.ActivateTab \"tabKunde\"\r\n                 <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> Err.Number = 0<span style=\"color:blue;\"> Then<\/span>\r\n                     Me.TimerInterval = 300\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">Case <\/span>\"p\"\r\n                 Me.RibbonName = \"RibbonProjekt\"\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 objRibbon_RibbonProjekt.ActivateTab \"tabProjekte\"\r\n                 <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> Err.Number = 0<span style=\"color:blue;\"> Then<\/span>\r\n                     Me.TimerInterval = 300\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         Me.RibbonName = \"\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Verbesserung des Ereignisses ctlTreeView_Click<\/span><\/b><\/p>\n<p>Stattdessen fragen wir nach der <b>ActivateTab<\/b>-Methode ab, ob <b>Err.Number <\/b>nicht mehr den Wert <b>0 <\/b>hat, also ob ein Fehler aufgetreten ist. In diesem Fall stellen wir die Eigenschaft <b>TimerInterval <\/b>des Formulars auf den Wert <b>300 <\/b>ein, was dazu f&uuml;hrt, dass die Ereignisprozedur, die durch das Ereignis <b>Bei Zeitgeber <\/b>ausgel&ouml;st wird, in 300 Millisekunden ausgel&ouml;st wird.<\/p>\n<p>Was aber geschieht in dieser Prozedur, die wir ja bisher noch gar nicht angelegt haben Diese Prozedur sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Timer()\r\n     Me.TimerInterval = 0\r\n     ctlTreeview_Click\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Sie stellt also erst einmal die Eigenschaft <b>Zeitgeberintervall <\/b>wieder auf den Wert <b>0 <\/b>ein, was bewirkt, dass diese Ereignisprozedur zun&auml;chst erst einmal nicht wieder aufgerufen wird. Dann ruft sie einfach erneut die Prozedur <b>ctlTreeView_Click <\/b>auf. Mittlerweile d&uuml;rfte mit den 300 Millisekunden gen&uuml;gend Zeit vergangen sein, dass die Objektvariable <b>objRibbon_Kunde <\/b>mit dem Verweis auf das Ribbon gef&uuml;llt ist und wir die Methode <b>ActivateTab <\/b>aufrufen k&ouml;nnen.<\/p>\n<p><b>Ribbon aktivieren beim &Ouml;ffnen des Formulars<\/b><\/p>\n<p>Wenn der Benutzer das Formular &ouml;ffnet, klickt er ja nicht direkt einen Eintrag im <b>TreeView<\/b>-Steuerelement an. Damit dennoch direkt der erste Eintrag in diesem Steuer-element markiert ist und das passende Ribbon angezeigt wird, erweitern wir die Ereignisprozedur, die beim &Ouml;ffnen des Formulars ausgel&ouml;st wird, um wenige Zeilen:<\/p>\n<pre><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;\">With<\/span> objTreeView\r\n         .Appearance = ccFlat\r\n         .BorderStyle = ccNone\r\n         .LineStyle = tvwRootLines\r\n         .Style = tvwTreelinesPlusMinusPictureText\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     FillTreeView\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objTreeView.Nodes.count = 0<span style=\"color:blue;\"> Then<\/span>\r\n         objTreeView.SelectedItem = objTreeView.Nodes(1)\r\n         Me.TimerInterval = 300\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Nach dem Aufruf der Prozedur <b>FillTreeView <\/b>pr&uuml;fen wir, ob das Steuer-element &uuml;berhaupt Elemente enth&auml;lt. Ist das der Fall, markieren wir das erste Element, indem wir es der Eigenschaft <b>SelectedItem <\/b>zuweisen.<\/p>\n<p>Dann stellen wir wieder die Eigenschaft <b>Zeitgeberintervall <\/b>auf den Wert <b>300 <\/b>ein, damit die Ereignisprozedur <b>Bei Zeitgeber <\/b>nach 300 Millisekunden ausgel&ouml;st wird und dann die Ereignisprozedur <b>ctlTreeView_Click <\/b>aufruft. Dies sorgt dann f&uuml;r die Anzeige des Ribbons f&uuml;r das erste Element.<\/p>\n<p><b>Schaltfl&auml;chen mit Ereignissen f&uuml;llen<\/b><\/p>\n<p>Damit die Ribbon-Schaltfl&auml;chen auch etwas bewirken, haben wir f&uuml;r diese das Attribut <b>onAction <\/b>auf die Callback-Funktion <b>onAction <\/b>eingestellt. Diese Callback-Funktion f&uuml;gen wir ebenfalls zum Modul <b>mdlRibbons <\/b>hinzu. Die Funktion erh&auml;lt mit dem Parameter <b>control <\/b>ein Objekt des Typs <b>IRibbonControl<\/b>. Dieses bietet interessante Eigenschaften, zum Beispiel die Eigenschaft <b>ID<\/b>. Diese liefert den Namen des ausl&ouml;senden Steuerelements, auf das wir in der Callback-Funktion aus Listing 6 dann mit <b>control.ID <\/b>zugreifen.<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>onAction(control<span style=\"color:blue;\"> As <\/span>IRibbonControl)\r\n     Select Case control.ID\r\n         <span style=\"color:blue;\">Case <\/span>\"btnKundeLoeschen\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnKundenLoeschen' angeklickt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"btnNeuesProjekt\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnNeuesProjekt' angeklickt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"btnKundeUmbenennen\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnKundeUmbenennen' angeklickt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"btnAusschneiden\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnAusschneiden' angeklickt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"btnKopieren\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnKopieren' angeklickt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"btnEinfuegen\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnEinfuegen' angeklickt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"btnProjektLoeschen\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnProjektLoeschen' angeklickt\"\r\n         <span style=\"color:blue;\">Case <\/span>\"btnProjektUmbenennen\"\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Schaltfl&auml;che 'btnProjektUmbenennen' angeklickt\"\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"Unbehandeltes Ribbon-Ereignis f&uuml;r: \" & control.ID\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: Diese Prozedur wird beim Anklicken von Ribbon-Schaltfl&auml;chen ausgel&ouml;st<\/span><\/b><\/p>\n<p>Hier haben wir in einer <b>Select Case<\/b>-Bedingung f&uuml;r jede Schaltfl&auml;che einen eigenen <b>Case<\/b>-Zweig eingetragen, der jeweils in einer Meldung anzeigt, welche Schaltfl&auml;che der Benutzer angeklickt hat. Diese <b>MsgBox<\/b>-Anweisungen k&ouml;nnen Sie durch die gew&uuml;nschten Anweisungen oder auch durch Aufrufe entsprechender Prozeduren ersetzen.<\/p>\n<p><b>Alternative: Ribbon komplett neu aufbauen<\/b><\/p>\n<p>In einer zweiten Beispieldatenbank namens <b>TreeViewMitRibbon_StartFromScratch.accdb <\/b>haben wir eine Alternative zur vorherigen Variante implementiert. Hier haben wir das Ribbon so definiert, dass die vorhandenen Elemente mit dem Attribut <b>startFromScratch=&#8220;true&#8220; <\/b>entfernt werden und nur das von uns definierte <b>tab<\/b>-Element erscheint.<\/p>\n<p>Damit sparen wir uns erstens die <b>contextualTabs<\/b>-Elemente und auch das zeitverz&ouml;gerte Einstellen des kontextsensitiven <b>tab<\/b>-Elements. Das Ergebnis soll wie in Bild 10 aussehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_04\/pic_1244_010.png\" alt=\"Komplett neues Tab statt ContextualTab\" width=\"499,6607\" height=\"404,0408\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Komplett neues Tab statt ContextualTab<\/span><\/b><\/p>\n<p>Die Ribbon-Definition sieht in gek&uuml;rzter Form wie in Listing 7 aus.<\/p>\n<pre>&lt;xml version=\"1.0\"&gt;\r\n&lt;customUI xmlns=\"http:\/\/schemas.microsoft.com\/office\/2009\/07\/customui\" onLoad=\"OnLoad_RibbonKunde\"\r\n     loadImage=\"loadImage\"&gt;\r\n   &lt;ribbon startFromScratch=\"true\"&gt;\r\n     &lt;tabs&gt;\r\n       &lt;tab id=\"tabKunde\" label=\"Kunden\"&gt;\r\n         &lt;group id=\"grpKunde\" label=\"Kunde\"&gt;\r\n           &lt;button image=\"user_delete_32\" label=\"Kunde l&ouml;schen\" id=\"btnKundeLoeschen\" onAction=\"onAction\" \r\n               size=\"large\"\/&gt;\r\n         ...\r\n       &lt;\/tab&gt;\r\n     &lt;\/tabs&gt;\r\n   &lt;\/ribbon&gt;\r\n&lt;\/customUI&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Vereinfachung des Ribbons und Angabe des startFromScratch-Attributs<\/span><\/b><\/p>\n<p>Und auch die Prozedur, die beim Anklicken der Elemente ausgel&ouml;st wird, konnten wir erheblich vereinfachen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ctlTreeview_Click()\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> objNode = objTreeView.SelectedItem\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         Select Case <span style=\"color:blue;\">Left<\/span>(objNode.Key, 1)\r\n             <span style=\"color:blue;\">Case <\/span>\"k\"\r\n                 Me.RibbonName = \"RibbonKunde\"\r\n             <span style=\"color:blue;\">Case <\/span>\"p\"\r\n                 Me.RibbonName = \"RibbonProjekt\"\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         Me.RibbonName = \"\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Und auch das Ende der Prozedur <b>Form_Load <\/b>&auml;ndern wir wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     ...\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objTreeView.Nodes.count = 0<span style=\"color:blue;\"> Then<\/span>\r\n         objTreeView.SelectedItem = objTreeView.Nodes(1)\r\n         ctlTreeview_Click\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Dieser Beitrag hat gezeigt, wie Sie Ribbon-Befehle zu den Eintr&auml;gen eines <b>TreeView<\/b>-Steuerelements anzeigen k&ouml;nnen. Damit erhalten Sie eine Alternative zu den Kontextmen&uuml;-Befehlen, die sonst zur Verwaltung von Daten in Treeviews verwendet werden.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>TreeViewMitRibbon.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/A118882A-5B2B-4199-B21A-036E376D01AA\/aiu_1244.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die Programmierung des TreeView-Steuerelements haben wir bereits in vielen Beitr&auml;gen dokumentiert. Dort haben auch auch gezeigt, wie Sie Befehle f&uuml;r spezielle Elementtypen im TreeView in Kontextmen&uuml;s unterbringen, die beim Rechtsklick auf die jeweiligen Elemente angezeigt werden. Es gibt noch eine andere M&ouml;glichkeit, solche Befehle abh&auml;ngig vom Elementtyp abzubilden: als Ribbon-Eintr&auml;ge. Wie das gelingt, zeigt der vorliegende Beitrag.<\/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":[662020,66042020,44000023],"tags":[],"class_list":["post-55001244","post","type-post","status-publish","format-standard","hentry","category-662020","category-66042020","category-Mit_Formularen_arbeiten"],"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>TreeView mit Ribbon-Eintr&auml;gen - 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\/TreeView_mit_RibbonEintraegen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TreeView mit Ribbon-Eintr&auml;gen\" \/>\n<meta property=\"og:description\" content=\"Die Programmierung des TreeView-Steuerelements haben wir bereits in vielen Beitr&auml;gen dokumentiert. Dort haben auch auch gezeigt, wie Sie Befehle f&uuml;r spezielle Elementtypen im TreeView in Kontextmen&uuml;s unterbringen, die beim Rechtsklick auf die jeweiligen Elemente angezeigt werden. Es gibt noch eine andere M&ouml;glichkeit, solche Befehle abh&auml;ngig vom Elementtyp abzubilden: als Ribbon-Eintr&auml;ge. Wie das gelingt, zeigt der vorliegende Beitrag.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-08-05T10:25:23+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/973f7a55989f44a69836d217e6b1c653\" \/>\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=\"19\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"TreeView mit Ribbon-Eintr&auml;gen\",\"datePublished\":\"2020-08-05T10:25:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/\"},\"wordCount\":2960,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/973f7a55989f44a69836d217e6b1c653\",\"articleSection\":[\"2020\",\"4\\\/2020\",\"Mit Formularen arbeiten\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/\",\"name\":\"TreeView mit Ribbon-Eintr&auml;gen - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/973f7a55989f44a69836d217e6b1c653\",\"datePublished\":\"2020-08-05T10:25:23+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/973f7a55989f44a69836d217e6b1c653\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/973f7a55989f44a69836d217e6b1c653\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/TreeView_mit_RibbonEintraegen\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"TreeView mit Ribbon-Eintr&auml;gen\"}]},{\"@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":"TreeView mit Ribbon-Eintr&auml;gen - 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\/TreeView_mit_RibbonEintraegen\/","og_locale":"de_DE","og_type":"article","og_title":"TreeView mit Ribbon-Eintr&auml;gen","og_description":"Die Programmierung des TreeView-Steuerelements haben wir bereits in vielen Beitr&auml;gen dokumentiert. Dort haben auch auch gezeigt, wie Sie Befehle f&uuml;r spezielle Elementtypen im TreeView in Kontextmen&uuml;s unterbringen, die beim Rechtsklick auf die jeweiligen Elemente angezeigt werden. Es gibt noch eine andere M&ouml;glichkeit, solche Befehle abh&auml;ngig vom Elementtyp abzubilden: als Ribbon-Eintr&auml;ge. Wie das gelingt, zeigt der vorliegende Beitrag.","og_url":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-08-05T10:25:23+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/973f7a55989f44a69836d217e6b1c653","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"19\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"TreeView mit Ribbon-Eintr&auml;gen","datePublished":"2020-08-05T10:25:23+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/"},"wordCount":2960,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/973f7a55989f44a69836d217e6b1c653","articleSection":["2020","4\/2020","Mit Formularen arbeiten"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/","url":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/","name":"TreeView mit Ribbon-Eintr&auml;gen - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/973f7a55989f44a69836d217e6b1c653","datePublished":"2020-08-05T10:25:23+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/973f7a55989f44a69836d217e6b1c653","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/973f7a55989f44a69836d217e6b1c653"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/TreeView_mit_RibbonEintraegen\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"TreeView mit Ribbon-Eintr&auml;gen"}]},{"@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\/55001244","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=55001244"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001244\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001244"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001244"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001244"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}