{"id":55001327,"date":"2021-10-01T00:00:00","date_gmt":"2021-09-29T22:11:44","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1327"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"AccessOptionen_per_Ribbon_aendern","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/","title":{"rendered":"Access-Optionen per Ribbon &auml;ndern"},"content":{"rendered":"<p><b>Es gibt einige Access-Optionen, die man immer wieder nutzt. In meinem Fall ist es zum Beispiel die Einstellung, ob Formulare nun als &uuml;berlappende Fenster oder als Dokumente im Registerkartenformat angezeigt werden sollen. Sicher haben Sie &auml;hnliche Einstellungen, die Sie oft &auml;ndern oder die Sie vielleicht einfach nur schnell einsehen m&ouml;chten &#8211; was bei dem mittlerweile recht umfangreich gewordenen Optionen-Dialog schon einige Sekunden kosten kann. Warum also nicht ein COM-Add-In bauen, das die Informationen der wichtigsten Access-Einstellungen immer direkt im Ribbon anzeigt &#8211; anstatt irgendwo versteckt im Optionen-Dialog Und da wir mit twinBASIC auch noch ein praktisches Tool zum Erstellen von COM-Add-Ins zur Hand haben, k&ouml;nnen wir direkt loslegen!<\/b><\/p>\n<h2>Voraussetzung: Visual Studio Code und twinBASIC<\/h2>\n<p>Wenn Sie dauerhafte Erg&auml;nzungen oder &Auml;nderungen am Ribbon vornehmen wollen, ben&ouml;tigen Sie ein COM-Add-In. Eine andere M&ouml;glichkeit gibt es nur, wenn Sie mit den eingebauten Funktionen zum Anpassen der Benutzeroberfl&auml;che arbeiten wollen &#8211; und die sind bei Weitem nicht ausreichend.<\/p>\n<p>Ein COM-Add-In konnten Sie fr&uuml;her mit Visual Studio 6 bauen, heutzutage mit Visual Studio .NET. Das ist allerdings nicht besonders komfortabel und erfordert umfangreichere Softwarevoraussetzungen als Visual Studio 6 gebaute COM-Add-Ins. Seit kurzem gibt es allerdings eine Erweiterung namens twinBASIC f&uuml;r Visual Studio Code, mit der Sie zum Beispiel COM-Add-Ins f&uuml;r Access und den VBA-Editor programmieren k&ouml;nnen. Wie das geht, haben wir bereits in den Beitr&auml;gen <b>twinBASIC &#8211; VB\/VBA mit moderner Umgebung <\/b>(<b>www.access-im-unternehmen.de\/1303<\/b>), <b>twinBASIC &#8211; COM-Add-Ins f&uuml;r Access <\/b>(<b>www.access-im-unternehmen.de\/1306<\/b>) und anderen erl&auml;utert.<\/p>\n<p>Im erstgenannten Beitrag erfahren Sie alles &uuml;ber die Installation, in letzterem die Grundlagen f&uuml;r das Erstellen von COM-Add-Ins. Details zu diesen Themen finden Sie in den genannten Beitr&auml;gen.<\/p>\n<h2>Neues COM-Add-In anlegen<\/h2>\n<p>Um ein neues COM-Add-In anzulegen, klicken Sie in Visual Studio Code links auf das twinBASIC-Symbol. Es erscheint eine Liste mit Projektvorlagen, wo Sie die Vorlage <b>Sample 5 MyCOMAddin <\/b>ausw&auml;hlen (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_1327_001.png\" alt=\"Erstellen eines neuen COM-Add-Ins\" width=\"700\" height=\"316,4383\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Erstellen eines neuen COM-Add-Ins<\/span><\/b><\/p>\n<p>Anschlie&szlig;end erscheint ein Dialog, in dem Sie die anzulegende Datei samt Verzeichnis ausw&auml;hlen. Hier geben wir <b>amvAccessOptionsGoRibbon.twinproj <\/b>an.<\/p>\n<p>Dies f&uuml;gt einige Dateien zum gew&auml;hlten Verzeichnis hinzu, von denen die folgenden f&uuml;r uns interessant sind:<\/p>\n<ul>\n<li><b>amvAccessOptionsGoRibbon_ACCESS_RegisterAddin32.reg<\/b>: Datei zum Hinzuf&uuml;gen der Registry-Eintr&auml;ge f&uuml;r das COM-Add-In<\/li>\n<li><b>amvAccessOptionsGoRibbon_ACCESS_UnregisterAddin32.reg<\/b>: Datei zum Entfernen der Registry-Eintr&auml;ge f&uuml;r das COM-Add-In<\/li>\n<li><b>amvAccessOptionsGoRibbon_myCOMAddin.code-workspace<\/b>: Arbeitsumgebung<\/li>\n<li><b>amvAccessOptionsGoRibbon_myCOMAddin.twinproj<\/b>: Projektdatei<\/li>\n<\/ul>\n<p>Das Projekt wird allerdings auch direkt in Visual Studio Code angezeigt.<\/p>\n<h2>Was bietet die Vorlage<\/h2>\n<p>Mit der Vorlage erhalten Sie bereits fast alles, was Sie ben&ouml;tigen:<\/p>\n<ul>\n<li>Die Implementierung der Schnittstelle <b>IDTExtensibility2<\/b>, die einige Ereignisprozeduren bereitstellt, die zu verschiedenen Zeitpunkten beim Verwenden des COM-Add-Ins ausgel&ouml;st werden &#8211; zum Beispiel beim Start (<b>OnConnection<\/b>)<\/li>\n<li>Die Implementierung der Schnittstelle <b>IRibbonExtensibility <\/b>in Form der Ereignisprozedur <b>GetCustomUI<\/b>. Diese wird beim Start des COM-Add-Ins ausgel&ouml;st und stellt das Ribbon zusammen, &uuml;ber das die Benutzeroberfl&auml;che beziehungsweise die Funktionen des COM-Add-Ins bereitgestellt werden sollen.<\/li>\n<li>Eine von dieser Ereignisprozedur aufgerufene Callback-Funktion, die zeigt, wie Sie Funktionen &uuml;ber das Ribbon aufrufen k&ouml;nnen.<\/li>\n<\/ul>\n<h2>COM-Add-In zum Laufen bringen<\/h2>\n<p>Dementsprechend brauchen Sie nur zwei Schritte zu erledigen, damit das COM-Add-In l&auml;uft:<\/p>\n<ul>\n<li>Das COM-Add-In kompilieren, indem Sie auf die Schaltfl&auml;che Build klicken (siehe Bild 2).<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_1327_002.png\" alt=\"COM-Add-In kompilieren\" width=\"424,5589\" height=\"522,8365\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: COM-Add-In kompilieren<\/span><\/b><\/p>\n<li>Die Registrierungsdatei <b>amvAccessOptionsGoRibbon_ACCESS_RegisterAddin32.reg<\/b> starten, indem Sie diese doppelt anklicken und die folgenden Meldungen best&auml;tigen.<\/li>\n<\/ul>\n<p>Wenn Sie nun eine Access-Datenbank &ouml;ffnen, erscheint ein neuer Eintrag namens <b>twinBASIC Test <\/b>im Ribbon mit einer eigenen Schaltfl&auml;che (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_1327_003.png\" alt=\"Das COM-Add-In ist nach wenigen Mausklicks einsatzbereit\" width=\"649,559\" height=\"207,4087\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Das COM-Add-In ist nach wenigen Mausklicks einsatzbereit<\/span><\/b><\/p>\n<p>Im Gegensatz zu dem COM-Add-In, das wir wie im Beitrag  <b>twinBASIC &#8211; COM-Add-Ins f&uuml;r Access <\/b>erstellt haben, kann twinBASIC nun auch benutzerdefinierte Icons anzeigen. Wie Sie diese hinzuf&uuml;gen und &uuml;ber entsprechende Callback-Funktionen aufrufen, zeigen wir im Beitrag <b>Benutzerdefinierte Bilder in twinBASIC <\/b>(<b>www.access-im-unternehmen.de\/1325<\/b>).<\/p>\n<h2>COM-Add-In vorbereiten<\/h2>\n<p>Da wir wissen, dass wir das COM-Add-In mit Access einsetzen wollen, k&ouml;nnen wir eine Objektvariable speziell zum Aufnehmen der aktuellen Access-Instanz deklarieren:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>objAccess<span style=\"color:blue;\"> As <\/span>Access.Application<\/pre>\n<p>Au&szlig;erdem weisen wir diese in der Prozedur <b>OnConnection <\/b>wie folgt gezielt zu:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>OnConnection(ByVal Application<span style=\"color:blue;\"> As Object<\/span>, _\r\n         ByVal ConnectMode<span style=\"color:blue;\"> As <\/span>ext_ConnectMode, _\r\n         ByVal AddInInst<span style=\"color:blue;\"> As Object<\/span>, _\r\n         ByRef custom<span style=\"color:blue;\"> As Variant<\/span>()) _\r\n     Implements IDTExtensibility2.OnConnection\r\n     <span style=\"color:blue;\">Set<\/span> objAccess = Application\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier tragen wir den mit dem Parameter <b>Application <\/b>&uuml;bergebenen Verweis auf die aktuelle Access-Instanz in die Variable <b>objAccess <\/b>ein.<\/p>\n<h2>Optionen mit dem Ribbon einstellen<\/h2>\n<p>Um Optionen mit dem Ribbon einzustellen, ben&ouml;tigen wir mehr als nur ein paar Schaltfl&auml;chen. Immerhin wollen wir ja vor dem &Auml;ndern einer Option auch wissen, wie ihr aktueller Wert lautet! Also ben&ouml;tigen wir Steuerelemente wie Kontrollk&auml;stchen, Textfelder et cetera.<\/p>\n<p>Da wir diese dynamisch einlesen und auch anpassen wollen, stellen wir ihre Werte zu Beginn mit entsprechenden Callback-Funktionen ein. Sp&auml;ter &auml;ndern wir diese dann &uuml;ber das Ribbon und sorgen daf&uuml;r, dass die &Auml;nderungen sich auch in den entsprechenden Access-Optionen niederschlagen.<\/p>\n<p>Wir beginnen mit einer ersten Option, um uns den Ablauf anzusehen. Dies soll der Titel der Access-Anwendung sein. Der Vorteil gegen&uuml;ber einigen anderen Optionen ist, dass wir &Auml;nderungen direkt in der Titelleiste angezeigt bekommen &#8211; im Gegensatz zu vielen anderen Optionen, die sich erst beim erneuten &Ouml;ffnen der Datenbankanwendung zeigen.<\/p>\n<p>Also f&uuml;gen wir der Ribbon-Definition ein Textfeld hinzu. Danach sieht Prozedur <b>GetCustomUI <\/b>zur Definition des Ribbons wie in Listing 1 aus. Hier finden wir statt der bisher vorhandenen Schaltfl&auml;che ein <b>editBox<\/b>-Element. F&uuml;r dieses haben wir die Eigenschaft <b>label <\/b>auf <b>Datenbanktitel <\/b>und <b>maxLength <\/b>auf <b>255 <\/b>eingestellt. Letztere sorgt daf&uuml;r, dass der Titel die maximale Zeichenzahl von <b>255 <\/b>nicht &uuml;berschreitet. Damit die <b>editBox<\/b>-Steuerelemente breit genug dargestellt werden, setzen wir au&szlig;erdem das Attribut <b>sizeString <\/b>auf den Wert <b>xxxxxxxxxxxxxxxxxxxxxxxxx<\/b>. Au&szlig;erdem haben wir gleich zwei Callback-Attribute definiert:<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>GetCustomUI(ByVal RibbonID<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span> _\r\n     Implements IRibbonExtensibility.GetCustomUI\r\n     <span style=\"color:blue;\">Dim <\/span>strXML<span style=\"color:blue;\"> As String<\/span>\r\n     strXML &= \"&lt;xml version=\"1.0\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"&lt;customUI xmlns=\"http:\/\/schemas.microsoft.com\/office\/2009\/07\/customui\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"  &lt;ribbon&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"    &lt;tabs&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"      &lt;tab id=\"tabOptions\" label=\"Optionen\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"        &lt;group id=\"grpThisDatabase\" label=\"&lt;Aktuelle Datenbank&gt;\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;editBox label=\"Datenbanktitel:\"id=\"txtTitle\" maxLength=\"255\" \" _\r\n            & \" sizeString=\"xxxxxxxxxxxxxxxxxxxxxxxxx\" getText=\"getText\" onChange=\"onChange\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"        &lt;\/group&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"      &lt;\/tab&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"    &lt;\/tabs&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"  &lt;\/ribbon&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"&lt;\/customUI&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     Return strXML\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Einlesen des Ribbons mit dem Textfeld zum Festlegen des Datenbanktitels<\/span><\/b><\/p>\n<ul>\n<li><b>getText<\/b>: Gibt eine Callback-Funktion an, die beim erstmaligen Anzeigen oder der Anforderung der Aktualisierung der Anzeige ausgel&ouml;st werden soll. Hier wollen wir den aktuellen Titel aus den Access-Optionen einlesen und anschlie&szlig;end im <b>editBox<\/b>-Steuerelement anzeigen.<\/li>\n<li><b>onChange<\/b>: Gibt eine Callback-Funktion an, die beim &Auml;ndern des Wertes des <b>editBox<\/b>-Steuerelements ausgel&ouml;st wird. Hiermit wollen wir nach &Auml;nderungen durch den Benutzer den neuen Wert in die Access-Optionen &uuml;bertragen.<\/li>\n<\/ul>\n<h2>Einlesen des aktuellen Datenbanktitels<\/h2>\n<p>Die Callback-Funktion <b>getText<\/b> wird ausgel&ouml;st, wenn das Ribbon geladen oder wenn per Code eine der Methoden <b>Invalidate <\/b>oder <b>InvalidateControl <\/b>der in einer Variablen gespeicherten Ribbon-Instanz ausgel&ouml;st wird und das Steuerelement danach erstmals sichtbar wird.<\/p>\n<p>Sie erh&auml;lt als ersten Parameter einen Verweis auf das aufrufende Steuerelement. Der zweite Parameter erwartet die im <b>editBox<\/b>-Steuerelement anzuzeigende Zeichenkette.<\/p>\n<p>Wenn Sie die Prozedur wie nachfolgend in das twinBASIC-Projekt einf&uuml;gen, werden einige Elemente rot unterstrichen. Das liegt daran, dass wir noch keinen Verweis auf die DAO-Bibliothek hinzugef&uuml;gt haben:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>GetText(control<span style=\"color:blue;\"> As <\/span>IRibbonControl)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\r\n     <span style=\"color:blue;\">Dim <\/span>strText<span style=\"color:blue;\"> As String<\/span>\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = objAccess.CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> prp = db.Properties(\"AppTitle\")\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     <span style=\"color:blue;\">If <\/span>prp Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         strText = \"&lt;Kein Titel&gt;\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strText = prp.Value\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     GetText = strText\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Das holen wir nach, indem wir in twinBASIC zum Bereich <b>Settings <\/b>wechseln und dort unter <b>COM Type Library \/ Active X References <\/b>einen Verweis auf die Bibliothek <b>Microsoft Office 16.0 Access Database Engine Object Library [v12.0] <\/b>hinzuf&uuml;gen (siehe Bild 4). Danach unbedingt mit <b>Strg + S <\/b>speichern, damit die &Auml;nderungen wirksam werden!<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_1327_004.png\" alt=\"Hinzuf&uuml;gen eines Verweises auf die DAO-Bibliothek\" width=\"649,559\" height=\"508,2075\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Hinzuf&uuml;gen eines Verweises auf die DAO-Bibliothek<\/span><\/b><\/p>\n<p>Danach sind fast alle roten Unterstreichungen verschwunden, nur eine nicht &#8211; die unter <b>CurrentDb<\/b>. <b>CurrentDb <\/b>ist auch keine Eigenschaft der DAO-Bibliothek, sondern der Access-Bibliothek.<\/p>\n<p>Also f&uuml;gen wir auch diese noch mit dem Eintrag <b>Microsoft Access 16.0 Object Library [v9.0] <\/b>hinzu. Nach dem erneuten Speichern k&ouml;nnen wir uns nun den Code der Prozedur <b>getText <\/b>ohne rote Unterstreichungen ansehen.<\/p>\n<p>Die Prozedur deaktiviert zun&auml;chst die eingebaute Fehlerbehandlung und ruft den Wert der Eigenschaft <b>AppTitle <\/b>des <b>Database<\/b>-Objekts der aktuellen Datenbank ab. Die Fehlerbehandlung deaktivieren wir dabei, weil ein Fehler ausgel&ouml;st wird, wenn diese Eigenschaft noch nicht oder nicht mehr vorhanden ist. Sie ist nur vorhanden, wenn diese bereits durch den Benutzer &uuml;ber den Optionen-Dialog von Access gesetzt wurde (oder per Code, wie wir gleich demonstrieren).<\/p>\n<p>Danach aktivieren wir die Fehlerbehandlung wieder und pr&uuml;fen per <b>If&#8230;Then<\/b>-Bedingung, ob <b>prp <\/b>eine Eigenschaft zugewiesen wurde.<\/p>\n<p>Das ist nur der Fall, wenn die Eigenschaft aktuell vorhanden ist. Ist <b>prp <\/b>leer, &uuml;bergeben wir die Zeichenkette <b><Kein Titel><\/b> als anzuzeigenden Text. Enth&auml;lt <b>prp <\/b>einen Wert, &uuml;bergeben wir diesen an den Parameter <b>text<\/b>.<\/p>\n<h2>Andere Callback-Signatur in twinBASIC-Ribbons<\/h2>\n<p>Wie schon im Beitrag <b>twinBASIC &#8211; COM-Add-Ins f&uuml;r Access <\/b>festgestellt, sehen wir auch hier wieder eine andere Signatur f&uuml;r die Callback-Funktion. Sie lautet hier:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>GetText(control<span style=\"color:blue;\"> As <\/span>IRibbonControl)<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Unter VBA w&uuml;rde diese lauten:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>getText(control<span style=\"color:blue;\"> As <\/span>IRibbonControl, ByRef text)<\/pre>\n<p>Die hier verwendete Signatur ist die gleiche, die wir auch in einem VB6-COM-Add-In nutzen w&uuml;rden. Da twinBASIC zum Nachfolger von VB6 avanciert und wir noch weitere Tools damit entwickeln werden, stellen wir in einem weiteren Beitrag namens <b>Ribbon: Callback-Signaturen f&uuml;r VBA und VB6 <\/b>(<b>www.access-im-unternehmen.de\/1324<\/b>) die Unterschiede vor.<\/p>\n<h2>Speichern des ge&auml;nderten Datenbanktitels<\/h2>\n<p>Mit der gleichen Eigenschaft besch&auml;ftigt sich die Callback-Funktion <b>onChange<\/b> (siehe Listing 2). Diese hat die gleichen Parameter. Allerdings wird sie ausgel&ouml;st, wenn der Benutzer den im <b>editBox<\/b>-Steuerelement enthaltenen Text &auml;ndert und die &Auml;nderung beispielsweise durch Verlassen des Textfeldes abschlie&szlig;t. Dementsprechend ist der zweite Parameter <b>text <\/b>diesmal auch kein R&uuml;ckgabeparameter, sondern er liefert den neu vom Benutzer eingegebenen Text. <\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>OnChange(control<span style=\"color:blue;\"> As <\/span>IRibbonControl, text<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\r\n     <span style=\"color:blue;\">Set<\/span> db = objAccess.CurrentDb\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(text) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         db.Properties.Delete \"AppTitle\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> prp = db.Properties(\"AppTitle\")\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             <span style=\"color:blue;\">Set<\/span> prp = db.CreateProperty(\"AppTitle\", dbText, text)\r\n             db.Properties.Append prp\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             prp.Value = text\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     objAccess.RefreshTitleBar\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: &Auml;ndern einer Option nach &Auml;nderung im Ribbon<\/span><\/b><\/p>\n<p>Den Inhalt von <b>text <\/b>pr&uuml;ft die Prozedur zun&auml;chst in einer <b>If&#8230;Then<\/b>-Bedingung. Es kann sein, dass der Benutzer das <b>editBox<\/b>-Steuerelement komplett geleert hat, dann soll auch der Titel geleert werden. Das funktioniert allerdings nur in der gew&uuml;nschten Form, indem wir die Eigenschaft <b>AppTitle <\/b>wieder l&ouml;schen. Das erledigt die Prozedur im <b>If<\/b>-Teil der Bedingung mit der <b>Delete<\/b>-Methode der <b>Properties<\/b>-Auflistung.<\/p>\n<p>Hat der Benutzer jedoch einen Titel mit mindestens einem Zeichen eingegeben, dann wollen wir die Eigenschaft <b>AppTitle <\/b>auf diesen Wert einstellen. Dazu versucht die Prozedur, nach vorheriger Deaktivierung der Fehlerbehandlung, die Eigenschaft mit der Variablen <b>prp <\/b>zu referenzieren. Ist dabei ein Fehler aufgetreten, erstellt die Prozedur die Eigenschaft neu und h&auml;ngt diese an die Auflistung <b>Properties <\/b>des <b>Database<\/b>-Objekts der aktuellen Datenbank an.<\/p>\n<p>Ist die Eigenschaft bereits vorhanden, stellt die Prozedur diese lediglich auf den Wert aus dem Parameter <b>text <\/b>ein.<\/p>\n<p>In jedem Fall soll die Anzeige der Titelleiste anschlie&szlig;end aktualisiert werden, was die Methode <b>RefreshTitleBar <\/b>des <b>Application<\/b>-Objekts der aktuellen Access-Instanz erledigt. Diese haben wir ja zuvor in die Variable <b>objAccess <\/b>eingelesen.<\/p>\n<p>Nachdem Sie die Ribbon-Definition in der Prozedur GetCustomUI angepasst und die beiden Callback-Funktionen hinzugef&uuml;gt haben, k&ouml;nnen Sie die &Auml;nderungen speichern und das COM-Add-In neu kompilieren. Das Ergebnis der Kompilierung finden Sie &uuml;brigens unten in Visual Studio Code in der Debugging-Console.<\/p>\n<p><!--30percent--><\/p>\n<p>Wenn Sie danach eine Access-Datenbank &ouml;ffnen, finden Sie ein neues Tab namens <b>Optionen <\/b>im Ribbon. Klicken Sie es an, erscheint die von uns hinzugef&uuml;gte Option zum Einstellen des Datenbanktitels (siehe Bild 5). Dieses zeigt direkt beim &Ouml;ffnen den aktuellen Wert an &#8211; bei einer Datenbank, f&uuml;r die Sie noch keinen Anwendungstitel eingestellt haben, beispielsweise <b><Kein Titel><\/b>. Nach einer &Auml;nderung wird der neue Titel direkt in die Titelleiste &uuml;bertragen. Leeren Sie die Eigenschaft im Ribbon, erscheint wieder der Standardtitel, bestehend aus Datenbankname und Pfad.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_1327_005.png\" alt=\"Die erste Access-Option im Access-Ribbon\" width=\"649,559\" height=\"142,2843\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Die erste Access-Option im Access-Ribbon<\/span><\/b><\/p>\n<h2>Option zum &Auml;ndern des Anwendungssymbols<\/h2>\n<p>Wir wollen gleich die n&auml;chste Option aus dem Optionen-Dialog ermitteln und ausprobieren, n&auml;mlich das Definieren eines Anwendungssymbosl. Hier haben wir die zus&auml;tzliche Herausforderung, dass wir einen <b>Datei ausw&auml;hlen<\/b>-Dialog hinzuf&uuml;gen wollen. Also ben&ouml;tigen wir nicht nur ein <b>editBox<\/b>-Steuerelement, sondern daneben auch noch ein <b>button<\/b>-Element. Damit diese nebeneinander erscheinen, fassen wir die beiden Elemente in einem <b>box<\/b>-Element zusammen. Die notwendige Erweiterung der Prozedur <b>GetCustomUI<\/b> sehen Sie in Listing 3.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>GetCustomUI(ByVal RibbonID<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span> _\r\n     Implements IRibbonExtensibility.GetCustomUI\r\n     ...\r\n     strXML &= \"          &lt;editBox label=\"Anwendungstitel:\" id=\"txtTitle\" maxLength=\"255\" getText=\"getText\"\" _\r\n         & \" onChange=\"onChange\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;box id=\"box1\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"            &lt;editBox label=\"Anwendungssymbol:\" id=\"txtIcon\" maxLength=\"255\"\" _\r\n         & \" getText=\"getText\" onChange=\"onChange\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"            &lt;button screentip=\"Symbol ausw&auml;hlen ...\" label=\"...\" id=\"btnChooseSymbol\"\" _\r\n         & \" onAction=\"onAction\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strXML &= \"          &lt;\/box&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     ...\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Erweiterung der Ribbon-Definition f&uuml;r das Anpassen des Anwendungssymbols <\/span><\/b><\/p>\n<h2>Eigene Callback-Prozedur f&uuml;r gleiche Attribute f&uuml;r jedes Steuerelement<\/h2>\n<p>Bei Ereignisprozeduren von Formularen, Berichten oder Steuerelementen wird f&uuml;r jedes Ereignis eines jeden Elements eine neue Prozedur erstellt, die den Namen des Elements, einen Unterstrich und die Bezeichnung des Ereignisses als Bezeichnung tr&auml;gt. Bei Callback-Funktionen des Ribbons hat es sich eingeb&uuml;rgert, dass man zum Beispiel f&uuml;r das Ereignis <b>onAction <\/b>nur eine Callback-Funktion namens <b>onAction <\/b>definiert. Diese ermittelt dann &uuml;ber den Parameter <b>control <\/b>und dessen Eigenschaft <b>id <\/b>den Namen des aufrufenden Steuerelements. In einer <b>Select Case<\/b>-Bedingung wird dann der Name ausgewertet und in den <b>Case<\/b>-Zweigen finden sich dann die Anweisungen, die f&uuml;r das jeweilige Steuerelement ausgef&uuml;hrt werden sollen.<\/p>\n<p>Sie k&ouml;nnen nat&uuml;rlich auch beispielsweise f&uuml;r das <b>onAction<\/b>-Attribut eines Elements namens <b>btnBeispiel <\/b>einen Wert wie <b>btnBeispiel_OnAction <\/b>anlegen und eine entsprechende Callback-Funktion hinterlegen. Je nachdem, wie umfangreich das Ribbon ist und wie aufwendig der Code, kann dies die bessere Variante sein. Wir haben f&uuml;r die L&ouml;sung dieses Beitrags entschieden, die letztere Variante mit individuellen Callback-Funktionen je Steuerelement zu nutzen.<\/p>\n<p>Das hei&szlig;t zun&auml;chst, dass wir die bereits erstellten Callback-Funktion umbenennen. Aus der <b>GetText<\/b>-Funktion f&uuml;r das Textfeld <b>txtTitle <\/b>wird nun:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>txtTitle_GetText(control<span style=\"color:blue;\"> As <\/span>IRibbonControl) <span style=\"color:blue;\"> As String<\/span>\r\n     ...\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Die gleiche &Auml;nderung nehmen wir f&uuml;r die Callback-Funktion  <b>OnChange <\/b>f&uuml;r das Textfeld <b>txtTitle <\/b>vor:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>txtTitle_OnChange(control<span style=\"color:blue;\"> As <\/span>IRibbonControl,  text<span style=\"color:blue;\"> As String<\/span>)\r\n     ...\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Dementsprechend passen wir auch noch den Aufruf der Callback-Funktionen des <b>editBox<\/b>-Steuerelements <b>txtTitle <\/b>in den entsprechenden Attributen an:<\/p>\n<pre>&lt;editBox label=\"Anwendungstitel:\" id=\"txtTitle\" maxLength=\"255\" getText=\"txtTitle_getText\" onChange=\"txtTitle_onChange\"\/&gt;<\/pre>\n<h2>Ribbon-Steuerelemente f&uuml;r das Anwendungssymbol<\/h2>\n<p>In den XML-Definitionen f&uuml;r die Steuerelemente im Ribbon verwenden wir direkt die entsprechenden neuen Bezeichnungen:<\/p>\n<pre>&lt;editBox label=\"Anwendungssymbol:\" id=\"txtIcon\" maxLength=\"255\" getText=\"txtIcon_getText\" onChange=\"txtIcon_onChange\"\/&gt;\r\n&lt;button screentip=\"Symbol ausw&auml;hlen ...\" label=\"...\" id=\"btnChooseSymbol\" onAction=\"btnChooseSymbol_onAction\"\/&gt;<\/pre>\n<h2>Auswahl eines neuen Icons<\/h2>\n<p>Die Prozedur <b>btnChooseSymbol_onAction<\/b> wird aufgerufen, wenn der Benutzer die Schaltfl&auml;che mit den drei Punkten bet&auml;tigt (siehe Listing 4). Sie referenziert das <b>Database<\/b>-Objekt der aktuell ge&ouml;ffneten Datenbank und ermittelt als Startverzeichnis f&uuml;r den Dateiauswahl-Dialog das aktuelle Datenbankverzeichnis. Dieses landet in <b>strStartDir<\/b>. Dann verwendet es die Funktion <b>OpenFileName<\/b>, um einen Dateiauswahl-Dialog anzuzeigen. Mit diesem kann der Benutzer ein neues Anwendungssymbol ausw&auml;hlen.<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>btnChooseSymbol_onAction(control<span style=\"color:blue;\"> As <\/span>IRibbonControl)\r\n     <span style=\"color:blue;\">Dim <\/span>strStartDir<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strIcon<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\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>strTemp<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objFSO<span style=\"color:blue;\"> As <\/span>FileSystemObject\r\n     <span style=\"color:blue;\">Set<\/span> db = objAccess.CurrentDb\r\n     strStartDir = objAccess.CurrentProject.Path\r\n     strIcon = OpenFileName(strStartDir, \"Icon ausw&auml;hlen\", \"Bilddateien (*.ico, *.png, *.bmp)\")\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strIcon) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">MsgBox<\/span>(\"Icon in Anwendungsverzeichnis kopieren\", vbYesNo + vbQuestion) = vbYes<span style=\"color:blue;\"> Then<\/span>\r\n             strTemp = mid(strIcon, <span style=\"color:blue;\">InStrRev<\/span>(strIcon, \"\\\")+1)\r\n             <span style=\"color:blue;\">Set<\/span> objFSO = CreateObject(\"Scripting.FileSystemObject\")\r\n             objFSO.CopyFile strIcon, objAccess.CurrentProject.Path & \"\\\"\r\n             strIcon = strTemp\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> prp = db.Properties(\"AppIcon\")\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             <span style=\"color:blue;\">Set<\/span> prp = db.CreateProperty(\"AppIcon\", dbText, strIcon)\r\n             db.Properties.Append prp\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             prp.Value = strIcon\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         objRibbon.InvalidateControl \"txtIcon\"\r\n         objAccess.RefreshTitleBar\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: Auswahl eines neuen Icons<\/span><\/b><\/p>\n<p>Anschlie&szlig;end haben wir eine Funktion eingebaut, die sogar den eigentlichen Optionen-Dialog noch etwas verbessert: Die Prozedur fragt den Benutzer, ob er das gew&auml;hlte Icon gleich in das Anwendungsverzeichnis kopieren will. In diesem Fall schreibt die Prozedur den reinen Dateinamen in die Variable <b>strTemp<\/b>. Dann erstellt sie eine Instanz der Klasse <b>FileSystemDialog <\/b>und f&uuml;hrt ihre Methode <b>CopyFile <\/b>aus, wodurch die vom Benutzer ausgew&auml;hlte Datei in das Anwendungsverzeichnis kopiert wird. Schlie&szlig;lich stellen wir <b>strIcon <\/b>auf den Wert von <b>strTemp <\/b>ein, da wir den Pfad nicht mehr ben&ouml;tigen, wenn sich das Icon im gleichen Verzeichnis wie die Access-Datenbank befindet.<\/p>\n<p>Danach pr&uuml;ft die Prozedur, ob die Property <b>AppIcon <\/b>bereits vorhanden ist und legt diese gegebenenfalls an, wobei die ermittelte Icon-Datei aus <b>strIcon <\/b>als neuer Wert &uuml;bergeben wird. Ist <b>AppIcon <\/b>bereits vorhanden, weist die Prozedur lediglich den neuen Wert zu.<\/p>\n<p>Schlie&szlig;lich folgt noch ein wichtiger Schritt: die Aktualisierung der Anzeige mit dem neuen Icon. Das erledigen wir mit der Methode <b>InvalidateControl <\/b>f&uuml;r das Steuerelement <b>txtIcon<\/b> wie folgt, bevor wir die Anzeige der Titelleiste aktualisieren:<\/p>\n<pre>objRibbon.InvalidateControl \"txtIcon\"<\/pre>\n<p>Um diese Anweisung auszuf&uuml;hren, sind allerdings noch ein paar Schritte erforderlich. Zum Beispiel gibt es noch keine Variable namens <b>objRibbon<\/b>. Diese deklarieren wir als modulweit g&uuml;ltige Variable wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>objRibbon<span style=\"color:blue;\"> As <\/span>IRibbonUI<\/pre>\n<p>Diese Variable muss beim ersten Anzeigen des Ribbons gef&uuml;llt werden. Dazu hinterlegen wir f&uuml;r das Attribut <b>onLoad <\/b>des <b>CustomUI<\/b>-Elements den Namen der aufzurufenden Callback-Prozedur, hier <b>onLoad<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>GetCustomUI(ByVal RibbonID<span style=\"color:blue;\"> As String<\/span>) <span style=\"color:blue;\"> As String<\/span> Implements IRibbonExtensibility.GetCustomUI\r\n     ...\r\n     strXML &= \"&lt;customUI ... onLoad=\"onLoad\"&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     ...\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Die <b>onLoad<\/b>-Prozedur enth&auml;lt nur eine Anweisung, welche der Variablen <b>objRibbon <\/b>die Ribbon-Instanz zuweist:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>OnLoad(ribbon<span style=\"color:blue;\"> As <\/span>IRibbonUI)\r\n     <span style=\"color:blue;\">Set<\/span> objRibbon = ribbon\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Damit k&ouml;nnen wir ab jetzt die beiden Methoden <b>Invalidate <\/b>und <b>InvalidateControl <\/b>aufrufen. Die Erste sorgt daf&uuml;r, dass alle <b>get&#8230;<\/b>-Callback-Funktionen erneut aufgerufen werden, damit das Aussehen des Ribbons mit gegebenenfalls ge&auml;nderten Rahmenbedingungen neu gestaltet werden kann. Die Zweite erwartet als Parameter den Namen eines einzelnen Steuerelements, dessen <b>get&#8230;<\/b>-Callback-Funktionen aufgerufen werden sollen. Das f&uuml;hrt in unserem Fall dazu, dass nach dem Aktualisieren der Property <b>AppIcon <\/b>die Callback-Funktion <b>txtIcon_GetText <\/b>erneut ausgel&ouml;st wird. Dadurch wird der neue Wert der Property in das Textfeld eingetragen.<\/p>\n<h2>Der Datei &ouml;ffnen-Dialog in twinBASIC<\/h2>\n<p>In den Beispieldatenbanken von <b>Access im Unternehmen <\/b>verwenden wir zum Anzeigen eines Dateiauswahl-Dialogs immer die entsprechende Methode der <b>Wizhook<\/b>-Klasse. Diese nutzen wir auch hier. Dazu sind allerdings ein paar &Auml;nderungen n&ouml;tig, da wir uns nicht in einem VBA-Projekt einer Access-Datenbank selbst befinden. Somit stehen uns Klassen wie <b>Access.Application <\/b>nicht direkt zur Verf&uuml;gung, auf die in der &uuml;blicherweise genutzten Funktion <b>OpenFileName <\/b>sonst wie selbstverst&auml;ndlich zugegriffen wird.<\/p>\n<p>Die in twinBASIC zu verwendende Version haben wir exemplarisch in Listing 5 abgebildet. Sie verwendet an drei Stellen zus&auml;tzlich das Objekt <b>objAccess <\/b>&#8211; und zwar immer dort, wo wir auf die Eigenschaften und Methoden der <b>Wizhook<\/b>-Klasse zugreifen.<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>OpenFileName(<span style=\"color:blue;\">Optional<\/span> StartDir<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> sTitle<span style=\"color:blue;\"> As String<\/span> = \"Datei ausw&auml;hlen:\", _\r\n     <span style=\"color:blue;\">Optional<\/span> sFilter<span style=\"color:blue;\"> As String<\/span> = \"Access-DB (*.mdb)|Alle Dateien (*.*)\")<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Static <\/span>sDir<span style=\"color:blue;\"> As String<\/span>\r\n     objAccess.WizHook.Key = 51488399\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(StartDir) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(sDir) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             StartDir = objAccess.CurrentProject.Path\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             StartDir = sDir\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Call<\/span> objAccess.WizHook.GetFileName(Application.hWndAccessApp, \"Microsoft Access\", sTitle, _\r\n         \"&Ouml;ffnen\", OpenFileName, StartDir, sFilter, 0&, 0&, &H40, <span style=\"color:blue;\">False<\/span>)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(OpenFileName) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         sDir = <span style=\"color:blue;\">Left<\/span>(OpenFileName, <span style=\"color:blue;\">InStrRev<\/span>(OpenFileName, \"\\\", , vbTextCompare))\r\n    End If\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Funktion zum Anzeigen eines Dateiauswahl-Dialogs unter twinBASIC<\/span><\/b><\/p>\n<h2>Die Option &#8222;Icon als Formular- oder Berichtssymbol verwenden&#8220;<\/h2>\n<p>Wenn wir schon das Icon per Ribbon ausw&auml;hlen, wollen wir damit auch festlegen, ob dieses Ribbon auch als Icon f&uuml;r Formulare oder Berichte angezeigt wird. Dies erledigen wir durch das Hinzuf&uuml;gen eines <b>checkBox<\/b>-Steuerelements namens <b>chkFormReportIcon<\/b>. Dieses definieren wir wie folgt und f&uuml;gen es zum gleichen <b>group<\/b>-Element wie die ersten beiden Optionen hinzu:<\/p>\n<pre>strXML &= \"            &lt;checkBox label=\"Icon in Formular oder Bericht anzeigen:\" id=\"chkFormReportIcon\" getPressed=\"chkFormReportIcon_getPressed\" onAction=\"chkFormReportIcon_onAction\"\/&gt;\" & <span style=\"color:blue;\">vbCrLf<\/span><\/pre>\n<p>Die Callback-Funktion <b>getPressed <\/b>ermittelt den anzuzeigenden Zustand f&uuml;r das <b>checkBox<\/b>-Steuerelement. Dieser soll nat&uuml;rlich mit der entsprechenden Option &uuml;bereinstimmen. Also fragen wir in der Prozedur <b>chkFormReportIcon_getPressed <\/b>ab, ob die Property <b>UseAppIconForFrmRpt <\/b>&uuml;berhaupt existiert &#8211; das erledigen wir wieder, indem wir bei deaktivierter Fehlerbehandlung versuchen, diese Property mit <b>prp <\/b>zu referenzieren. Ist <b>prp <\/b>danach leer, stellen wir die Variable <b>bolResult <\/b>auf <b>False <\/b>ein, denn dann ist der Standardwert f&uuml;r diese Eigenschaft <b>Nein<\/b>. Ist <b>prp <\/b>hingegen gef&uuml;llt, lesen wir den Wert mit <b>Value <\/b>aus. Den Wert aus <b>bolResult <\/b>geben wir dann als Ergebnis mit der <b>Return<\/b>-Anweisung zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>chkFormReportIcon_getPressed(control _\r\n        <span style=\"color:blue;\"> As <\/span>IRibbonControl)<span style=\"color:blue;\"> As Boolean<\/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>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\r\n     <span style=\"color:blue;\">Dim <\/span>bolResult<span style=\"color:blue;\"> As Boolean<\/span>\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = objAccess.CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> prp = db.Properties(\"UseAppIconForFrmRpt\")\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     <span style=\"color:blue;\">If <\/span>prp Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         bolResult = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         bolResult = prp.Value\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     Return bolResult\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Au&szlig;erdem ben&ouml;tigen wir noch die Callback-Funktion f&uuml;r das Attribut <b>onAction<\/b>. Wenn der Benutzer das Kontrollk&auml;stchen anklickt, soll der neue Wert in die Eigenschaft geschrieben werden. Der Aufbau ist &auml;hnlich wie zuvor in den Routinen zum Zuweisen der neuen Werte. Der Parameter <b>pressed <\/b>liefert den neuen Wert, hier <b>True <\/b>oder <b>False<\/b>. Wenn <b>pressed <\/b>den Wert <b>False <\/b>hat, l&ouml;scht die Prozedur die Eigenschaft <b>UseAppIconForFormRpt<\/b>. Hat pressed den Wert <b>True<\/b>, wird die Eigenschaft <b>UseApp-IconForFormRpt <\/b>gegebenenfalls neu erstellt und mit dem Wert aus <b>pressed <\/b>gef&uuml;llt. Ist die Eigenschaft vorhanden, erfolgt eine einfache Zuweisung (siehe Listing 6).<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>chkFormReportIcon_onAction(control<span style=\"color:blue;\"> As <\/span>IRibbonControl, pressed<span style=\"color:blue;\"> As Boolean<\/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>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\r\n     <span style=\"color:blue;\">Set<\/span> db = objAccess.CurrentDb\r\n     <span style=\"color:blue;\">If <\/span>pressed = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         db.Properties.Delete \"UseAppIconForFrmRpt\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> prp = db.Properties(\"UseAppIconForFrmRpt\")\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             <span style=\"color:blue;\">Set<\/span> prp = db.CreateProperty(\"UseAppIconForFrmRpt\", dbBoolean, pressed)\r\n             db.Properties.Append prp\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             prp.Value = pressed\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     objAccess.RefreshTitleBar\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Einstellen des Wertes der Eigenschaft UseAppIconForFrmRpt<\/span><\/b><\/p>\n<p>Im Gegensatz zu den beiden Textfeldern zuvor ist es bei dieser <b>Boolean<\/b>-Eigenschaft eigentlich nicht n&ouml;tig, die Eigenschaft zu l&ouml;schen, um diese auf <b>False <\/b>einzustellen. Sie k&ouml;nnen also statt diese zu l&ouml;schen auch einfach den Wert der Eigenschaft auf <b>False <\/b>einstellen.<\/p>\n<h2>Die Option &#8222;Formular anzeigen&#8220;<\/h2>\n<p>Als n&auml;chstes schauen wir uns die Option <b>Formular anzeigen <\/b>an, die im Optionen-Dialog ein Kombinationsfeld zur Auswahl eines der Formulare der aktuellen Datenbankdatei anbietet. Damit haben wir auch gleich einmal ein sch&ouml;nes Beispiel f&uuml;r die Programmierung von Kombinationsfeldern im Ribbon.<\/p>\n<p>Als Erstes wollen wir wieder das passende Steuerelement hinzuf&uuml;gen, wobei die Entscheidung zwischen den beiden Typen <b>comboBox <\/b>und <b>dropDown <\/b>zu f&auml;llen ist. Wir wollen eigentlich nur Eintr&auml;ge ausw&auml;hlen und keine eigenen Texte eingeben, was f&uuml;r das <b>dropDown<\/b>-Steuerelement spricht. Allerdings bietet nur das <b>comboBox<\/b>-Element die M&ouml;glichkeit, bei jedem erneuten Aufklappen die Werte erneut einzulesen.<\/p>\n<h2>comboBox definieren<\/h2>\n<p>Da die Definition des <b>comboBox<\/b>-Steuerelements etwas umfangreicher ist, haben wir diese direkt als XML-Code abgebildet und die Attribute auf jeweils eine Zeile aufgeteilt:<\/p>\n<pre>&lt;comboBox label=\"Startformular:\" \r\n     id=\"cboStartupForm\" \r\n     getItemCount=\"cboStartupForm_getItemCount\" \r\n     getItemID=\"cboStartupForm_getItemID\" \r\n     getItemLabel=\"cboStartupForm_getItemLabel\" \r\n     getText=\"cboStartupForm_getText\" \r\n     onChange=\"cboStartupForm_onChange\" \r\n     invalidateContentOnDrop=\"True\" \r\n     maxlength=\"255\" \r\n     sizeString=\"xxxxxxxxxxxxxxxxxxxxxxxxx\" \/&gt;<\/pre>\n<p>Wichtig ist vor allem das Attribut <b>invalidateContentOnDrop<\/b>, das mit dem Wert <b>True <\/b>daf&uuml;r sorgt, dass das <b>comboBox<\/b>-Steuerelement bei jedem &Ouml;ffnen neu eingelesen wird.<\/p>\n<p>Die erste Callback-Funktion, die hier aufgerufen wird, lautet <b>cboStartupForm_GetItemCount<\/b>. Sie soll eigentlich nur die Anzahl der anzuzeigenden Elemente zur&uuml;ckliefern, aber in der Tat ist hier noch mehr Arbeit zu erledigen. Die Bezeichnungen der einzelnen Elemente werden n&auml;mlich jeweils in einem einzelnen Aufruf der Prozedur <b>cboStartup-Form_getItemLabel <\/b>ermittelt, wobei der Index des jeweils einzulesenden Elements &uuml;bergeben wird. Deshalb stellen wir bereits in der <b>GetItemCount<\/b>-Prozedur ein Array mit allen anzuzeigenden Eintr&auml;gen zusammen. Das erste Element soll au&szlig;erdem ein Eintrag namens <b><Kein Formular> <\/b>sein, damit der Benutzer intuitiv das Startformular entfernen kann. Damit <b>cboStartupForm_getItemLabel <\/b>das Array nutzen kann, das wir in <b>cboStartupForm_getItemCount <\/b>zusammenstellen, deklarieren wir es als modulweit g&uuml;ltige Variable wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>strForms()<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Danach k&ouml;nnen wir die Funktion <b>cboStartForm_GetItemCount <\/b>wie in Listing 7 definieren. Die Prozedur liest zun&auml;chst die Anzahl der Formulare &uuml;ber die Eigenschaft <b>Count <\/b>der Auflistung <b>AllForms <\/b>der <b>CurrentProject<\/b>-Klasse ein. Dann stellt sie die Gr&ouml;&szlig;e des Arrays mit <b>Redim Preserve <\/b>auf <b>0 <\/b>ein und legt als Eintrag mit dem Index <b>0 <\/b>den Wert <b><Kein Startformular> <\/b>fest.<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>cboStartupForm_GetItemCount(control<span style=\"color:blue;\"> As <\/span>IRibbonControl)<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngCount<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     lngCount = objAccess.CurrentProject.AllForms.Count\r\n     ReDim Preserve strForms(0)\r\n     strForms(0) = \"&lt;Kein Startformular&gt;\"\r\n     For i = 0 To intCount - 1\r\n         ReDim Preserve strForms(i + 1)\r\n         strForms(i + 1) = objAccess.CurrentProject.AllForms(i).Name\r\n     <span style=\"color:blue;\">Next<\/span>\r\n     lngCount = lngCount + 1\r\n     Return lngCount\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Ermitteln der anzuzeigenden Eintr&auml;ge f&uuml;r das comboBox-Steuerelement<\/span><\/b><\/p>\n<p>In einer <b>For&#8230;Next<\/b>-Schleife &uuml;ber die Elemente von <b>0 <\/b>bis zur Anzahl minus <b>1 <\/b>erh&ouml;ht die Funktion mit <b>Redim Preserve <\/b>die Gr&ouml;&szlig;e des Arrays jeweils um <b>1 <\/b>und f&uuml;gt dem <b>i <\/b>plus ersten Element den Namen des Formular-Eintrags mit dem Index <b>i <\/b>hinzu. Danach erh&ouml;ht sie <b>intCount <\/b>noch um <b>1<\/b>, damit sowohl <b><Kein Formular><\/b> als auch die einzelnen Formulare ber&uuml;cksichtigt werden.<\/p>\n<p>Damit kommen wir zum Einlesen der einzelnen Formulare. Dies geschieht in der Callback-Funktion <b>cboStartupForm_GetItemLabel<\/b>, die mit dem Parameter <b>index <\/b>den Index des einzulesenden Elements erh&auml;lt und den anzuzeigenden Text als Ergebnis zur&uuml;ckliefern soll.<\/p>\n<p>Diese schreibt einfach das Element des Arrays <b>strForms <\/b>mit dem Index aus <b>index <\/b>in die Variable <b>strStartupForm<\/b>, die wiederum mit der <b>Return<\/b>-Anweisung zur&uuml;ckgegeben wird:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>cboStartupForm_GetItemLabel(control<span style=\"color:blue;\"> As <\/span> IRibbonControl, index<span style=\"color:blue;\"> As Integer<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strStartupForm as String\r\n     strStartupForm = strForms(index)\r\n     Return strStartupForm\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Anzeigen des aktuellen Startformulars<\/h2>\n<p>Damit kommen wir zum Callbackattribut <b>getText<\/b>. Dieses gibt die Callback-Funktion an, die den aktuell anzuzeigenden Text liefern soll. Diese hei&szlig;t <b>cboStartupForm_GetText <\/b>und liefert das Ergebnis als String zur&uuml;ck (siehe Listing 8). Sie versucht bei deaktivierter Fehlerbehandlung den Wert der Eigenschaft <b>StartupForm <\/b>einzulesen. Ist die damit gef&uuml;llte Variable <b>prp <\/b>danach leer, wird <b>strStartupForm <\/b>auf <b><Kein Startformular> <\/b>eingestellt. Anderenfalls erh&auml;lt <b>strStartupForm <\/b>den Namen des aktuellen Wertes dieser Eigenschaft.<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>cboStartupForm_GetText(control<span style=\"color:blue;\"> As <\/span>IRibbonControl)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\r\n     <span style=\"color:blue;\">Dim <\/span>strStartupForm<span style=\"color:blue;\"> As String<\/span>\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = objAccess.CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> prp = db.Properties(\"StartupForm\")\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     <span style=\"color:blue;\">If <\/span>prp Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         strStartupForm = \"&lt;Kein Startformular&gt;\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strStartupForm = prp.Value\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     Return strStartupForm\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Ermitteln des aktuellen Startformulars<\/span><\/b><\/p>\n<h2>Aktualisieren des Startformulars<\/h2>\n<p>Fehlt noch das Callbackattribut <b>onChange<\/b>, welches die Prozedur <b>cboStartupForm_OnChange <\/b>aufruft (siehe Listing 9). Diese nimmt mit dem Parameter <b>text <\/b>den vom Benutzer gew&auml;hlten Wert entgegen. Diesen pr&uuml;ft die Prozedur zun&auml;chst auf den Wert <b><Kein Formular><\/b>. Ist dieser enthalten, l&ouml;scht die Prozedur die Eigenschaft <b>StartupForm<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>cboStartupForm_OnChange(control<span style=\"color:blue;\"> As <\/span>IRibbonControl, text<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\r\n     <span style=\"color:blue;\">Set<\/span> db = objAccess.CurrentDb\r\n     <span style=\"color:blue;\">If <\/span>text = \"&lt;Kein Startformular&gt;\"<span style=\"color:blue;\"> Then<\/span>\r\n         db.Properties.Delete \"StartupForm\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> prp = db.Properties(\"StartupForm\")\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             <span style=\"color:blue;\">Set<\/span> prp = db.CreateProperty(\"StartupForm\", dbText, text)\r\n             db.Properties.Append prp\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             prp.Value = text\r\n         <span style=\"color:blue;\">End If<\/span>\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 9: &Auml;ndern des Startformulars<\/span><\/b><\/p>\n<p>Anderenfalls referenziert sie die Eigenschaft <b>StartupForm <\/b>wie in den vorherigen Beispielen bei deaktivierter Fehlerbehandlung mit der Variablen <b>prp<\/b>. Ist diese danach leer, war sie noch nicht vorhanden und die Prozedur erstellt sie mit dem Wert aus <b>text<\/b>. Anderenfalls tr&auml;gt sie diesen Wert einfach f&uuml;r die Eigenschaft <b>Value <\/b>der Property <b>prp <\/b>ein.<\/p>\n<h2>Optionen mit SetOption anpassen<\/h2>\n<p>Die bisher ge&auml;nderten Optionen haben sich auf die aktuelle Datenbank bezogen. Wir wollen uns auch noch ansehen, wie Sie solche Optionen anzeigen und &auml;ndern k&ouml;nnen, die sich auf die Access-Nutzung des aktuellen Benutzers beziehen, also solche, die Sie mit <b>GetOption <\/b>ermitteln und mit <b>SetOption <\/b>schreiben k&ouml;nnen.<\/p>\n<p>Dazu suchen wir uns zwei Optionen heraus, die zumindest in meinem Alltag recht h&auml;ufig zum Einsatz kommen und deshalb viel Zeit in Anspruch nehmen.<\/p>\n<p>Es geht um die beiden Optionen <b>Systemobjekte anzeigen <\/b>und <b>Versteckte Objekte anzeigen <\/b>aus dem Dialog <b>Navigationsoptionen<\/b> (siehe Bild 6).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_1327_006.png\" alt=\"Die Optionen des Bereichs Anzeigeoptionen wollen wir im Ribbon anzeigen.\" width=\"649,559\" height=\"334,2876\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Die Optionen des Bereichs Anzeigeoptionen wollen wir im Ribbon anzeigen.<\/span><\/b><\/p>\n<p>Diese wollen wir wie in Bild 7 im Ribbon abbilden. Wir ben&ouml;tigen also zwei <b>checkBox<\/b>-Steuerelemente, die in der XML-Definition wie folgt aussehen:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_1327_007.png\" alt=\"Das Ribbon mit den von uns hinzugef&uuml;gten Einstellungen\" width=\"700\" height=\"262,391\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Das Ribbon mit den von uns hinzugef&uuml;gten Einstellungen<\/span><\/b><\/p>\n<pre>&lt;checkBox label=\"Ausgeblendete Objekte anzeigen:\" id=\"chkShowHiddenObjects\" getPressed=\"chkShowHiddenObjects_getPressed\" onAction=\"chkShowHiddenObjects_onAction\"\/&gt;\r\n&lt;checkBox label=\"Systemobjekte anzeigen:\" id=\"chkShowSystemObjects\" getPressed=\"chkShowSystemObjects_getPressed\" onAction=\"chkShowSystemObjects_onAction\"\/&gt;<\/pre>\n<p>Wir definieren also wieder je ein <b>getPressed<\/b>-Attribut und ein <b>onAction<\/b>-Attribut, um den aktuellen Wert einzulesen und den vom Benutzer angeklickten Wert einzustellen.<\/p>\n<h2>Option &#8222;Systemobjekte anzeigen&#8220;<\/h2>\n<p>Die Callback-Routinen f&uuml;r das &Auml;ndern von Einstellungen, die in der Registry gespeichert werden, sind erfreulicherweise wesentlich weniger schreibaufwendig als die f&uuml;r die aktuelle Datenbank.<\/p>\n<p>Das liegt daran, dass wir einfach <b>GetOption <\/b>und <b>SetOption <\/b>nutzen k&ouml;nnen und nicht immer noch pr&uuml;fen m&uuml;ssen, ob die Property bereits vorhanden ist oder noch erstellt beziehungsweise gel&ouml;scht werden muss.<\/p>\n<p>Um zu ermitteln, ob die Option <b>Ausgeblendete Objekte anzeigen <\/b>aktiviert ist und diesen Wert dem <b>checkBox<\/b>-Element <b>chkShowHiddenObjects <\/b>zuzuweisen, verwenden wir die folgende Prozedur:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>chkShowHiddenObjects_getPressed( control<span style=\"color:blue;\"> As <\/span>IRibbonControl)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolResult<span style=\"color:blue;\"> As Boolean<\/span>\r\n     bolResult = objAccess.GetOption(\"Show Hidden Objects\")\r\n     Return bolResult\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Wenn der Benutzer das <b>checkBox<\/b>-Steuerelement anklickt, wird das Callback-Ereignis <b>onAction <\/b>ausgel&ouml;st, f&uuml;r das wie die folgende Prozedur hinterlegen.<\/p>\n<p>Diese stellt <b>Show Hidden Objects <\/b>mit der <b>SetOption<\/b>-Methode auf den Wert des Parameters <b>pressed <\/b>ein:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>chkShowHiddenObjects_onAction( control<span style=\"color:blue;\"> As <\/span>IRibbonControl, pressed<span style=\"color:blue;\"> As Boolean<\/span>)\r\n     objAccess.SetOption \"Show Hidden Objects\", pressed\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Option &#8222;Versteckte Objekte anzeigen&#8220;<\/h2>\n<p>Die Routinen f&uuml;r das <b>checkBox<\/b>-Steuerelement <b>chkShowSystemObjects <\/b>sieht &auml;hnlich aus &#8211; sie liest allerdings die Eigenschaft <b>Show System Objects<\/b> aus:<\/p>\n<pre><span style=\"color:blue;\">Function <\/span>chkShowSystemObjects_getPressed( control<span style=\"color:blue;\"> As <\/span>IRibbonControl)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolResult<span style=\"color:blue;\"> As Boolean<\/span>\r\n     bolResult = objAccess.GetOption(\"Show System Objects\")\r\n     Return bolResult\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Und die <b>onAction<\/b>-Prozedur stellt die gleiche Option auf den Wert des Parameters <b>pressed <\/b>ein:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>chkShowSystemObjects_onAction( control<span style=\"color:blue;\"> As <\/span>IRibbonControl, pressed<span style=\"color:blue;\"> As Boolean<\/span>)\r\n     objAccess.SetOption \"Show System Objects\", pressed\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis ist sehr erfreulich &#8211; ohne erst in mehreren Schritten den Dialog <b>Navigationsoptionen <\/b>&ouml;ffnen zu m&uuml;ssen, k&ouml;nnen Sie nun durch einen einfachen Wechsel zum Tab <b>Optionen <\/b>und einen Mausklick die Anzeige von versteckten Objekten oder von Systemobjekten einstellen.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Beitrag zeigt, wie Sie das Ribbon um einen eigenen Bereich erweitern, der einige Optionen des Optionen-Dialogs von Access anzeigt. Damit machen Sie die Optionen viel schneller verf&uuml;gbar als wenn Sie erst den Optionen-Dialog &ouml;ffnen und die gew&uuml;nschte Funktion suchen m&uuml;ssen. Sie k&ouml;nnen weitere, f&uuml;r Ihre eigenen Anforderungen n&ouml;tigen Befehle hinzuprogrammieren &#8211; das technische Handwerkzeug liefert der Beitrag bereits.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>AccessOptionsGoRibbon_ACCESS_RegisterAddin32.reg<\/p>\n<p>AccessOptionsGoRibbon_ACCESS_UnregisterAddin32.reg<\/p>\n<p>AccessOptionsGoRibbon_EXCEL_RegisterAddin32.reg<\/p>\n<p>AccessOptionsGoRibbon_EXCEL_UnregisterAddin32.reg<\/p>\n<p>AccessOptionsGoRibbon_myCOMAddin.code-workspace<\/p>\n<p>AccessOptionsGoRibbon_myCOMAddin.twinproj<\/p>\n<p>AccessOptionsGoRibbon_myCOMAddin.zip<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/7CA7817E-55BC-4A9A-A084-45CBC83FA609\/aiu_1327.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Es gibt einige Access-Optionen, die man immer wieder nutzt. In meinem Fall ist es zum Beispiel die Einstellung, ob Formulare nun als &uuml;berlappende Fenster oder als Dokumente im Registerkartenformat angezeigt werden sollen. Sicher haben Sie &auml;hnliche Einstellungen, die Sie oft &auml;ndern oder die Sie vielleicht einfach nur schnell einsehen k&ouml;nnen &#8211; was bei dem mittlerweile recht umfangreich gewordenen Optionen-Dialog schon einige Sekunden kosten kann. Warum also nicht ein COM-Add-In bauen, dass die Informationen der wichtisten Access-Einstellungen immer direkt im Ribbon anzeigt &#8211; anstatt irgendwo versteckt im Optionen-Dialog Und da wir mit twinBASIC auch noch ein praktisches Tool zum Erstellen von COM-Add-Ins zur Hand haben, k&ouml;nnen wir direkt loslegen!<\/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":[662021,66052021,44000027],"tags":[],"class_list":["post-55001327","post","type-post","status-publish","format-standard","hentry","category-662021","category-66052021","category-Loesungen"],"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>Access-Optionen per Ribbon &auml;ndern - 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\/AccessOptionen_per_Ribbon_aendern\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Access-Optionen per Ribbon &auml;ndern\" \/>\n<meta property=\"og:description\" content=\"Es gibt einige Access-Optionen, die man immer wieder nutzt. In meinem Fall ist es zum Beispiel die Einstellung, ob Formulare nun als &uuml;berlappende Fenster oder als Dokumente im Registerkartenformat angezeigt werden sollen. Sicher haben Sie &auml;hnliche Einstellungen, die Sie oft &auml;ndern oder die Sie vielleicht einfach nur schnell einsehen k&ouml;nnen - was bei dem mittlerweile recht umfangreich gewordenen Optionen-Dialog schon einige Sekunden kosten kann. Warum also nicht ein COM-Add-In bauen, dass die Informationen der wichtisten Access-Einstellungen immer direkt im Ribbon anzeigt - anstatt irgendwo versteckt im Optionen-Dialog Und da wir mit twinBASIC auch noch ein praktisches Tool zum Erstellen von COM-Add-Ins zur Hand haben, k&ouml;nnen wir direkt loslegen!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-29T22:11:44+00:00\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"27\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Access-Optionen per Ribbon &auml;ndern\",\"datePublished\":\"2021-09-29T22:11:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/\"},\"wordCount\":4347,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"articleSection\":[\"2021\",\"5\\\/2021\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/\",\"name\":\"Access-Optionen per Ribbon &auml;ndern - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"datePublished\":\"2021-09-29T22:11:44+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AccessOptionen_per_Ribbon_aendern\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Access-Optionen per Ribbon &auml;ndern\"}]},{\"@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":"Access-Optionen per Ribbon &auml;ndern - 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\/AccessOptionen_per_Ribbon_aendern\/","og_locale":"de_DE","og_type":"article","og_title":"Access-Optionen per Ribbon &auml;ndern","og_description":"Es gibt einige Access-Optionen, die man immer wieder nutzt. In meinem Fall ist es zum Beispiel die Einstellung, ob Formulare nun als &uuml;berlappende Fenster oder als Dokumente im Registerkartenformat angezeigt werden sollen. Sicher haben Sie &auml;hnliche Einstellungen, die Sie oft &auml;ndern oder die Sie vielleicht einfach nur schnell einsehen k&ouml;nnen - was bei dem mittlerweile recht umfangreich gewordenen Optionen-Dialog schon einige Sekunden kosten kann. Warum also nicht ein COM-Add-In bauen, dass die Informationen der wichtisten Access-Einstellungen immer direkt im Ribbon anzeigt - anstatt irgendwo versteckt im Optionen-Dialog Und da wir mit twinBASIC auch noch ein praktisches Tool zum Erstellen von COM-Add-Ins zur Hand haben, k&ouml;nnen wir direkt loslegen!","og_url":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/","og_site_name":"Access im Unternehmen","article_published_time":"2021-09-29T22:11:44+00:00","author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"27\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Access-Optionen per Ribbon &auml;ndern","datePublished":"2021-09-29T22:11:44+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/"},"wordCount":4347,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"articleSection":["2021","5\/2021","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/","url":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/","name":"Access-Optionen per Ribbon &auml;ndern - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"datePublished":"2021-09-29T22:11:44+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/AccessOptionen_per_Ribbon_aendern\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Access-Optionen per Ribbon &auml;ndern"}]},{"@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\/55001327","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=55001327"}],"version-history":[{"count":1,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001327\/revisions"}],"predecessor-version":[{"id":88072586,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001327\/revisions\/88072586"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001327"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001327"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001327"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}