{"id":55001563,"date":"2026-04-01T00:00:00","date_gmt":"2026-03-05T20:48:21","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1563"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Schnelle_Schaltflaechen_mit_Stil","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/","title":{"rendered":"Schnelle Schaltfl&auml;chen mit Stil"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg01.met.vgwort.de\/na\/94aba167088843dab03f5b20c23d1aa0\" width=\"1\" height=\"1\" alt=\"\"><b>Je schneller ich Ergebnisse beim Programmieren erhalten m&ouml;chte, desto ungeduldiger werde ich, wenn mich kleinteilige, sich st&auml;ndig wiederholende Aufgaben aufhalten. In diesem Fall ist vom Anlegen von Schaltfl&auml;chen die Rede. Ich h&auml;tte gern so schnell wie m&ouml;glich Schaltfl&auml;chen, welche die von mir gew&uuml;nschte Beschriftung, einen passenden Namen und je nach Situation ein Icon enthalten. Diese Icons sollen nach meinen W&uuml;nschen gestaltet sein &#8211; also beispielsweise mit transparentem Hintergrund und ohne Rahmen, sodass nur das Icon und die Beschriftung erscheinen und die Schriftfarbe und Schriftbreite diese als Schaltfl&auml;che von den Beschriftungen abhebt. Schlie&szlig;lich sollte auch noch direkt der VBA-Editor mit der passenden Ereignisprozedur ge&ouml;ffnet werden. Das alles umfasst einige Schritte, und auch wenn man eine Schaltfl&auml;che einmal formatiert hat und diese dann kopiert und als Vorlage f&uuml;r eine neue Schaltfl&auml;che verwendet, muss man noch einige Aspekte selbst hinzuf&uuml;gen. In diesem Beitrag stelle ich daher einen Assistenten vor, mit dem wir Schaltfl&auml;chen wesentlich schneller und komfortabler anlegen k&ouml;nnen.<\/b><\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_001.png\" alt=\"Individuelles Schaltfl&auml;chendesign\" width=\"549,559\" height=\"286,6404\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Individuelles Schaltfl&auml;chendesign<\/span><\/b><\/p>\n<h2>Schaltfl&auml;chen &#8211; der Standardweg<\/h2>\n<p>Wenn ich in einem Formular eine neue Schaltfl&auml;che wie die aus Bild 1 erstellen m&ouml;chte, sind einige Schritte n&ouml;tig:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_001.png\" alt=\"Individuelles Schaltfl&auml;chendesign\" width=\"549,559\" height=\"286,6404\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Individuelles Schaltfl&auml;chendesign<\/span><\/b><\/p>\n<ul>\n<li>Klick auf den Ribbon-Eintrag <b>Formularentwurf|Steuerelemente|Schaltfl&auml;che<\/b><\/li>\n<li>Klick auf die Stelle im Formularentwurf, wo die Schaltfl&auml;che angelegt werden soll<\/li>\n<li>Anpassen der Beschriftung<\/li>\n<li>Wechsel zur Registerseite <b>Andere <\/b>im Eigenschaftenblatt und Anpassen des Steuerelementnamens<\/li>\n<li>Anlegen der Ereignisprozedur durch Wechsel zur Registerseite <b>Ereignisse <\/b>im Eigenschaftenblatt, Klick in die Eigenschaft <b>Beim Klicken<\/b>, Klick auf die Schaltfl&auml;che mit den drei Punkten<\/li>\n<li>Hinzuf&uuml;gen des Codes, der durch die Schaltfl&auml;che ausgel&ouml;st werden soll<\/li>\n<li>Hinzuf&uuml;gen eines Icons &uuml;ber den Ribbonbefehl <b>Bild einf&uuml;gen<\/b>, hier gegebenenfalls noch Ausw&auml;hlen des gew&uuml;nschten Bildes<\/li>\n<li>Einstellen der Eigenschaft <b>Anordnung der Bildbeschriftung <\/b>auf <b>Rechts<\/b><\/li>\n<li>Hinzuf&uuml;gen eines Leerzeichens links von der Bildbeschriftung, damit diese ausreichend Abstand vom Icon hat<\/li>\n<li>Einstellen der Eigenschaft <b>Hintergrundfarbe <\/b>auf die Farbe des Formulars<\/li>\n<li>Einstellen der Eigenschaft <b>Rahmenart <\/b>auf <b>Transparent<\/b><\/li>\n<li>Einstellung der Eigenschaften <b>Farbe beim Daraufzeigen <\/b>und <b>Farbe f&uuml;r gedr&uuml;ckten Zustand <\/b>auf die gew&uuml;nschten Farben<\/li>\n<li>Einstellen der Eigenschaft <b>Schriftbreite <\/b>auf <b>Fett<\/b><\/li>\n<\/ul>\n<p>Damit ist die erste Schaltfl&auml;che angelegt.<\/p>\n<p>F&uuml;r die folgenden Schaltfl&auml;chen wird es etwas einfacher, weil wir nun eine Schaltfl&auml;che haben, die wir bereits kopieren und als neue Schaltfl&auml;che einf&uuml;gen k&ouml;nnen. Dennoch m&uuml;ssen wir dann folgende Einstellungen erneut vornehmen:<\/p>\n<ul>\n<li>Beschriftung einstellen<\/li>\n<li>Steuerelementname einstellen<\/li>\n<li>Icon ausw&auml;hlen<\/li>\n<li>Ereignisprozedur anlegen<\/li>\n<\/ul>\n<h2>Schaltfl&auml;chen einfacher hinzuf&uuml;gen<\/h2>\n<p>Mit der nachfolgend beschriebenen L&ouml;sung wollen wir diese Schritte erheblich vereinfachen.<\/p>\n<p>Dazu programmieren wir ein Formular, das die wichtigsten Konfigurationsm&ouml;glichkeiten f&uuml;r eine neue Schaltfl&auml;che enth&auml;lt. In weiteren Beitr&auml;gen (siehe Ende des Beitrags) zeigen wir, wie die L&ouml;sung in einen Steuerelement-Wizard umgewandelt wird.<\/p>\n<p>Damit wollen wir nur noch die sich unterscheidenden Merkmale anpassen &#8211; und auch das werden wir vereinfachen. Wir wollen hier nur noch die folgenden Aktionen durchf&uuml;hren m&uuml;ssen:<\/p>\n<ul>\n<li>Angabe der Beschriftung<\/li>\n<li>Auswahl des Icons<\/li>\n<li>Anschlie&szlig;endes Erg&auml;nzen der bereits angelegten Ereignisprozedur<\/li>\n<\/ul>\n<p>Wenn wir die Beschriftung eingegeben haben, wollen wir daraus automatisch einen Steuerelementnamen ableiten. Wenn die Beschriftung etwa <b>Weitersuchen <\/b>lautet, soll automatisch der Steuerelementname <b>cmdWeitersuchen <\/b>vorgeschlagen werden.<\/p>\n<p>Wenn sich die Beschriftung aus mehreren W&ouml;rtern zusammensetzt, soll der Steuerelementname aus dem gleichen Text bestehen &#8211; allerdings werden Leerzeichen entfernt, Umlaute und Sonderzeichen werden ersetzt und jedes neue Wort wird gro&szlig;geschrieben. Aus der Beschriftung <b>N&auml;chste Fundstelle <\/b>wird so <b>cmdNaechsteFundstelle<\/b>.<\/p>\n<p>Dieser Steuerelementname soll nat&uuml;rlich angepasst werden k&ouml;nnen, bevor das Steuerelement angelegt wird.<\/p>\n<h2>Funktionsweise der L&ouml;sung<\/h2>\n<p>Die L&ouml;sung besteht aus dem Formular aus Bild 2. In das Feld <b>Beschriftung <\/b>geben wir den Text ein, der auf der Schaltfl&auml;che angezeigt werden soll. Daraus wird automatisch der Name f&uuml;r das Steuerelement generiert, den wir anschlie&szlig;end nach Bedarf anpassen k&ouml;nnen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_006.png\" alt=\"Das Formular frmButtonWizard\" width=\"499,5589\" height=\"436,6299\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Das Formular frmButtonWizard<\/span><\/b><\/p>\n<p>&Uuml;ber die Schaltfl&auml;che <b>Auswahl <\/b>k&ouml;nnen wir einen Dateidialog &ouml;ffnen, mit dem wir Icons ausw&auml;hlen, die f&uuml;r die zu erstellenden Schaltfl&auml;chen verwendet werden sollen. Diese werden anschlie&szlig;end in den Bildsteuerelementen darunter angezeigt. Mit dem Feld <b>Filter <\/b>k&ouml;nnen wir gezielt nach den Namen der Bild-Dateien suchen. Wenn mehr Bilder vorhanden sind, als angezeigt werden k&ouml;nnen, erlauben die beiden Schaltfl&auml;chen mit dem Pfeil nach oben und dem Pfeil nach unten das Bl&auml;ttern in den Icons.<\/p>\n<p>Die Vorschau zeigt an, wie die fertige Schaltfl&auml;che sp&auml;ter aussehen wird. Mit einem Klick auf Schaltfl&auml;che anlegen erstellen wir schlie&szlig;lich vollautomatisch die gew&uuml;nschte Schaltfl&auml;che.<\/p>\n<p>Bild 3 zeigt einige Beispiele f&uuml;r solche Schaltfl&auml;chen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_007.png\" alt=\"Einige Beispielschaltfl&auml;chen, die mit der L&ouml;sung aus diesem Beitrag erstellt wurden\" width=\"424,5589\" height=\"220,4835\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Einige Beispielschaltfl&auml;chen, die mit der L&ouml;sung aus diesem Beitrag erstellt wurden<\/span><\/b><\/p>\n<h2>Formular zum Anlegen von Steuerelementen<\/h2>\n<p>Um die gew&uuml;nschten Einstellungen vorzunehmen, stellen wir ein entsprechendes Formular bereit. Dieses legen wir in einer neuen, leeren Datenbankdatei unter dem Namen <b>frmButtonWizard <\/b>an.<\/p>\n<p>Hier wollen wir zuerst die Beschriftung des Steuerelements abfragen und daraus direkt bei der Eingabe den Namen des Steuerelements ableiten. Dazu f&uuml;gen wir die Steuerelemente aus Bild 4 hinzu.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_002.png\" alt=\"Erster Entwurf des Formulars\" width=\"549,559\" height=\"157,4308\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Erster Entwurf des Formulars<\/span><\/b><\/p>\n<p>Die erste Schaltfl&auml;che hei&szlig;t <b>txtBeschriftung<\/b>, die zweite <b>txtSteuerelementname<\/b>. Die Schaltfl&auml;che nennen wir <b>cmdAktualisieren<\/b>.<\/p>\n<p>Der Benutzer soll die Beschriftung der Schaltfl&auml;che in <b>txtBeschriftung<\/b> eingeben. Dadurch l&ouml;sen wir bei der Eingabe eines jeden einzelnen Zeichens das Ereignis <b>Bei &Auml;nderung <\/b>aus. F&uuml;r dieses hinterlegen wir die folgende Ereignisprozedur:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>txtBeschriftung_Change()\r\n    <span style=\"color:blue;\">Call<\/span> SteuerelementnameAktualisieren( _\r\n        Me.txtBeschriftung.Text)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese ruft die Prozedur <b>SteuerelementnameAktualisieren <\/b>auf und &uuml;bergibt dieser den aktuellen Text des Textfeldes <b>txtBeschriftung <\/b>als Parameter.<\/p>\n<p>In dieser Prozedur (siehe Listing 1) erzeugen wir mit <b>Split <\/b>aus den einzelnen W&ouml;rtern der Beschriftung ein Array namens <b>strWoerter <\/b>&#8211; dieses kann auch nur ein Element enthalten. Danach durchlaufen wir alle Elemente des Arrays und f&uuml;gen diese aneinander. Dabei wird das erste Zeichen eines jeden Wortes gro&szlig;geschrieben und bei den &uuml;brigen wird die Schreibweise beibehalten. So wird aus <b>Datensatz anlegen <\/b>der Text <b>DatensatzAnlegen<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>SteuerelementnameAktualisieren(strBeschriftung<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>strTemp<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strWoerter()<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n    <span style=\"color:blue;\">If <\/span>bolManuellGeaendert = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Exit Sub<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strBeschriftung) = 0<span style=\"color:blue;\"> Then<\/span>\r\n        strWoerter = <span style=\"color:blue;\">Split<\/span>(strBeschriftung, \" \")\r\n        For i = <span style=\"color:blue;\">LBound<\/span>(strWoerter) To <span style=\"color:blue;\">UBound<\/span>(strWoerter)\r\n            strTemp = strTemp & StrConv(<span style=\"color:blue;\">Left<\/span>(strWoerter(i), 1), vbUpperCase) & <span style=\"color:blue;\">Mid<\/span>(strWoerter(i), 2)\r\n        <span style=\"color:blue;\">Next<\/span> i\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \" \", \"\")\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \"&auml;\", \"ae\")\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \"&ouml;\", \"oe\")\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \"&uuml;\", \"ue\")\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \"&Auml;\", \"Ae\")\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \"&Ouml;\", \"Oe\")\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \"&Uuml;\", \"Ue\")\r\n        strTemp = <span style=\"color:blue;\">Replace<\/span>(strTemp, \"&szlig;\", \"ss\")\r\n        strTemp = AlphanumerischBereinigt(strTemp)\r\n        strTemp = \"cmd\" & strTemp\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        strTemp = \"\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    Me.txtSteuerelementname = strTemp\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Aktualisieren des Steuerelementnamens<\/span><\/b><\/p>\n<p>Danach ersetzt die Prozedur die Umlaute und das scharfe &szlig; durch die entsprechenden Umschreibungen. Schlie&szlig;lich lassen wir den aktuellen Text noch durch die Funktion <b>AlphanumerischBereinigen<\/b> laufen, in der alle Zeichen au&szlig;er a-z, A-Z und 0-9 entfernt werden. Diese Funktion sehen wir in Listing 2.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>AlphanumerischBereinigt(ByVal strEingabe<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strErgebnis<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strZeichen<span style=\"color:blue;\"> As String<\/span>\r\n    For i = 1 To <span style=\"color:blue;\">Len<\/span>(strEingabe)\r\n        strZeichen = Mid$(strEingabe, i, 1)\r\n        <span style=\"color:blue;\">If <\/span>strZeichen Like \"[A-Za-z0-9]\"<span style=\"color:blue;\"> Then<\/span>\r\n            strErgebnis = strErgebnis & strZeichen\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Next<\/span> i\r\n    AlphanumerischBereinigt = strErgebnis\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Entfernen nicht-alphanumerischer Zeichen<\/span><\/b><\/p>\n<p>Es kann auch sein, dass der Benutzer den so generierten Steuerelementnamen manuell anpassen m&ouml;chte. Das kann er tun und wir stellen dann den Wert einer Variablen namens <b>bolManuellGeaendert<\/b>, die wir wie folgt deklarieren, auf <b>True <\/b>ein:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>bolManuellGeaendert<span style=\"color:blue;\"> As Boolean<\/span><\/pre>\n<p>Bei einer &Auml;nderung im Textfeld <b>txtSteuerelementname <\/b>wird die folgende Ereignisprozedur ausgel&ouml;st, welche <b>bolManuellGeaendert <\/b>auf <b>True <\/b>einstellt, den aktuellen Text in einer <b>TempVar<\/b>-Variablen speichert (so kann diese beispielsweise bei Laufzeitfehlern nicht gel&ouml;scht werden) und anschlie&szlig;end die Routine <b>VorschauAktualisieren <\/b>aufruft, die wir weiter unten beschreiben:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>txtSteuerelementname_Change()\r\n    bolManuellGeaendert = <span style=\"color:blue;\">True<\/span>\r\n    TempVars(\"Steuerelementname\") = _\r\n        Me.txtSteuerelementname.Text\r\n    <span style=\"color:blue;\">Call<\/span> VorschauAktualisieren\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Schlie&szlig;lich fehlt noch die Schaltfl&auml;che <b>cmdAktualisieren<\/b>. Diese soll, falls der Benutzer den Steuerelementnamen bereits manuell angepasst hat, die automatische Aktualisierung wieder aktivieren, indem sie erstens eine initiale Aktualisierung durchf&uuml;hrt und <b>bolManuellGeaendert <\/b>wieder auf <b>False <\/b>einstellt.<\/p>\n<p>Dadurch werden folgende &Auml;nderungen in <b>txtBeschriftung <\/b>wieder in <b>txtSteuerelementname <\/b>&uuml;bertragen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAktualisieren_Click()    \r\n    Me.txtFilter.SetFocus\r\n    <span style=\"color:blue;\">Call<\/span> SteuerelementnameAktualisieren( _\r\n        Nz(Me.txtBeschriftung, \"\"))\r\n    bolManuellGeaendert = <span style=\"color:blue;\">False<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Icon ausw&auml;hlen<\/h2>\n<p>Nun folgt ein spannender Teil. Wie wollen wir die Auswahl eines Icons realisieren? Wir k&ouml;nnten einfach einen Dateiauswahl-Dialog &ouml;ffnen und den Benutzer das gew&uuml;nschte Icon ausw&auml;hlen lassen. Dieses w&uuml;rden wir anschlie&szlig;end in der Tabelle <b>MSysResources <\/b>der Zieldatenbank speichern und f&uuml;r die Schaltfl&auml;che verwenden.<\/p>\n<p>Praktischer w&auml;re es jedoch, wenn wir die einmal verwendeten Icons direkt auch in unserer L&ouml;sung speichern und f&uuml;r die weitere Verwendung direkt zur Auswahl anbieten &#8211; zum Beispiel, wenn wir ein Add-In aus dieser L&ouml;sung erstellen. Dann h&auml;tte der Benutzer einen Schritt weniger bei bereits verwendeten Icons und k&ouml;nnte diese direkt ausw&auml;hlen.<\/p>\n<p>Also legen wir dazu eine neue Tabelle namens <b>tblResources <\/b>an, die genauso aufgebaut ist wie die Tabelle <b>MSysResources<\/b>. Genau genommen haben wir diese einfach kopiert und unter dem Namen <b>tblResources <\/b>wieder eingef&uuml;gt. Den Entwurf dieser Tabelle sehen Sie in Bild 5.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_003.png\" alt=\"Tabelle zum Speichern der Icons\" width=\"499,5589\" height=\"403,202\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Tabelle zum Speichern der Icons<\/span><\/b><\/p>\n<p>Damit kommen wir zur Schaltfl&auml;che <b>cmdBilderAuswaehlen<\/b>, die im Entwurf aus Bild 6 markiert ist.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_004.png\" alt=\"Vollst&auml;ndiger Entwurf des Formulars frmButtonWizard\" width=\"499,5589\" height=\"459,771\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Vollst&auml;ndiger Entwurf des Formulars frmButtonWizard<\/span><\/b><\/p>\n<p>Diese soll einen <b>Dateiauswahl<\/b>-Dialog anzeigen und die Bilder anschlie&szlig;end in der Tabelle <b>tblResources <\/b>speichern. Dazu deklarieren wir eine Konstante, welche die dabei zu verwendende Tabelle enth&auml;lt:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>Const cStrResourcesTable<span style=\"color:blue;\"> As String<\/span> _\r\n    = \"tblResources\"<\/pre>\n<p>Die Prozedur <b>cmdBilderAuswaehlen <\/b>ruft die Funktion <b>ChooseFiles <\/b>auf, die im Modul <b>mdlFileDialog <\/b>enthalten ist und den Standard-Office-Dialog zum Ausw&auml;hlen von Dateien verwendet. Sie speichert die ausgew&auml;hlten Dateipfade in der Variablen <b>strFileList<\/b>. Wenn diese nicht leer ist, unterteilt sie diese Liste jeweils am Pipe-Zeichen (<b>|<\/b>) und schreibt die einzelnen Pfade in ein Array namens <b>strFiles<\/b>.<\/p>\n<p>F&uuml;r jede Datei ruft sie einmal die Routine <b>BildInRessourcenSpeichern <\/b>auf und &uuml;bergibt dieser den Dateipfad und den Namen der Tabelle, in der das Icon gespeichert werden soll.<\/p>\n<p>Nachdem alle Icons gespeichert sind, ruft sie die Prozedur <b>LoadImages <\/b>auf, die daf&uuml;r sorgt, dass die aktuell in der Tabelle <b>tblResources <\/b>gespeicherten Icons in der Matrix im Formular angezeigt werden.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdBilderAuswaehlen_Click()\r\n    <span style=\"color:blue;\">Dim <\/span>strFilelist<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strFiles()<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>var<span style=\"color:blue;\"> As Variant<\/span>\r\n    \r\n    Me.txtFilter.SetFocus\r\n    strFilelist = ChooseFiles\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strFilelist) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n        strFiles = <span style=\"color:blue;\">Split<\/span>(strFilelist, \"|\")\r\n        For Each var In strFiles\r\n            BildInRessourcenSpeichern CStr(var), _\r\n                cStrResourcesTable\r\n        <span style=\"color:blue;\">Next<\/span> var\r\n        <span style=\"color:blue;\">Call<\/span> LoadImages\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wie die Routine <b>LoadImages <\/b>funktioniert, erl&auml;utern wir im Detail im Beitrag <b>Icons in der Datenbank verwalten <\/b>(<b>www.access-im-unternehmen.de\/1564<\/b>).<\/p>\n<p>Und wie wir die Matrix aus Bild-Steuerelementen erzeugen, die Sie im Formularentwurf sehen, beschreiben wir im Beitrag <b>Schaltfl&auml;chen-Matrix per VBA erzeugen <\/b>(<b>www.access-im-unternehmen.de\/1562<\/b>).<\/p>\n<h2>Vorschau der Schaltfl&auml;che anzeigen<\/h2>\n<p>Damit haben wir nun die Textfelder, in denen die Beschriftung und der Steuerelementname gespeichert sind. Au&szlig;erdem haben wir eine Funktion, mit der wir die als Icons zu verwendenden Bilder in die Tabelle <b>tblResources <\/b>laden k&ouml;nnen und eine Matrix aus Bild-Steuerelementen, mit denen wir die verf&uuml;gbaren Icons anzeigen. Au&szlig;erdem haben im oben angegebenen Artikel beschrieben, wie wir zwischen den Bildern navigieren k&ouml;nnen, wenn die Tabelle <b>tblResources <\/b>mehr Bilder enth&auml;lt, als auf einen Blick angezeigt werden k&ouml;nnen.<\/p>\n<p>Damit kommen wir zur Anzeige der Vorschau f&uuml;r die zu erstellende Schaltfl&auml;che. Diese soll immer aktualisiert werden, wenn wir eine &Auml;nderung an der Beschriftung oder dem gew&auml;hlten Icon vornehmen.<\/p>\n<p>Die dadurch ausgel&ouml;ste Prozedur hei&szlig;t <b>VorschauAktualisieren<\/b> (siehe Listing 3). Sie referenziert die als Beispielschaltfl&auml;che angelegte Schaltfl&auml;che namens <b>cmdVorschau<\/b>. Dann holt sie mit der Funktion <b>Schriftabmessungen <\/b>die Breite und die H&ouml;he f&uuml;r die anzuzeigende Beschriftung und liefert diese mit den beiden Parametern <b>lngBreite <\/b>und <b>lngHoehe <\/b>zur&uuml;ck (diese Funktion beschreiben wir im Anschluss).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>VorschauAktualisieren()\r\n    <span style=\"color:blue;\">Dim <\/span>lngHoehe<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngBreite<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>varPictureData<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>bolAktivieren<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">With<\/span> Me.cmdVorschau\r\n        <span style=\"color:blue;\">Call<\/span> Schriftabmessungen(lngBreite, lngHoehe)\r\n        .Height = 480        \r\n        Me.Painting = <span style=\"color:blue;\">False<\/span>\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(TempVars(\"Picture\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n            .PictureData = Null\r\n            .Caption = Nz(TempVars(\"Beschriftung\"), \"\")\r\n            .Width = lngBreite + 480\r\n            .Alignment = 2\r\n            <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(.Caption) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                bolAktivieren = <span style=\"color:blue;\">True<\/span>\r\n            <span style=\"color:blue;\">End If<\/span>\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            <span style=\"color:blue;\">If <\/span>GetPictureDataFromResourcesByName(TempVars(\"Picture\"), varPictureData, cStrResourcesTable) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                .PictureData = varPictureData\r\n                .PictureType = 2\r\n                <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(TempVars(\"Beschriftung\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                    .Caption = \"  \" & TempVars(\"Beschriftung\")\r\n                    .Width = lngBreite + 600\r\n                    .Alignment = 1\r\n                <span style=\"color:blue;\">Else<\/span>\r\n                    .Caption = \"\"\r\n                    .Width = 480\r\n                    .Alignment = 2\r\n                <span style=\"color:blue;\">End If<\/span>\r\n                bolAktivieren = <span style=\"color:blue;\">True<\/span>\r\n            <span style=\"color:blue;\">End If<\/span>\r\n        End If        \r\n        Me.Painting = <span style=\"color:blue;\">True<\/span>\r\n        Me.cmdVorschau.Requery        \r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(TempVars(\"Steuerelementname\"), \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n        bolAktivieren = <span style=\"color:blue;\">False<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">If <\/span>bolAktivieren = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n       Me.cmdSchaltflaecheAnlegen.Enabled = <span style=\"color:blue;\">True<\/span>\r\n    <span style=\"color:blue;\">Else<\/span>\r\n       Me.cmdSchaltflaecheAnlegen.Enabled = <span style=\"color:blue;\">False<\/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 3: Aktualisieren der Schaltfl&auml;chen-Vorschau<\/span><\/b><\/p>\n<p>Als H&ouml;he des Steuerelements legen wir 480 Pixel fest. Mit <b>Me.Painting = False<\/b> verhindern wir w&auml;hrend des Vorgangs das Neuzeichnen des Formulars, damit es nicht zu unn&ouml;tigem Flackern kommt.<\/p>\n<p>Dann lesen wir aus der <b>TempVar<\/b>-Variablen <b>Picture <\/b>den zuvor zwischengespeicherten Namen des zu verwendenden Icons aus. Hat diese Zeichenkette die L&auml;nge <b>0<\/b>, leeren wir die Eigenschaft <b>PictureData <\/b>der Schaltfl&auml;che, tragen die Beschriftung ein, legen die Breite auf <b>480 <\/b>plus der ermittelten Breite f&uuml;r die Beschriftung aus <b>lngWidth <\/b>fest und stellen die Ausrichtung auf linksb&uuml;ndig ein. Schlie&szlig;lich legen wir f&uuml;r die Variable <b>bolAktivieren <\/b>den Wert <b>True <\/b>fest. Dieser wird sp&auml;ter ausgewertet, um die Schaltfl&auml;che zum Anlegen der neuen Schaltfl&auml;che zu aktivieren oder zu deaktivieren.<\/p>\n<p>Wenn die <b>TempVar<\/b>-Variable gef&uuml;llt ist, gelangen wir in den <b>Else<\/b>-Zweig der Bedingung. Hier rufen wir die Funktion <b>GetPictureDataFromResourcesByName <\/b>auf, die wir im Modul <b>mdlPictureData <\/b>finden. Dieser Funktion &uuml;bergeben wir den Namen des einzulesenden Icons, die Tabelle, in der sich das Icon befindet (hier <b>tblResources<\/b>) und eine leere <b>Variant<\/b>-Variable, die wir mit dem zu verwendenden Bild-Objekt f&uuml;llen. Liefert die Funktion den Wert <b>True <\/b>als Ergebnis zur&uuml;ck, konnte das Bild erfolgreich eingelesen werden.<\/p>\n<p>Dann weisen wir den Inhalt von <b>varPictureData <\/b>der Eigenschaft <b>PictureData <\/b>der Vorschau-Schaltfl&auml;che zu und stellen <b>PictureType <\/b>auf <b>2 <\/b>ein.<\/p>\n<p>Enth&auml;lt die <b>TempVar<\/b>-Variable <b>Beschriftung <\/b>einen Text, wird dieser f&uuml;r die Eigenschaft <b>Caption <\/b>als Beschriftung eingetragen. Au&szlig;erdem wird die Breite auf 600 Pixel plus der zuvor ermittelten Breite der Beschriftung eingestellt und <b>bolAktivieren <\/b>erh&auml;lt den Wert <b>True<\/b>.<\/p>\n<p><b>bolAktivieren <\/b>hat anschlie&szlig;end nur den Wert <b>False<\/b>, wenn  weder eine Bildbeschriftung vorliegt noch ein Bild ausgew&auml;hlt wurde.<\/p>\n<p>Danach aktivieren wir mit <b>Me.Painting = True <\/b>das Neuzeichnen des Formulars wieder und aktualisieren die Anzeige der Vorschau-Schaltfl&auml;che.<\/p>\n<p>Danach pr&uuml;fen wir den Wert von <b>bolAktivieren<\/b>. Hat diese Variable den Wert <b>True<\/b>, aktivieren wir die Schaltfl&auml;che <b>cmdSchaltflaecheAnlegen<\/b>, andernfalls deaktivieren wir diese. Damit stellen wir sicher, dass die Schaltfl&auml;che nicht angelegt werden kann, wenn noch Informationen fehlen.<\/p>\n<h2>Die Funktion &#8222;Schriftabmessungen&#8220;<\/h2>\n<p>Die Funktion <b>Schriftabmessungen <\/b>soll die Breite ermitteln, welche die angegebene Beschriftung in den f&uuml;r die Schaltfl&auml;che eingestellten Schrifteigenschaften einnehmen wird (siehe Listing 4). Damit stellen wir sicher, dass die Schaltfl&auml;che in genau der richtigen Breite angelegt wird.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Schriftabmessungen(lngBreite<span style=\"color:blue;\"> As Long<\/span>, lngHoehe<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>strFontname<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngFontsize<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngFontweight<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>bolFontItalic<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>bolFontUnderline<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strText<span style=\"color:blue;\"> As String<\/span>\r\n    WizHook.Key = 51488399\r\n    \r\n    <span style=\"color:blue;\">With<\/span> Me.cmdVorschau\r\n        strFontname = .FontName\r\n        lngFontsize = .FontSize\r\n        lngFontweight = .FontWeight\r\n        bolFontItalic = .FontItalic\r\n        bolFontUnderline = .FontUnderline\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(TempVars(\"Picture\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n            strText = Nz(TempVars(\"Beschriftung\"), \"\")\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            strText = \"  \" & TempVars(\"Beschriftung\")\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">Call<\/span> WizHook.TwipsFromFont(strFontname, lngFontsize, lngFontweight, bolFontItalic, bolFontUnderline, 0, strText, _\r\n        0, lngBreite, lngHoehe)\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Ermitteln der Schriftbreite des Textes f&uuml;r die Schaltfl&auml;che<\/span><\/b><\/p>\n<p>Die beiden Parameter der Funktion dienen als R&uuml;ckgabeparameter, wobei wir hier nur den Parameter <b>lngBreite<\/b> verwenden. Damit die Funktion auch in anderen Settings genutzt werden kann, haben wir jedoch auch die H&ouml;he mitber&uuml;cksichtigt.<\/p>\n<p>Die Funktion nutzt eine Funktion einer nicht dokumentierten Klasse namens <b>Wizhook<\/b>, die einige praktische Funktionen bereitstellt. Um die Funktionen dieser Klasse zu nutzen, m&uuml;ssen wir zun&auml;chst die Eigenschaft <b>Key <\/b>dieser Klasse auf den Wert <b>51488399 <\/b>einstellen.<\/p>\n<p>Dann ermitteln wir anhand der <b>Vorschau<\/b>-Schaltfl&auml;che <b>cmdVorschau <\/b>die Schriftart, die Schriftgr&ouml;&szlig;e, die Schriftdicke und die beiden Eigenschaften <b>Kursiv <\/b>und <b>Unterstrichen <\/b>und schreiben diese in entsprechende Variablen.<\/p>\n<p>Anschlie&szlig;end pr&uuml;fen wir, ob die <b>TempVar<\/b>-Variable <b>Picture <\/b>ein Icon enth&auml;lt. Falls nicht, speichern wir die reine Beschriftung f&uuml;r die Schaltfl&auml;che in <b>strText<\/b>. Andernfalls f&uuml;gen wir noch zwei Leerzeichen an, die zwischen Icon und Beschriftung als Platzhalter hinzugef&uuml;gt werden sollen, und speichern diese Zeichenkette in <b>strText<\/b>. So berechnen wir f&uuml;r beide F&auml;lle &#8211; mit und ohne Icon &#8211; die korrekte Breite f&uuml;r die Beschriftung.<\/p>\n<p>Diese holen wir schlie&szlig;lich mit der Funktion <b>TwipsFromFont <\/b>der <b>Wizhook<\/b>-Klasse, der wir die zuvor eingesammelten Informationen &uuml;ber die Schrift und den Text als Parameter &uuml;bergeben.<\/p>\n<p>Die letzten beiden Parameter dieser Funktion werden mit der Breite und der H&ouml;he dieser Beschriftung gef&uuml;llt.<\/p>\n<h2>Erstellen der Schaltfl&auml;che<\/h2>\n<p>Damit kommen wir zum entscheidenden Schritt: Wir wollen per Mausklick die Schaltfl&auml;che mit den angegebenen Eigenschaften erstellen.<\/p>\n<p>Diesen Vorgang starten wir mit der Ereignisprozedur, die durch einen Mausklick auf die Schaltfl&auml;che <b>cmdSchaltflaecheAnlegen <\/b>ausgel&ouml;st wird. Diese ruft eine weitere Prozedur namens <b>SchaltflaecheAnlegen <\/b>auf:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdSchaltflaecheAnlegen_Click()\r\n    Me.txtFilter.SetFocus\r\n    <span style=\"color:blue;\">Call<\/span> SchaltflaecheAnlegen\r\n    cmdSchaltflaecheAnlegen.Enabled = <span style=\"color:blue;\">False<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Die Prozedur &#8222;SchaltflaecheAnlegen&#8220;<\/h2>\n<p>Diese Prozedur (siehe Listing 5) legt zun&auml;chst die Koordinaten f&uuml;r das Anlegen des neuen Steuerelements fest. Dann f&uuml;llt sie die beiden Database-Variablen <b>db <\/b>und <b>dbc<\/b>. <b>db <\/b>erh&auml;lt einen Verweis auf die aktuell ge&ouml;ffnete Datenbank. <b>dbc <\/b>f&uuml;llen wir mit einem Verweis auf die Datenbank mit der in diesem Beitrag beschriebenen L&ouml;sung. Dies ist ein vorbereitender Schritt darauf, dass wir die L&ouml;sung als Add-In verwenden.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>SchaltflaecheAnlegen()\r\n    <span style=\"color:blue;\">Dim <\/span>cmd<span style=\"color:blue;\"> As <\/span>Access.CommandButton\r\n    <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>Property\r\n    <span style=\"color:blue;\">Dim <\/span>strPicture<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngPictureID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngLeft<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngTop<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>dbc<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    \r\n    lng<span style=\"color:blue;\">Left<\/span> = 1000\r\n    lngTop = 1000\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n    <span style=\"color:blue;\">Call<\/span> PositionLetzterButton(dbc, lngLeft, lngTop)\r\n    <span style=\"color:blue;\">If <\/span>SchaltflaecheSchonVorhanden(Me.txtSteuerelementname) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Exit Sub<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> cmd = CreateControl(TempVars(\"Form\"), acCommandButton, acDetail, , , lngLeft, lngTop, Me.cmdVorschau.Width, _\r\n        Me.cmdVorschau.Height)\r\n    <span style=\"color:blue;\">With<\/span> cmd\r\n        For Each prp In cmdVorschau.Properties\r\n            Select Case prp.Name\r\n                <span style=\"color:blue;\">Case <\/span>\"Top\", \"Left\"\r\n                <span style=\"color:blue;\">Case <\/span>\"EventProcPrefix\", \"ControlType\", \"Section\", \"RowStart\", \"RowEnd\", \"ColumnStart\", _\r\n                    \"ColumnEnd\", \"TabIndex\", \"InSelection\", \"Name\"\r\n                <span style=\"color:blue;\">Case Else<\/span>\r\n                    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                    .Properties(prp.Name) = prp.Value\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;\">Next<\/span> prp\r\n        strPicture = Me.cmdVorschau.Picture\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> strPicture = \"(keines)\"<span style=\"color:blue;\"> Then<\/span>\r\n            lngPictureID = CodeDb.OpenRecordset(\"SELECT ID FROM \" & cStrResourcesTable & \" WHERE Name = ''\" _\r\n                & TempVars(\"Picture\") & \"''\", dbOpenDynaset).Fields(\"ID\")\r\n            BildKopierenVonResourceZuResource dbc, db, cStrResourcesTable, \"MSysResources\", lngPictureID\r\n        <span style=\"color:blue;\">End If<\/span>\r\n        .Picture = TempVars(\"Picture\")\r\n        .Name = Nz(Me.txtSteuerelementname, \"\")\r\n        .OnClick = \"[Event Procedure]\"\r\n        .Parent.HasModule = <span style=\"color:blue;\">True<\/span>\r\n        dbc.Execute \"INSERT INTO tblHistory(Formularname, Buttonname, Buttondatum) VALUES(''\" & Nz(TempVars(\"Form\"), \"\") _\r\n            & \"'', ''\" & Nz(Me.txtSteuerelementname, \"\") & \"'', #\" & Format(Now, \"yyyy-mm-dd hh:nn:ss\") & \"#)\", dbFailOnError\r\n        <span style=\"color:blue;\">Call<\/span> EreignisprozedurAnlegen(TempVars(\"Form\"), Me.txtSteuerelementname)\r\n        <span style=\"color:blue;\">Call<\/span> AccessAktivieren\r\n    End <span style=\"color:blue;\">With<\/span>   \r\n    <span style=\"color:blue;\">Call<\/span> FormularZuruecksetzen    \r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Erstellen der Schaltfl&auml;che<\/span><\/b><\/p>\n<p>Es kann sein, dass ein Benutzer gleich mehrere Schaltfl&auml;chen mit dem Formular anlegt. Dann sollen neue Schaltfl&auml;chen nicht mit den gleichen Koordinaten der bereits angelegten Schaltfl&auml;che angelegt werden, sondern unter dieser Schaltfl&auml;che. Deshalb speichern wir die Koordinaten der zuletzt angelegten Schaltfl&auml;che in der Tabelle <b>tblHistory<\/b> (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1563_005.png\" alt=\"Tabelle zum Speichern der Koordinaten bereits angelegter Schaltfl&auml;chen\" width=\"499,5589\" height=\"390,3096\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Tabelle zum Speichern der Koordinaten bereits angelegter Schaltfl&auml;chen<\/span><\/b><\/p>\n<h2>Koordinaten f&uuml;r die neue Schaltfl&auml;che ermitteln<\/h2>\n<p>Die Funktion <b>PositionLetzterButton <\/b>nimmt einen Verweis auf <b>dbc <\/b>sowie die Variablen f&uuml;r die Koordinaten entgegen. Sie &ouml;ffnet ein Recordset auf Basis der Tabelle <b>tblHistory <\/b>und holt dabei lediglich den neuesten Eintrag, der im aktuellen Formular angelegt wurde.<\/p>\n<p>Sie liest den Namen dieser Schaltfl&auml;che in <b>strLetzterButton <\/b>ein und referenziert diesen dann auf dem Formular. Ist dies erfolgreich und der Benutzer hat die Schaltfl&auml;che nicht etwa wieder gel&ouml;scht, lesen wir die Koordinaten dieser Schaltfl&auml;che ein und f&uuml;gen der <b>Top<\/b>-Koordinate die H&ouml;he der Schaltfl&auml;che plus 100 Twips hinzu:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>PositionLetzterButton(dbc<span style=\"color:blue;\"> As <\/span>DAO.Database,  _\r\n        lngLeft<span style=\"color:blue;\"> As Long<\/span>, lngTop<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>rstHistory<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>strLetzterButton<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>cmdLetzterButton<span style=\"color:blue;\"> As <\/span>CommandButton\r\n    <span style=\"color:blue;\">Set<\/span> rstHistory = dbc.OpenRecordset( _\r\n        \"SELECT TOP 1 * FROM tblHistory \" _\r\n        & \"WHERE Formularname = ''\" & TempVars(\"Form\") _\r\n        & \"'' ORDER BY Buttondatum DESC\", dbOpenDynaset)\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rstHistory.EOF<span style=\"color:blue;\"> Then<\/span>\r\n        strLetzterButton = rstHistory!ButtonName\r\n        On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n        <span style=\"color:blue;\">Set<\/span> cmdLetzterButton = _\r\n            Forms(TempVars(\"Form\")).Controls(strLetzterButton)\r\n        <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> cmdLetzterButton Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n            lng<span style=\"color:blue;\">Left<\/span> = cmdLetzterButton.Left\r\n            lngTop = cmdLetzterButton.Top _\r\n                + Me.cmdVorschau.Height + 100\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 Function<\/span><\/pre>\n<h2>Pr&uuml;fen, ob bereits eine Schaltfl&auml;che gleichen Namens vorhanden ist<\/h2>\n<p>Au&szlig;erdem pr&uuml;fen wir mit einer weiteren Funktion namens <b>SchaltflaecheSchonVorhanden<\/b>, ob bereits eine Schaltfl&auml;che mit dem Namen der anzulegenden Schaltfl&auml;che existiert. Falls ja, wird die Prozedur an dieser Stelle verlassen.<\/p>\n<p>Die Funktion <b>SchaltflaecheSchonVorhanden <\/b>nimmt den Namen der Schaltfl&auml;che entgegen und versucht, ein Steuerelement mit diesem Namen zu referenzieren. Ist die Variable <b>cmdTemp <\/b>anschlie&szlig;end nicht leer, existiert bereits eine entsprechende Schaltfl&auml;che. Dann gibt die Funktion eine passende Meldung aus und liefert den Wert <b>True <\/b>zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>SchaltflaecheSchonVorhanden( _\r\n        strSchaltflaeche<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>cmdTemp<span style=\"color:blue;\"> As <\/span>CommandButton\r\n    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> cmdTemp = _\r\n        Forms(TempVars(\"Form\")).Controls(strSchaltflaeche)\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> cmdTemp Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">MsgBox<\/span> \"Es ist bereits eine Schaltfl&auml;che \" _\r\n            & \"namens ''\" & Me.txtSteuerelementname _\r\n            & \"'' vorhanden.\", vbOKOnly + <span style=\"color:blue;\">vbCr<\/span>itical, _\r\n           \"Schaltfl&auml;che bereits vorhanden\"\r\n       SchaltflaecheSchonVorhanden = <span style=\"color:blue;\">True<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Anlegen der Schaltfl&auml;che<\/h2>\n<p>Sind alle Bedingungen erf&uuml;llt, legt die Prozedur <b>SchaltflaecheAnlegen <\/b>die neue Schaltfl&auml;che mit der Anweisung <b>CreateControl <\/b>an.<\/p>\n<p>Dabei &uuml;bergibt sie den Namen des Zielformulars, den Steuerelementtyp (<b>acCommandButton<\/b>), den Zielbereich (<b>acDetail<\/b>), die Koordinaten der linken und oberen Ecke sowie die H&ouml;he und die Breite entsprechend der Vorschauschaltfl&auml;che <b>cmdVorschau <\/b>als Parameter.<\/p>\n<p>Das Ergebnis weist sie der Variablen <b>cmd <\/b>zu, f&uuml;r die wir weitere Einstellungen vornehmen. Diese sollen weitgehend denen der Vorschau-Schaltfl&auml;che entsprechen.<\/p>\n<p>Deshalb durchlaufen wir alle Eigenschaften dieser Schaltfl&auml;che und &uuml;bertragen diese mit wenigen Ausnahmen auf die neu angelegte Schaltfl&auml;che.<\/p>\n<p>Ausnahmen sind die Koordinaten aus den Eigenschaften <b>Top <\/b>und <b>Left <\/b>sowie einige weitere Eigenschaften, die nicht &uuml;bertragen werden sollen.<\/p>\n<p>Dann schreiben wir den Namen des Icons der Vorschau-Schaltfl&auml;che in die Variable <b>strPicture<\/b>. Ist der Wert nicht gleich <b>(keines)<\/b>, ermitteln wir die ID des Datensatzes zu diesem Icon aus der Tabelle <b>strResources <\/b>der Datenbank mit der L&ouml;sung.<\/p>\n<p>F&uuml;r diese ID rufen wir die Funktion <b>BildKopierenVonResourceZuResource <\/b>auf und speichern das Bild damit in der Tabelle <b>MSysResources <\/b>der Zieldatenbank. Diese finden wir im Modul <b>mdlMSysResources<\/b>.<\/p>\n<p>Da das Icon nun in der Tabelle <b>MSysResources<\/b> der Zieldatenbank vorliegt, k&ouml;nnen wir die Eigenschaft <b>Picture <\/b>der angelegten Schaltfl&auml;che einfach auf den Namen dieses Bildes einstellen. Au&szlig;erdem legen wir den Namen der Schaltfl&auml;che fest und stellen die Ereigniseigenschaft <b>Beim Klicken <\/b>durch Zuweisen von <b>[Event Procedure]<\/b> an die VBA-Eigenschaft <b>OnClick <\/b>auf <b>[Ereigniseigenschaft] <\/b>ein.<\/p>\n<p>Schlie&szlig;lich m&uuml;ssen wir, da dies nicht immer schon der Fall ist, die Eigenschaft <b>HasModule <\/b>des Formulars auf <b>True <\/b>einstellen. Dadurch wird ein Klassenmodul f&uuml;r dieses Formular angelegt.<\/p>\n<p>Nachdem dies geschehen ist, tragen wir die Daten der erstellten Schaltfl&auml;che in die Tabelle <b>tblHistory <\/b>ein.<\/p>\n<h2>Ereignisprozedur f&uuml;r die Schaltfl&auml;che anlegen<\/h2>\n<p>Durch einen Aufruf der Funktion <b>EreignisprozedurAnlegen <\/b>aus Listing 6 legen wir den Dummy f&uuml;r die Ereignisprozedur im Klassenmodul des Formulars an.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>EreignisprozedurAnlegen(strFormular<span style=\"color:blue;\"> As String<\/span>, strSchaltflaeche<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBide.VBComponent\r\n    <span style=\"color:blue;\">Dim <\/span>lngLine<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>objVBProject<span style=\"color:blue;\"> As <\/span>VBide.VBProject\r\n    For Each objVBProject In VBE.VBProjects\r\n        <span style=\"color:blue;\">If <\/span>objVBProject.FileName = CurrentDb.Name<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">Exit For<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Next<\/span> objVBProject\r\n    \r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objVBProject Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Set<\/span> objVBComponent = objVBProject.VBComponents(\"Form_\" & strFormular)\r\n        <span style=\"color:blue;\">Call<\/span> objVBComponent.CodeModule.CreateEventProc(\"Click\", strSchaltflaeche)\r\n        lngLine = objVBComponent.CodeModule.ProcBodyLine(strSchaltflaeche & \"_Click\", vbext_pk_Proc)\r\n        objVBComponent.CodeModule.ReplaceLine lngLine + 1, \"    <span style=\"color:blue;\">MsgBox<\/span> \"\"Noch nicht implementiert.\"\"\"\r\n        objVBComponent.CodeModule.CodePane.SetSelection lngLine + 1, 5, lngLine + 1, 5\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Hinzuf&uuml;gen der Ereignisprozedur f&uuml;r die Schaltfl&auml;che<\/span><\/b><\/p>\n<p>Die Funktion nimmt den Namen des Formulars und den der Schaltfl&auml;che entgegen. Dann ermittelt sie das aktuelle VBA-Projekt. Das ist f&uuml;r den Fall notwendig, dass wir die L&ouml;sung als Add-In einsetzen.<\/p>\n<p>In diesem Fall kann es sein, dass sowohl das VBA-Projekt des Add-Ins als auch das der aktuell ge&ouml;ffneten Access-Datenbanken im VBA-Editor angezeigt werden &#8211; und dann m&uuml;ssen wir das passende VBA-Projekt finden.<\/p>\n<p>Dazu durchlaufen wir alle aktuell geladenen VBA-Projekte und vergleichen den Dateinamen des VBA-Projekts mit dem der aktuellen Datenbank (&uuml;ber <b>CurrentDb.Name<\/b>).<\/p>\n<p>Danach referenzieren wir das Klassenmodul des Formulars, dem die Schaltfl&auml;che hinzugef&uuml;gt werden soll. Der Name des Klassenmoduls setzt sich aus der Zeichenkette <b>Form_ <\/b>und dem Namen des Formulars zusammen.<\/p>\n<p>F&uuml;r dieses Modul rufen wir die Methode <b>CreateEventProc <\/b>des <b>CodeModule<\/b>-Objekts auf. Dieser &uuml;bergeben wir den Namen des Ereignisses (<b>Click<\/b>) und den Steuerelementnamen und erzeugen so die Prozedur <b>[Steuerelementname]_Click<\/b>.<\/p>\n<p>Dann ermitteln wir mit <b>ProcBodyLine<\/b> die erste Zeile dieser Prozedur und speichern diese in <b>lngLine<\/b>. In der folgenden Zeile f&uuml;gen wir eine Platzhalter-Anweisung hinzu, die beim Anklicken der Schaltfl&auml;che eine entsprechende Meldung anzeigt.<\/p>\n<p>Schlie&szlig;lich markieren wir die vollst&auml;ndige Prozedur, damit der Benutzer diese beim Aktivieren des VBA-Editors direkt erkennen kann.<\/p>\n<h2>Access-Fenster wieder aktivieren<\/h2>\n<p>Bei diesen Aktionen wird der VBA-Editor aktiviert. Damit wieder das Access-Fenster den Fokus erh&auml;lt, rufen wir die Prozedur <b>AccessAktivieren <\/b>auf.<\/p>\n<p>Diese nutzt die Windows-API, um das Handle des Access-Fensters zu ermitteln und dieses in den Vordergrund zu verschieben:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AccessAktivieren()\r\n    <span style=\"color:blue;\">Dim <\/span>hwndAccess<span style=\"color:blue;\"> As Long<\/span>Ptr\r\n    hwndAccess = Application.hWndAccessApp\r\n    SetForegroundWindow hwndAccess\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>frmButtonWizard zur&uuml;cksetzen<\/h2>\n<p>Au&szlig;erdem rufen wir noch die Prozedur <b>FormularZuruecksetzen <\/b>auf, die das Formular <b>frmButtonWizard <\/b>auf den Anfangszustand zur&uuml;cksetzt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FormularZuruecksetzen()\r\n    Me.cmdVorschau.PictureData = Null\r\n    Me.cmdVorschau.Caption = \"\"\r\n    Me.cmdVorschau.Width = 480\r\n    Me.txtBeschriftung = \"\"\r\n    Me.txtSteuerelementname = \"\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Beim &Ouml;ffnen des Formulars<\/h2>\n<p>Im Ereignis <b>Beim &Ouml;ffnen <\/b>des Formulars werden einige Aktionen ausgef&uuml;hrt, deren Erl&auml;uterung zu Beginn noch keinen Sinn ergeben h&auml;tte (siehe Listing 7).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Open(Cancel<span style=\"color:blue;\"> As Integer<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>lngError<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>varPictureData<span style=\"color:blue;\"> As Variant<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>dbc<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    \r\n    <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n    dbc.Execute \"DELETE FROM tblHistory\", dbFailOnError\r\n    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n    \r\n    TempVars(\"Form\") = Screen.ActiveForm.Name\r\n    lngError = Err.Number\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n    \r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngError = 0<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">MsgBox<\/span> \"Es ist kein Formular ge&ouml;ffnet, dem ein Button hinzugef&uuml;gt werden kann.\", vbOKOnly + vbExclamation, _\r\n            \"amvButtonWizard - Kein Formular ge&ouml;ffnet.\"\r\n        Cancel = <span style=\"color:blue;\">True<\/span>\r\n        <span style=\"color:blue;\">Exit Sub<\/span>\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> Screen.ActiveForm.CurrentView = 0<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">MsgBox<\/span> \"Das Formular, dem ein Button hinzugef&uuml;gt werden soll, muss in der Entwurfsansicht ge&ouml;ffnet sein.\", _\r\n                vbOKOnly + vbExclamation, \"amvButtonWizard - Formular nicht im Entwurf ge&ouml;ffnet\"\r\n            Cancel = <span style=\"color:blue;\">True<\/span>\r\n            <span style=\"color:blue;\">Exit Sub<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    \r\n    TempVars(\"Picture\") = \"\"\r\n    TempVars(\"Beschriftung\") = \"\"\r\n    TempVars(\"Steuerelementname\") = \"\"\r\n    <span style=\"color:blue;\">Call<\/span> LoadImages\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Ereignisprozedur, die beim &Ouml;ffnen des Formulars ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Hier referenzieren wir die <b>CodeDb <\/b>und leeren f&uuml;r diese die Tabelle <b>tblHistory<\/b>. Dann lesen wir bei deaktivierter Fehlerbehandlung den Namen des aktuellen Formulars ein (<b>Screen.ActiveForm.Name<\/b>).<\/p>\n<p>Dies l&ouml;st einen Fehler aus, wenn kein Formular den Fokus hat. In diesem Fall gibt die Prozedur eine entsprechende Meldung aus. Durch das Setzen des Parameters <b>Cancel <\/b>auf den Wert <b>True <\/b>wird das &Ouml;ffnen des Formulars abgebrochen, au&szlig;erdem wird die Prozedur beendet.<\/p>\n<p>Konnte ein Formular gefunden werden, pr&uuml;fen wir mit <b>CurrentView <\/b>die aktuelle Ansicht. Entspricht diese nicht dem Wert <b>0<\/b>, ist das Formular nicht in der Entwurfsansicht ge&ouml;ffnet und wir erhalten ebenfalls eine passende Meldung.<\/p>\n<p>War dies erfolgreich, leeren wir die <b>TempVar<\/b>-Variablen <b>Picture<\/b>, <b>Beschriftung <\/b>und <b>Steuerelementname<\/b>. Au&szlig;erdem laden wir mit <b>LoadImages<\/b> alle Bilder aus der Tabelle <b>tblResources <\/b>in die <b>Bild<\/b>-Steuerelemente des Formulars.<\/p>\n<h2>L&ouml;sung in Wizard umwandeln<\/h2>\n<p>Nun fehlt noch der entscheidende Schritt: Wir wollen die L&ouml;sung in einen Wizard umwandeln.<\/p>\n<p>Das Ergebnis soll sein, dass wir f&uuml;r das Hinzuf&uuml;gen von Steuerelementen die Option <b>Steuerelement-Assistenten verwenden <\/b>aktivieren und dann beim Hinzuf&uuml;gen einer Schaltfl&auml;che unsere L&ouml;sung ausw&auml;hlen k&ouml;nnen.<\/p>\n<p>Dazu sind einige Schritte n&ouml;tig:<\/p>\n<ul>\n<li>Wir m&uuml;ssen der Datenbank eine Tabelle namens <b>USysRegInfo <\/b>hinzuf&uuml;gen, welche die Informationen enth&auml;lt, die beim Installieren des Wizards in die Registry geschrieben werden. Diese werden dann beim &Ouml;ffnen von Access gelesen, damit unser Wizard beim Bet&auml;tigen der Schaltfl&auml;che zum Hinzuf&uuml;gen einer neuen Schaltfl&auml;che zur Auswahl angeboten wird.<\/li>\n<li>Au&szlig;erdem m&uuml;ssen wir den Code unserer L&ouml;sung an verschiedenen Stellen anpassen.<\/li>\n<\/ul>\n<p>Wie das gelingt, zeigen wir in zwei weiteren Beitr&auml;gen:<\/p>\n<ul>\n<li>In <b>Steuerelement-Wizards programmieren <\/b>(<b>www.access-im-unternehmen.de\/1593<\/b>) zeigen wir, wie Steuerelement-Wizards grunds&auml;tzlich programmiert werden.<\/li>\n<li>Und in <b>Button-Wizard programmieren <\/b>(<b>www.access-im-unternehmen.de\/1594<\/b>) liefern wir schlie&szlig;lich die Anleitung, mit der wir unsere L&ouml;sung in einen jederzeit verf&uuml;gbaren Wizard umwandeln.<\/li>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>amvButtonWizard.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/35B9C913-3A07-4AD2-8D50-32DC34C6EEF3\/aiu_1563.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Je schneller ich Ergebnisse beim Programmieren erhalten m&ouml;chte, desto ungeduldiger werde ich, wenn mich kleinteilige, sich st&auml;ndig wiederholende Aufgaben aufhalten. In diesem Fall ist vom Anlegen von Schaltfl&auml;chen die Rede. Ich h&auml;tte gern so schnell wie m&ouml;glich Schaltfl&auml;chen, welche die von mir gew&uuml;nschte Beschriftung, einen passenden Namen und je nach Situation ein Icon enthalten. Diese Icons sollen nach meinen W&uuml;nschen gestaltet sein &#8211; also beispielsweise mit transparentem Hintergrund und ohne Rahmen, sodass nur das Icon und die Beschriftung erscheinen und die Schriftfarbe und Schriftbreite diese als Schaltfl&auml;che von den Beschriftungen abhebt. Schlie&szlig;lich sollte auch noch direkt der VBA-Editor mit der passenden Ereignisprozedur ge&ouml;ffnet werden. Das alles umfasst einige Schritte, und auch wenn man eine Schaltfl&auml;che einmal formatiert hat und diese dann kopiert und als Vorlage f&uuml;r eine neue Schaltfl&auml;che verwendet, muss man noch einige Aspekte selbst hinzuf&uuml;gen. In diesem Beitrag stelle ich daher einen Assistenten vor, mit dem wir Schaltfl&auml;chen wesentlich schneller und komfortabler anlegen k&ouml;nnen.<\/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":[66022026,662025,662026,66062025,44000027],"tags":[],"class_list":["post-55001563","post","type-post","status-publish","format-standard","hentry","category-66022026","category-662025","category-662026","category-66062025","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.5) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Schnelle Schaltfl&auml;chen mit Stil - 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\/Schnelle_Schaltflaechen_mit_Stil\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Schnelle Schaltfl&auml;chen mit Stil\" \/>\n<meta property=\"og:description\" content=\"Je schneller ich Ergebnisse beim Programmieren erhalten m&ouml;chte, desto ungeduldiger werde ich, wenn mich kleinteilige, sich st&auml;ndig wiederholende Aufgaben aufhalten. In diesem Fall ist vom Anlegen von Schaltfl&auml;chen die Rede. Ich h&auml;tte gern so schnell wie m&ouml;glich Schaltfl&auml;chen, welche die von mir gew&uuml;nschte Beschriftung, einen passenden Namen und je nach Situation ein Icon enthalten. Diese Icons sollen nach meinen W&uuml;nschen gestaltet sein - also beispielsweise mit transparentem Hintergrund und ohne Rahmen, sodass nur das Icon und die Beschriftung erscheinen und die Schriftfarbe und Schriftbreite diese als Schaltfl&auml;che von den Beschriftungen abhebt. Schlie&szlig;lich sollte auch noch direkt der VBA-Editor mit der passenden Ereignisprozedur ge&ouml;ffnet werden. Das alles umfasst einige Schritte, und auch wenn man eine Schaltfl&auml;che einmal formatiert hat und diese dann kopiert und als Vorlage f&uuml;r eine neue Schaltfl&auml;che verwendet, muss man noch einige Aspekte selbst hinzuf&uuml;gen. In diesem Beitrag stelle ich daher einen Assistenten vor, mit dem wir Schaltfl&auml;chen wesentlich schneller und komfortabler anlegen k&ouml;nnen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-05T20:48:21+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg01.met.vgwort.de\/na\/94aba167088843dab03f5b20c23d1aa0\" \/>\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=\"25\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Schnelle Schaltfl&auml;chen mit Stil\",\"datePublished\":\"2026-03-05T20:48:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/\"},\"wordCount\":4001,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/94aba167088843dab03f5b20c23d1aa0\",\"articleSection\":[\"2\\\/2026\",\"2025\",\"2026\",\"6\\\/2025\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/\",\"name\":\"Schnelle Schaltfl&auml;chen mit Stil - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/94aba167088843dab03f5b20c23d1aa0\",\"datePublished\":\"2026-03-05T20:48:21+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/94aba167088843dab03f5b20c23d1aa0\",\"contentUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/94aba167088843dab03f5b20c23d1aa0\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schnelle_Schaltflaechen_mit_Stil\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Schnelle Schaltfl&auml;chen mit Stil\"}]},{\"@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":"Schnelle Schaltfl&auml;chen mit Stil - 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\/Schnelle_Schaltflaechen_mit_Stil\/","og_locale":"de_DE","og_type":"article","og_title":"Schnelle Schaltfl&auml;chen mit Stil","og_description":"Je schneller ich Ergebnisse beim Programmieren erhalten m&ouml;chte, desto ungeduldiger werde ich, wenn mich kleinteilige, sich st&auml;ndig wiederholende Aufgaben aufhalten. In diesem Fall ist vom Anlegen von Schaltfl&auml;chen die Rede. Ich h&auml;tte gern so schnell wie m&ouml;glich Schaltfl&auml;chen, welche die von mir gew&uuml;nschte Beschriftung, einen passenden Namen und je nach Situation ein Icon enthalten. Diese Icons sollen nach meinen W&uuml;nschen gestaltet sein - also beispielsweise mit transparentem Hintergrund und ohne Rahmen, sodass nur das Icon und die Beschriftung erscheinen und die Schriftfarbe und Schriftbreite diese als Schaltfl&auml;che von den Beschriftungen abhebt. Schlie&szlig;lich sollte auch noch direkt der VBA-Editor mit der passenden Ereignisprozedur ge&ouml;ffnet werden. Das alles umfasst einige Schritte, und auch wenn man eine Schaltfl&auml;che einmal formatiert hat und diese dann kopiert und als Vorlage f&uuml;r eine neue Schaltfl&auml;che verwendet, muss man noch einige Aspekte selbst hinzuf&uuml;gen. In diesem Beitrag stelle ich daher einen Assistenten vor, mit dem wir Schaltfl&auml;chen wesentlich schneller und komfortabler anlegen k&ouml;nnen.","og_url":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/","og_site_name":"Access im Unternehmen","article_published_time":"2026-03-05T20:48:21+00:00","og_image":[{"url":"http:\/\/vg01.met.vgwort.de\/na\/94aba167088843dab03f5b20c23d1aa0","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"25\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Schnelle Schaltfl&auml;chen mit Stil","datePublished":"2026-03-05T20:48:21+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/"},"wordCount":4001,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#primaryimage"},"thumbnailUrl":"http:\/\/vg01.met.vgwort.de\/na\/94aba167088843dab03f5b20c23d1aa0","articleSection":["2\/2026","2025","2026","6\/2025","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/","url":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/","name":"Schnelle Schaltfl&auml;chen mit Stil - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#primaryimage"},"thumbnailUrl":"http:\/\/vg01.met.vgwort.de\/na\/94aba167088843dab03f5b20c23d1aa0","datePublished":"2026-03-05T20:48:21+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#primaryimage","url":"http:\/\/vg01.met.vgwort.de\/na\/94aba167088843dab03f5b20c23d1aa0","contentUrl":"http:\/\/vg01.met.vgwort.de\/na\/94aba167088843dab03f5b20c23d1aa0"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Schnelle_Schaltflaechen_mit_Stil\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Schnelle Schaltfl&auml;chen mit Stil"}]},{"@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\/55001563","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=55001563"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001563\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001563"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001563"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001563"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}