{"id":55000921,"date":"2014-02-01T00:00:00","date_gmt":"2020-05-22T21:18:58","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=921"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Objekt_und_Feldnamen_per_Kontextmenue","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/","title":{"rendered":"Objekt- und Feldnamen per Kontextmen&uuml;"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/7d360348c1fc442e81e1e194740b8cc0\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Kennen Sie das auch Sie konzentrieren sich gerade mal wieder voll auf die Programmierung einer Prozedur und wollen eine SQL-Anweisung zusammenstellen. Dummerweise f&auml;llt Ihnen der Name der Tabelle und\/oder des Feldes nicht ein, das Sie dort verwenden m&ouml;chten. Also wechseln Sie zum Access-Fenster, ermitteln dort den gesuchten Namen und kehren wieder zum VBA-Editor zur&uuml;ck. Dort erg&auml;nzen Sie dann die gesuchte Anweisung. Damit ist jetzt Schluss: Dieser Beitrag stellt n&auml;mlich eine einfache L&ouml;sung vor, mit der Sie die Namen aller Tabellen, Abfragen und Felder ganz einfach per Kontextmen&uuml; nachschlagen und zum Code hinzuf&uuml;gen k&ouml;nnen.<\/b><\/p>\n<p>Mir selbst passiert es immer wieder, dass ich nicht mehr genau wei&szlig;, wie ein bestimmtes Feld einer Tabelle oder Abfrage hei&szlig;t, das ich f&uuml;r eine Anweisung im VBA-Code ben&ouml;tige. Hie&szlig; das Feld nun Anzahl oder Menge Werden die E-Mail-Adressen unter <b>EMail <\/b>oder <b>EMailAdresse <\/b>gespeichert Und was ist mit <b>Strasse<\/b>, <b>Strasse_Firma<\/b>, <b>StrasseFirma<\/b> oder <b>FirmaStrasse<\/b> Ganz abgesehen von den Feldnamen kann man sich mit wachsender Komplexit&auml;t einer Anwendung auch nicht mehr alle Tabellennamen merken &#8211; oder auch die Namen von Abfragen.<\/p>\n<p>Und wenn wir schon einmal dabei sind: Was geschieht mit den &uuml;brigen Objekten wie Formularen und Berichten und den darin enthaltenen Steuerelementen Sie sehen schon: Die Idee, die Namen von Objekten, Feldern und Steuerelementen per Kontextmen&uuml; im VBA-Codefenster zur Verf&uuml;gung zu stellen, liefert schnell eine gro&szlig;e Anzahl Anwendungsm&ouml;glichkeiten.<\/p>\n<p>Wie soll das Ganze aber nun funktionieren &#8211; was haben Sie von der in diesem Beitrag vorgestellten L&ouml;sung zu erwarten Die Ausgangssituation ist, dass Sie den VBA-Editor ge&ouml;ffnet haben und programmieren.<\/p>\n<p>Bei einer Access-Anwendung kommt es nur selten vor, dass Sie gr&ouml;&szlig;ere Mengen Code produzieren, ohne die Objekte der Datenbank wie Tabellen, Abfragen, Formulare oder Berichte zu referenzieren. Sie d&uuml;rfen dann beispielsweise Ausdr&uuml;cke wie <b>Forms!frmKunden!sfmEMailadressen.Form!txtEMail <\/b>aus dem Handgelenk sch&uuml;tteln. Wenn Sie denn die Namen aller Objekte direkt im Kopf haben. Falls nicht, m&uuml;ssen Sie immer wieder zum Access-Fenster wechseln und dort nachsehen, wie Formular, Unterformular oder Steuerelemente hei&szlig;en.<\/p>\n<p>Die hier beschriebene L&ouml;sung soll diese Informationen direkt im VBA-Editor verf&uuml;gbar machen &#8211; leicht zu erreichen per Kontextmen&uuml;. Sprich: Sie markieren die Stelle im Code, an der eine Referenz auf das gew&uuml;nschte Objekt\/Steuerelement eingef&uuml;gt werden soll, und bet&auml;tigen dann die rechte Maustaste. Das Kontextmen&uuml;, das nun &uuml;blicherweise erscheint, reichern wir mit einem Untereintrag etwa namens Objekte an. Dieses enth&auml;lt weitere Untereintr&auml;ge wie Tabellen, Abfragen, Formulare und Berichte.<\/p>\n<p>Der Eintrag <b>Tabellen<\/b> liefert wiederum die Namen aller verf&uuml;gbaren Tabellen, die Ebene darunter die Liste der Felder einer jeden Tabelle. Bei den &uuml;brigen Objekttypen sieht es &auml;hnlich aus. Bild 1 zeigt beispielsweise, wie Sie den Namen einer Tabelle f&uuml;r den Einsatz in einer OpenRecordset-Methode nachschlagen k&ouml;nnen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_921_002.png\" alt=\"Tabellenname vergessen und keine Lust, zum Access-Fenster zu wechseln Kein Problem!\" width=\"700\" height=\"522,8185\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Tabellenname vergessen und keine Lust, zum Access-Fenster zu wechseln Kein Problem!<\/span><\/b><\/p>\n<p>Nach dem Ausw&auml;hlen eines der Elemente wird der entsprechende Ausdruck an der angeklickten Stelle eingef&uuml;gt.<\/p>\n<p><b>Passendes Kontextmen&uuml; finden<\/b><\/p>\n<p>Wenn wir einem bestimmten Kontextmen&uuml; einen oder mehrere Eintr&auml;ge hinzuf&uuml;gen m&ouml;chten, m&uuml;ssen wir zun&auml;chst herausfinden, wie das Kontextmen&uuml; hei&szlig;t.<\/p>\n<p>Dazu wende ich immer einen einfachen Trick an: Ich f&uuml;ge allen verf&uuml;gbaren Kontextmen&uuml;s einen weiteren Eintrag hinzu, der schlicht und einfach den Namen des Kontextmen&uuml;s enth&auml;lt. Dann brauche ich das Kontextmen&uuml; nur noch anzuzeigen und erhalte seinen Namen (s. Listing 1). Die Prozedur deklariert ein <b>CommandBar<\/b>&#8211; und ein <b>CommandBarButton<\/b>-Objekt. Es durchl&auml;uft dann in einer <b>For Each<\/b>-Schleife die Auflistung <b>CommandBars <\/b>des <b>VBE<\/b>-Objekts. Die Angabe von <b>VBE <\/b>ist wichtig &#8211; wenn Sie nur <b>CommandBars <\/b>angeben, liefert dies die Auflistung der Men&uuml;s der Access-Anwendung, nicht des VBA-Editors.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>KontextmenueFinden()\r\n     <span style=\"color:blue;\">Dim <\/span>cbr<span style=\"color:blue;\"> As <\/span>CommandBar\r\n     <span style=\"color:blue;\">Dim <\/span>cbb<span style=\"color:blue;\"> As <\/span>CommandBarButton\r\n     For Each cbr In VBE.CommandBars\r\n         <span style=\"color:blue;\">If <\/span>cbr.Type = msoBarTypePopup<span style=\"color:blue;\"> Then<\/span>\r\n             On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> cbb = cbr.Controls.Add(msoControlButton, , , , <span style=\"color:blue;\">True<\/span>)\r\n             <span style=\"color:blue;\">With<\/span> cbb\r\n                 cbb.Caption = \"Men&uuml;name: \" & cbr.Name\r\n             End <span style=\"color:blue;\">With<\/span>\r\n             <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> cbr\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Hinzuf&uuml;gen eines Eintrags mit dem Men&uuml;namen zu den einzelnen Kontextmen&uuml;s<\/span><\/b><\/p>\n<p>Wenn das aktuell durchlaufene Objekt den Typ <b>msoBarTypePopup <\/b>aufweist, handelt es sich um ein Kontextmen&uuml; &#8211; diesem wollen wir nun ein neues Element hinzuf&uuml;gen. Dies erledigen wir mit der <b>Add<\/b>-Methode der <b>Controls<\/b>-Auflistung des <b>CommandBar<\/b>-Objekts. Dabei verwenden Sie als ersten Parameter die Konstante <b>msoControlButton <\/b>(f&uuml;r die Erstellung einer Schaltfl&auml;che) und f&uuml;r den letzten Parameter <b>Temporary <\/b>den Wert <b>True <\/b>&#8211; auf diese Weise verschwinden die Eintr&auml;ge beim Schlie&szlig;en von Access automatisch wieder.<\/p>\n<p>F&uuml;r das neue <b>CommandBarButton<\/b>-Objekt stellen wir als Beschriftung (<b>Caption<\/b>) den Ausdruck <b>Men&uuml;name <\/b>und den Inhalt der <b>Name<\/b>-Eigenschaft des Men&uuml;s hinzu, also etwa <b>Men&uuml;name Code Window<\/b>. Wenn Sie diese Prozedur einmalig ausgef&uuml;hrt haben, brauchen Sie nur noch mit der rechten Maustaste an die gew&uuml;nschte Stelle im Codefenster zu klicken &#8211; schon finden Sie im untersten Eintrag den Namen des aktuell angezeigten Kontextmen&uuml;s (s. Bild 2). Ein Rechtsklick auf das VBA-Codefenster zeigt also beispielsweise das Kontextmen&uuml; <b>Code Window <\/b>an.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_921_001.png\" alt=\"Anzeige des Kontextmen&uuml;namens per Kontextmen&uuml;\" width=\"575\" height=\"367,2208\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Anzeige des Kontextmen&uuml;namens per Kontextmen&uuml;<\/span><\/b><\/p>\n<p><b>Welche Objekte &#8211; und wie<\/b><\/p>\n<p>Bevor wir in den Code einsteigen, &uuml;berlegen wir uns noch, welche Elemente verwendet werden sollen und wann und wie wir diese einlesen.<\/p>\n<p>Wenn Sie nur die Tabellen verwenden m&ouml;chten, k&ouml;nnen Sie das Kontextmen&uuml; je nach der Anzahl der Tabellen vermutlich direkt vor dem Anzeigen erstellen. Wenn Sie jedoch alle Tabellen, Abfrage, Formulare und Berichte samt Steuerelementen nutzen m&ouml;chten, k&ouml;nnen Sie das Kontextmen&uuml; nicht bei jeder Anzeige dynamisch erstellen &#8211; dies w&uuml;rde viel zu viel Zeit in Anspruch nehmen. Sie m&uuml;ssen, wenn Sie auch die Steuerelemente der Formulare ausw&auml;hlen m&ouml;chten, immerhin alle Formulare im Entwurf &ouml;ffnen und die Steuerelemente (sowie eventuell verschachtelte Elemente wie Unterformular) einlesen.<\/p>\n<p>Wir wollen die umfangreiche Variante w&auml;hlen und gehen folgenderma&szlig;en vor:<\/p>\n<p>Beim Start der Anwendung muss eine Prozedur einmalig aufgerufen werden. Diese liest alle Objekte und deren Felder beziehungsweise Steuerelemente ein. Damit dies nicht jedes Mal n&ouml;tig ist, speichern wir allerdings auch gleichzeitig den Zeitpunkt der letzten &auml;nderung eines jeden Objekts. Auf diese Weise k&ouml;nnen wir pr&uuml;fen, ob sich das Objekt seit dem letzten Zusammenstellen der Daten f&uuml;r das Kontextmen&uuml; ge&auml;ndert hat, und brauchen die Inhalte dann nur bei Bedarf neu einzulesen.<\/p>\n<p>Die ermittelten Informationen speichern wir in einer Tabelle namens <b>tblObjekte<\/b>. Im gleichen Zuge, also beim Start der Anwendung, bauen wir auch das Kontextmen&uuml; neu auf. Dies ist auch n&ouml;tig, wenn Sie w&auml;hrend einer Sitzung umfangreiche &auml;nderungen vornehmen und direkt auf die neuen Elemente zugreifen m&ouml;chten &#8211; die ge&auml;nderten Objekte werden dann erneut eingelesen und das Kontextmen&uuml; auf Basis des aktuell in der Tabelle <b>tblObjekte <\/b>gespeicherten Stands erstellt. Die Tabelle <b>tblObjekte <\/b>sieht im Entwurf wie in Bild 3 aus. Sie enth&auml;lt die folgenden Felder:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_921_003.png\" alt=\"Tabelle zum Zwischenspeichern der Objekte\" width=\"650\" height=\"312,8166\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Tabelle zum Zwischenspeichern der Objekte<\/span><\/b><\/p>\n<ul>\n<li><b>ObjektID<\/b>: Prim&auml;rschl&uuml;sselfeld der Tabelle<\/li>\n<li><b>Objekt<\/b>: Name des Objekts (Tabelle, Abfrage, Formular, Bericht, Feld, Steuerelement)<\/li>\n<li><b>Objekttyp<\/b>: Zahlenwert, der den Objekttyp angibt<\/li>\n<li><b>UnterobjektVonObjektID<\/b>: Gibt an, ob es sich um ein untergeordnetes Objekt handelt (etwa f&uuml;r Felder oder Steuerelemente)<\/li>\n<li><b>LetzteAenderung<\/b>: Enth&auml;lt Datum und Zeit der letzten &auml;nderung<\/li>\n<li><b>Loeschen<\/b>: Ja\/Nein-Feld, mit dem festgelegt wird, welche Elemente nach dem erneuten Einlesen gel&ouml;scht werden sollen<\/li>\n<li><b>EnthaeltUnterformular<\/b>: Gibt an, welches Unterformular ein Unterformular-Steuerelement enth&auml;lt.<\/li>\n<li><b>Referenz<\/b>: Enth&auml;lt den Ausdruck, der beim Einf&uuml;gen im VBA-Code verwendet werden soll &#8211; zum Beispiel <b>Forms!frmFormular!txtTextfeld<\/b>.<\/li>\n<\/ul>\n<p><b>Einlesen der Elemente<\/b><\/p>\n<p>Die Prozedur <b>ObjekteEinlesen <\/b>aus Listing 2 startet den Einlesevorgang der Elemente der aktuell ge&ouml;ffneten Datenbankdatei. Die Prozedur f&uuml;llt zun&auml;chst eine Variable vom Typ <b>Database <\/b>mit einem Verweis auf die aktuelle Datenbank. Dann verwendet sie deren <b>Execute<\/b>-Methode, um das Feld <b>Loeschen <\/b>f&uuml;r alle Datens&auml;tze der Tabelle <b>tblObjekte <\/b>auf den Wert <b>True <\/b>einzustellen. Nachfolgend stellt die Prozedur f&uuml;r alle noch vorhandenen Elemente den Wert dieses Feldes auf <b>False <\/b>ein. So kann sie mit der letzten Anweisung alle Elemente l&ouml;schen, die gegebenenfalls seit dem vorherigen Einlesevorgang gel&ouml;scht wurden.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ObjekteEinlesen()\r\n    <span style=\"color:blue;\">Dim <\/span>datLetzteAenderung<span style=\"color:blue;\"> As Date<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>datLetzteGespeicherteAenderung<span style=\"color:blue;\"> As Date<\/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>tdf<span style=\"color:blue;\"> As <\/span>dao.TableDef\r\n    <span style=\"color:blue;\">Dim <\/span>qdf<span style=\"color:blue;\"> As <\/span>dao.QueryDef\r\n    <span style=\"color:blue;\">Dim <\/span>obj<span style=\"color:blue;\"> As <\/span>AccessObject\r\n    <span style=\"color:blue;\">Dim <\/span>frm<span style=\"color:blue;\"> As <\/span>Form\r\n    <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    db.Execute \"UPDATE tblObjekte SET Loeschen = -1\", dbFailOnError\r\n    For Each tdf In db.TableDefs\r\n        TabellenAbfragenFelder db, tdf, 0\r\n    <span style=\"color:blue;\">Next<\/span> tdf\r\n    For Each qdf In db.QueryDefs\r\n        TabellenAbfragenFelder db, qdf, 1\r\n    <span style=\"color:blue;\">Next<\/span> qdf\r\n    For Each obj In CurrentProject.AllForms\r\n        datLetzteAenderung = obj.DateModified\r\n        datLetzteGespeicherteAenderung = Nz(DLookup(\"LetzteAenderung\", _\r\n            \"tblObjekte\", \"Objekt = ''\" & obj.Name & \"''\"))\r\n        <span style=\"color:blue;\">If <\/span>CSng(datLetzteGespeicherteAenderung) &lt; CSng(datLetzteAenderung) _\r\n                Or datLetzteGespeicherteAenderung = 0<span style=\"color:blue;\"> Then<\/span>\r\n            DoCmd.OpenForm obj.Name, acDesign\r\n            <span style=\"color:blue;\">Set<\/span> frm = Forms(obj.Name)\r\n            FormulareBerichteSteuerelemente db, frm, -1, _\r\n                datLetzteAenderung, datLetzteGespeicherteAenderung\r\n            DoCmd.Close acForm, obj.Name\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            lngID = DLookup(\"ObjektID\", \"tblObjekte\", \"Objekt = ''\" & obj.Name & \"'' AND Objekttyp = -1\")\r\n            db.Execute \"UPDATE tblObjekte SET Loeschen = 0 &quot; _\r\n                &amp; &quot;WHERE ObjektID = \" & lngID, dbFailOnError\r\n            db.Execute \"UPDATE tblObjekte SET Loeschen = 0 &quot; _\r\n                &amp; &quot;WHERE UnterobjektVonObjektID = \" & lngID, dbFailOnError\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Next<\/span> obj\r\n    For Each obj In CurrentProject.AllReports\r\n        db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp) VALUES(''\" _\r\n            & obj.Name & \"'', \" & acForm & \")\", dbFailOnError\r\n    <span style=\"color:blue;\">Next<\/span> obj\r\n    db.Execute \"DELETE FROM tblObjekte WHERE Loeschen = -1\", dbFailOnError\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Einlesen der Tabellen, Abfrage und Formulare sowie Felder und Steuerelemente<\/span><\/b><\/p>\n<p>Doch eins nach dem anderen: Zun&auml;chst einmal durchl&auml;uft die Prozedur alle Elemente der <b>TableDefs<\/b>-Auflistung der Datenbank und referenziert diese jeweils mit der Objektvariablen <b>tdf<\/b>. Damit ruft sie die Prozedur <b>TabellenAbfragenFelder <\/b>auf, die sich um das Schreiben der Informationen zur jeweiligen Tabelle in die Tabelle <b>tblObjekte <\/b>k&uuml;mmert. Dazu &uuml;bergibt die Prozedur den Verweis auf die Datenbank (<b>db<\/b>) und auf das <b>TableDef<\/b>-Element (<b>tdf<\/b>) sowie den Wert <b>0 <\/b>als Typ des Elements (<b>0 <\/b>entspricht einer Tabelle, <b>1 <\/b>einer Abfrage). Diese Prozedur tr&auml;gt je einen Datensatz f&uuml;r die Tabelle und je einen weiteren f&uuml;r jedes Tabellenfeld in die Tabelle <b>tblObjekte <\/b>ein. Wir schauen uns diese Prozedur weiter unten an.<\/p>\n<p>Anschlie&szlig;end durchl&auml;uft die Prozedur <b>ObjekteEinlesen <\/b>in einer &auml;hnlichen <b>For Each<\/b>-Schleife die <b>QueryDef<\/b>-Objekte der Datenbank, also die Abfragen. Auch hier ruft die Prozedur f&uuml;r jedes Element die Prozedur <b>TabellenAbfragenFelder <\/b>auf, die wir weiter unten beschreiben. Diesmal &uuml;bergibt die Anweisung jedoch den Verweis auf das <b>QueryDef<\/b>-Objekt als zweiten Parametern (<b>qdf<\/b>).<\/p>\n<p>Schlie&szlig;lich durchl&auml;uft die Prozedur alle Elemente der Auflistung <b>AllForms <\/b>des Objekts <b>CurrentProject<\/b> und referenziert das jeweilige Objekt mit der Variablen <b>obj<\/b>.<\/p>\n<p>Innerhalb der Schleife ermittelt die Prozedur nun zun&auml;chst das Datum der letzten &auml;nderung des aktuellen Formulars und speichert dieses in der Variablen <b>datLetzteAenderung<\/b>. Au&szlig;erdem durchsucht sie die Tabelle <b>tblObjekte <\/b>nach einem eventuell bereits gespeicherten Datensatz f&uuml;r das aktuelle Formular-Objekt. Ist eines vorhanden, liest sie den Wert des Feldes <b>LetzteAenderung <\/b>f&uuml;r dieses Formular in die Variable <b>datLetzteGespeicherteAenderung <\/b>ein.<\/p>\n<p>Dann vergleicht die Prozedur die Werte von <b>datLetzteGespeicherteAenderung <\/b>und <b>datLetzteAenderung<\/b>. Wurde das Formular nach dem letzten Speichern in der Tabelle <b>tblObjekte <\/b>ge&auml;ndert, ist <b>datLetzteGespeicherteAenderung <\/b>kleiner als <b>datLetzteAenderung <\/b>und die in der entsprechenden <b>If&#8230;Then<\/b>-Bedingung enthaltenen Anweisungen werden ausgef&uuml;hrt &#8211; sprich: Das Formular wird erneut eingelesen. Dazu &ouml;ffnet die Prozedur das Formular in der Entwurfsansicht und referenziert es mit der Variablen <b>frm<\/b>. Diese wird dann, nebst einigen weiteren Informationen, an die Prozedur <b>FormulareBerichteSteuerelemente <\/b>&uuml;bergeben &#8211; mehr dazu weiter unten in der Beschreibung dieser Prozedur. Nach dem Einlesen schlie&szlig;t die Prozedur <b>ObjekteEinlesen <\/b>das im Entwurf ge&ouml;ffnete Formular wieder.<\/p>\n<p>Sollte <b>datLetzteGespeicherteAenderung <\/b>nicht kleiner als <b>datLetzte-Aenderung <\/b>sein, sind eigentlich keine weiteren Schritte n&ouml;tig. Allerdings haben wir ja zu Beginn der Prozedur das Feld <b>Loeschen <\/b>f&uuml;r alle Elemente auf <b>True <\/b>eingestellt. Wenn sich an einem Objekt jedoch nichts ge&auml;ndert hat, soll es auch nicht gel&ouml;scht werden &#8211; also stellen wir im <b>Else<\/b>-Teil der <b>If&#8230;Then<\/b>-Bedingung den Wert von <b>Loeschen <\/b>auf <b>False <\/b>ein. Dazu ermittelt die Prozedur zun&auml;chst den Prim&auml;rschl&uuml;sselwert aus dem Feld <b>ObjektID <\/b>f&uuml;r das Objekt mit dem angegebenen Namen und dem Wert <b>-1 <\/b>im Feld <b>Objekttyp<\/b>. Dann stellt sie das Feld <b>Loeschen <\/b>zun&auml;chst f&uuml;r den so ermittelten Datensatz auf <b>False <\/b>ein und dann f&uuml;r alle Datens&auml;tze, die diesem untergeordnet sind und dementsprechend den ermittelten Zahlenwert im Feld <b>UnterobjektVonObjektID <\/b>aufweisen &#8211; in diesem Fall also f&uuml;r die Steuerelemente des Formulars.<\/p>\n<p>Schlie&szlig;lich l&ouml;scht die Prozedur alle Datens&auml;tze der Tabelle <b>tblObjekte<\/b>, deren Feld <b>Loeschen <\/b>auch nach dem Durchlaufen und gegebenenfalls Aktualisieren aller Objekte und Unterobjekte noch den Wert <b>True <\/b>hat.<\/p>\n<p><b>Eintragen von Tabellen, Abfragen und Feldern in tblObjekte<\/b><\/p>\n<p>Nachdem der grundlegende Ablauf von der Prozedur <b>ObjekteEinlesen <\/b>gesteuert wird, ruft diese zwei weitere Prozeduren auf, um die Daten der Objekte wie Tabellen, Abfragen oder Formulare in der Tabelle <b>tblObjekte <\/b>zu speichern.<\/p>\n<p>Wir schauen uns als Erstes die Prozedur <b>TabellenAbfragenFelder <\/b>an, die in Listing 3 abgebildet ist. Die Prozedur erwartet die folgenden Parameter:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabellenAbfragenFelder(db<span style=\"color:blue;\"> As <\/span>dao.Database, objTdfQdf<span style=\"color:blue;\"> As Object<\/span>, lngObjekttypID<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>lngObjektID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>dao.Field\r\n    <span style=\"color:blue;\">Dim <\/span>datLetzteAenderung<span style=\"color:blue;\"> As Date<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>datLetzteGespeicherteAenderung<span style=\"color:blue;\"> As Date<\/span>\r\n    datLetzteAenderung = objTdfQdf.LastUpdated\r\n    datLetzteGespeicherteAenderung = Nz(DLookup(\"LetzteAenderung\", \"tblObjekte\", _\r\n        \"Objekt = ''\" & objTdfQdf.Name & \"''\"))\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> datLetzteGespeicherteAenderung = 0<span style=\"color:blue;\"> Then<\/span>\r\n        lngObjektID = DLookup(\"ObjektID\", \"tblObjekte\", \"Objekt = ''\" & objTdfQdf.Name & \"''\")\r\n        <span style=\"color:blue;\">If <\/span>CSng(datLetzteGespeicherteAenderung) &lt; CSng(datLetzteAenderung)<span style=\"color:blue;\"> Then<\/span>\r\n            db.Execute \"UPDATE tblObjekte SET LetzteAenderung = \" & ISODatum(datLetzteAenderung) _\r\n                & \", Loeschen = 0 WHERE ObjektID = \" & lngObjektID, dbFailOnError\r\n            db.Execute \"DELETE FROM tblObjekte WHERE UnterobjektVonObjektID = \" & lngObjektID\r\n            For Each fld In objTdfQdf.Fields\r\n                db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, &quot; _\r\n                    &amp; &quot;UnterobjektVonObjektID, Referenz) VALUES(''\" & fld.Name _\r\n                    & \"'', \" & lngObjekttypID & \", \" & lngObjektID & \", ''\" & objTdfQdf.Name _\r\n                    & \".\" & fld.Name & \"'')\", dbFailOnError\r\n            <span style=\"color:blue;\">Next<\/span> fld\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            db.Execute \"UPDATE tblObjekte SET Loeschen = 0 WHERE ObjektID = \" _\r\n                & lngObjektID, dbFailOnError\r\n            db.Execute \"UPDATE tblObjekte SET Loeschen = 0 WHERE UnterobjektVonObjektID = \" _\r\n                & lngObjektID, dbFailOnError\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, &quot; _\r\n            &amp; &quot;LetzteAenderung, Referenz) VALUES(''\" & objTdfQdf.Name & \"'', \" _\r\n            & lngObjekttypID & \", \" & ISODatum(datLetzteAenderung) _\r\n            & \", ''\" & objTdfQdf.Name & \"'')\", dbFailOnError\r\n        lngObjektID = db.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0)\r\n        For Each fld In objTdfQdf.Fields\r\n            db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, &quot; _\r\n                &amp; &quot;UnterobjektVonObjektID, Referenz) VALUES(''\" & fld.Name _\r\n                & \"'', \" & lngObjekttypID & \", \" & lngObjektID & \", ''\" _\r\n                & objTdfQdf.Name & \".\" & fld.Name & \"'')\", dbFailOnError\r\n        <span style=\"color:blue;\">Next<\/span> fld\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Eintragen der Tabellen und Felder in die Tabelle tblObjekte<\/span><\/b><\/p>\n<ul>\n<li><b>db<\/b>: Verweis auf die aktuelle Datenbank<\/li>\n<li><b>objTdfQdf<\/b>: Verweis auf das zu untersuchende <b>TableDef<\/b>&#8211; oder <b>QueryDef<\/b>-Objekt<\/li>\n<li><b>lngObjectType<\/b>: Objekttyp, hier <b>0 <\/b>(Tabelle) oder <b>1 <\/b>(Abfrage)<\/li>\n<\/ul>\n<p>Die Prozedur liest zun&auml;chst den Zeitpunkt der letzten Aktualisierung der Tabelle oder Abfrage aus der Eigenschaft <b>LastUpdated<\/b> in die Variable <b>datLetzteAenderung <\/b>ein. Dann ermittelt sie, wiederum per <b>DLookup<\/b>-Funktion, den Zeitpunkt der letzten Speicherung der Daten dieser Tabelle oder Abfrage in der Tabelle <b>tblObjekte<\/b>.<\/p>\n<p>Dann pr&uuml;ft die Prozedur <b>TabellenAbfragenFelder<\/b>, ob der mit der <b>Nz<\/b>-Funktion ermittelte Wert von <b>datLetzteGespeicherteAktualisierung <\/b>nicht den Wert <b>0 <\/b>enth&auml;lt. Dies ist der Fall, wenn dieses Objekt noch gar nicht gespeichert wurde, und f&uuml;hrt dazu, dass das Objekt im ersten Teil der <b>If&#8230;Then<\/b>-Bedingung aktualisiert und im zweiten Teil neu angelegt wird.<\/p>\n<p>Der erste Teil der <b>If&#8230;Then<\/b>-Bedingung unterscheidet wiederum, ob die letzte Speicherung in der Tabelle <b>tblObjekte <\/b>&auml;lter als die aktuelle Version der Tabelle oder Abfrage ist.<\/p>\n<p>Falls ja, aktualisiert sie die Informationen zu dieser Tabelle oder Abfrage, falls nein, aktualisiert sie nur das Feld <b>Loeschen <\/b>f&uuml;r die Tabelle\/Abfrage und die enthaltenen Felder auf den Wert <b>False<\/b>.<\/p>\n<p>Wenn die Daten aktualisiert werden m&uuml;ssen, weil das Objekt zwischenzeitlich ge&auml;ndert wurde, f&uuml;hrt die Prozedur zun&auml;chst eine <b>UPDATE<\/b>-Abfrage aus, welche den Zeitpunkt der letzten &auml;nderung auf die aktuelle Zeit und das Feld <b>Loeschen <\/b>auf den Wert <b>False <\/b>einstellt.<\/p>\n<p>Die Felder der Tabelle oder Abfrage wollen wir in diesem Fall gleich gr&uuml;ndlich aktualisieren &#8211; und zwar durch L&ouml;schen und erneutes Anlegen. Dies erledigen die beiden folgenden <b>DELETE<\/b>&#8211; und <b>INSERT INTO<\/b>-Anweisungen. Letztere wird dabei in einer <b>For Each<\/b>-Schleife &uuml;ber alle <b>Field<\/b>-Objekte ausgef&uuml;hrt und legt so f&uuml;r jedes Feld der soeben untersuchten Tabelle oder Abfrage einen Datensatz in der Tabelle <b>tblObjekte <\/b>an. Dabei ist wichtig, dass das Feld <b>UnterobjektVonObjektID <\/b>den Prim&auml;rschl&uuml;sselwert des Eintrags erh&auml;lt, der die Tabelle oder Abfrage selbst ausweist.<\/p>\n<p>Sollten keine &auml;nderungen vorliegen, tr&auml;gt die Prozedur einfach nur f&uuml;r alle betroffenen Datens&auml;tze (also den f&uuml;r die Tabelle\/Abfrage und die f&uuml;r die einzelnen Felder) den Wert <b>False <\/b>f&uuml;r das Feld <b>Loeschen <\/b>ein.<\/p>\n<p>Fehlt noch der Fall, dass die Tabelle oder Abfrage noch gar nicht gespeichert wurde. Die Prozedur tr&auml;gt dann zun&auml;chst einen neuen Datensatz f&uuml;r die Tabelle oder Abfrage in die Tabelle <b>tblObjekte <\/b>ein. Sie ermittelt mit <b>SELECT @@IDENTITY <\/b>den Prim&auml;rschl&uuml;sselwert des neu angelegten Datensatzes und verwendet diesen in der folgenden Schleife &uuml;ber alle Felder der Tabelle oder Abfrage, um in <b>UnterobjektVonObjektID <\/b>die Zuordnung des Feldes zum &uuml;bergeordneten Tabelle\/Abfrage-Datensatz herzustellen.<\/p>\n<p>Nach dem Einlesen einiger Beispieltabellen sieht die Tabelle <b>tblObjekte<\/b> etwa wie in Bild 4 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_921_004.png\" alt=\"Die Tabelle tblObjekte mit einigen Beispieldaten\" width=\"700\" height=\"226,6042\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Die Tabelle tblObjekte mit einigen Beispieldaten<\/span><\/b><\/p>\n<p><b>Eintragen von Formularen in tblObjekte<\/b><\/p>\n<p>Die Prozedur zum Eintrag eines Formulars samt Steuerelementen in die Tabelle <b>tblObjekte <\/b>unterscheidet sich etwa von der f&uuml;r die Tabellen. Der Grund ist, dass wir f&uuml;r Tabellen und Abfragen auf der einen und f&uuml;r Formulare und Berichte auf der anderen Seite verschiedene Auflistungen durchlaufen und unterschiedliche Objekte untersuchen m&uuml;ssen.<\/p>\n<p>Die Prozedur <b>FormulareBerichteSteuerelemente <\/b>aus Listing 4 k&uuml;mmert sich um das Eintragen letzterer Objekte.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FormulareBerichteSteuerelemente(db<span style=\"color:blue;\"> As <\/span>dao.Database, _\r\n        objFrmRpt<span style=\"color:blue;\"> As Object<\/span>, lngObjekttypID<span style=\"color:blue;\"> As Long<\/span>, _\r\n        datLetzteAenderung<span style=\"color:blue;\"> As Date<\/span>, datLetzteGespeicherteAenderung<span style=\"color:blue;\"> As Date<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>lngObjektID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>ctl<span style=\"color:blue;\"> As <\/span>Control\r\n    <span style=\"color:blue;\">Dim <\/span>strObjekttyp<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">If <\/span>lngObjekttypID = -1<span style=\"color:blue;\"> Then<\/span>\r\n        strObjekttyp = \"Forms\"\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        strObjekttyp = \"Report\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> datLetzteGespeicherteAenderung = 0<span style=\"color:blue;\"> Then<\/span>\r\n        lngObjektID = DLookup(\"ObjektID\", \"tblObjekte\", \"Objekt = ''\" & objFrmRpt.Name & \"''\")\r\n        db.Execute \"UPDATE tblObjekte SET LetzteAenderung = \" & ISODatum(datLetzteAenderung) _\r\n            & \", Loeschen = 0 WHERE ObjektID = \" & lngObjektID, dbFailOnError\r\n        db.Execute \"DELETE FROM tblObjekte WHERE UnterobjektVonObjektID = \" & lngObjektID\r\n        For Each ctl In objFrmRpt.Controls\r\n            <span style=\"color:blue;\">If <\/span>ctl.ControlType = acSubform<span style=\"color:blue;\"> Then<\/span>\r\n                db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, &quot;_\r\n                    &amp; &quot;UnterobjektVonObjektID, Referenz, \" _\r\n                    & \"EnthaeltUnterformular) VALUES(''\" & ctl.Name _\r\n                    & \"'', \" & ctl.ControlType & \", \" & lngObjektID & \", ''\" _\r\n                    & strObjekttyp & \"!\" & objFrmRpt.Name & \"!\" & ctl.Name _\r\n                    & \"'', ''\" & ctl.SourceObject & \"'')\", dbFailOnError\r\n            <span style=\"color:blue;\">Else<\/span>\r\n                db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, &quot; _\r\n                    &quot;UnterobjektVonObjektID, Referenz) VALUES(''\" & ctl.Name _\r\n                    & \"'', \" & ctl.ControlType & \", \" & lngObjektID & \", ''\" _\r\n                    & strObjekttyp & \"!\" & objFrmRpt.Name & \"!\" _\r\n                    & ctl.Name & \"'')\", dbFailOnError\r\n            <span style=\"color:blue;\">End If<\/span>\r\n        <span style=\"color:blue;\">Next<\/span> ctl\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, LetzteAenderung, &quot; _\r\n            &amp; &quot;Referenz) VALUES(''\" & objFrmRpt.Name & \"'', \" _\r\n            & lngObjekttypID & \", \" & ISODatum(datLetzteAenderung) _\r\n            & \", ''\" & strObjekttyp & \"!\" & objFrmRpt.Name _\r\n            & \"'')\", dbFailOnError\r\n        lngObjektID = db.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0)\r\n        For Each ctl In objFrmRpt.Controls\r\n            <span style=\"color:blue;\">If <\/span>ctl.ControlType = acSubform<span style=\"color:blue;\"> Then<\/span>\r\n                db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, &quot; _\r\n                    &quot;UnterobjektVonObjektID, Referenz, \" _\r\n                    & \"EnthaeltUnterformular) VALUES(''\" & ctl.Name & \"'', \" _\r\n                    & ctl.ControlType & \", \" & lngObjektID & \", ''\" _\r\n                    & strObjekttyp & \"!\" & objFrmRpt.Name & \"!\" & ctl.Name _\r\n                    & \"'', ''\" & ctl.SourceObject & \"'')\", dbFailOnError\r\n            <span style=\"color:blue;\">Else<\/span>\r\n                db.Execute \"INSERT INTO tblObjekte(Objekt, Objekttyp, &quot; _\r\n                    &amp; &quot;UnterobjektVonObjektID, Referenz) VALUES(''\" & ctl.Name _\r\n                    & \"'', \" & ctl.ControlType & \", \" & lngObjektID & \", ''\" _\r\n                    & strObjekttyp & \"!\" & objFrmRpt.Name _\r\n                    & \"!\" & ctl.Name & \"'')\", dbFailOnError\r\n            <span style=\"color:blue;\">End If<\/span>\r\n        <span style=\"color:blue;\">Next<\/span> ctl\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: Eintragen der Formulare und Steuerelemente in die Tabelle tblObjekte<\/span><\/b><\/p>\n<p>Sie erwartet die folgenden Parameter:<\/p>\n<ul>\n<li><b>db<\/b>: Verweis auf das aktuelle <b>Database<\/b>-Objekt<\/li>\n<li><b>objFrmRpt<\/b>: Verweis auf das Formular oder den Bericht<\/li>\n<li><b>lngObjekttypID<\/b>: Objekttyp (<b>-1<\/b> f&uuml;r Formulare, Berichte sind noch nicht implementiert)<\/li>\n<li><b>datLetzteAenderung<\/b>: Datum der letzten &auml;nderung des Objekts<\/li>\n<li><b>datLetzteGespeicherteAenderung<\/b>: Datum des letzten in <b>tblObjekte <\/b>gespeicherten Zustands<\/li>\n<\/ul>\n<p>Die Prozedur ermittelt zun&auml;chst anhand des Wertes von <b>lngObjekttypID <\/b>die Bezeichnung der Auflistung entweder f&uuml;r Formulare (<b>Forms<\/b>) oder Berichte (<b>Reports<\/b>). Diese soll sp&auml;ter beim Ausgeben eines Formulars\/Steuerelements &uuml;ber das Kontextmen&uuml; mit dem Objektnamen ausgegeben werden, also etwa <b>Forms!frmFormular<\/b>.<\/p>\n<p>Wenn der Parameter <b>datLetzteGespeicherteAenderung <\/b>nicht den Wert <b>0 <\/b>enth&auml;lt (<b>0 <\/b>bedeutet, dass das Objekt noch nicht gespeichert wurde), ermittelt die Prozedur per <b>DLookup <\/b>den Prim&auml;rschl&uuml;sselwert des Datensatzes f&uuml;r das Formular in der Tabelle <b>tblObjekte<\/b>. Sie aktualisiert dann den vorhandenen Datensatz und tr&auml;gt das aktuelle Datum f&uuml;r das Feld <b>LetzteAenderung <\/b>sowie den Wert <b>False <\/b>f&uuml;r das Feld <b>Loeschen <\/b>ein.<\/p>\n<p>Danach l&ouml;scht die Prozedur alle Datens&auml;tze f&uuml;r die Steuerelemente des soeben bearbeiteten Formular-Datensatzes. Diese werden, da ja neue Steuerelemente hinzugekommen oder vorhandene entfernt worden sein k&ouml;nnten, vollst&auml;ndig neu angelegt. Dies geschieht wiederum innerhalb einer <b>For Each<\/b>-Schleife &uuml;ber alle Elemente der <b>Controls<\/b>-Auflistung des mit <b>objFrmRpt <\/b>&uuml;bergebenen Formular-Objekts. Dabei gibt es zwei Varianten, um den entsprechenden Datensatz zur Tabelle <b>tblObjekte <\/b>hinzuzuf&uuml;gen: Eine f&uuml;r Steuerelemente mit dem Typ <b>acSubform <\/b>und eine f&uuml;r die &uuml;brigen. Wenn es sich um ein Unterformular-Steuerelement handelt, soll zus&auml;tzlich in das Feld <b>EnthaeltUnterformular <\/b>noch der Name des im Unterformular-Steuerelement enthaltenen Unterformulars gespeichert werden. Dieses Feature ist f&uuml;r eine zuk&uuml;nftige Erweiterung gedacht, aktuell liefert die L&ouml;sung nur Kontextmen&uuml;s bis zur ersten Ebene von Steuerelementen eines Formulars. Die zweite Variante speichert genau wie die erste alle notwendigen Information zum aktuellen Steuerelement in der Tabelle <b>tblObjekte<\/b> &#8211; vor allem aber den Wert <b>False <\/b>im Feld <b>Loeschen<\/b>, damit der neu erstellte Datensatz weiter unten nicht direkt wieder gel&ouml;scht wird.<\/p>\n<p>Sollte der Parameter <b>datLetzteGespeicherteAenderung <\/b>den Wert <b>0 <\/b>enthalten, ist das Formular noch nicht vorhanden. Dann legt die Prozedur zun&auml;chst per <b>INSERT INTO<\/b>-Aktionsabfrage einen neuen Datensatz f&uuml;r das Formular in der Tabelle <b>tblObjekte <\/b>an. Die folgende Anweisung ermittelt den Prim&auml;rschl&uuml;sselwert des neu angelegten Datensatzes, damit dieser weiter unten gleich als Wert des Feldes <b>UnterobjektVonObjekt-ID <\/b>verwendet werden kann. Dort legt die Prozedur, wieder innerhalb einer <b>For Each<\/b>-Schleife &uuml;ber alle Steuerelemente des Formulars, f&uuml;r jedes Steuerelement einen neuen Eintrag in der Tabelle <b>tblObjekte <\/b>an. Auch hier gibt es wieder zwei Varianten, die davon abh&auml;ngen, ob es sich bei dem aktuellen Steuerelement um ein Unterformular- oder ein anderes Steuerelement handelt.<\/p>\n<p>Bild 5 zeigt die Daten der Tabelle <b>tblObjekte <\/b>f&uuml;r ein Formular und seine Steuerelemente &#8211; inklusive Unterformular-Steuerelement.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_01\/pic_921_005.png\" alt=\"Die Tabelle tblObjekte mit einigen Beispieldaten f&uuml;r die Abbildung eines Formulars\" width=\"700\" height=\"269,1277\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Die Tabelle tblObjekte mit einigen Beispieldaten f&uuml;r die Abbildung eines Formulars<\/span><\/b><\/p>\n<p><b>Kontextmen&uuml; erzeugen<\/b><\/p>\n<p>Nun ben&ouml;tigen wir noch eine Prozedur, die aus den in der Tabelle <b>tblObjekte <\/b>gespeicherten Daten ein entsprechendes Kontextmen&uuml; zaubert.<\/p>\n<p>Dabei ergibt sich ein Problem, das aus einer unterschiedlichen Implementierung beim Anklicken eines Kontextmen&uuml;-Eintrags resultiert: W&auml;hrend Sie f&uuml;r Kontextmen&uuml;s im Access-Fenster einfach die auszuf&uuml;hrende Funktion mit der Eigenschaft <b>OnAction <\/b>des <b>CommandBarButton<\/b>-Elements definieren, ist dies f&uuml;r Kontextmen&uuml;s im VBA-Editor nicht m&ouml;glich. Hier ben&ouml;tigen Sie ein als <b>WithEvents <\/b>deklariertes <b>CommandBarButton<\/b>-Element, f&uuml;r das Sie eine Ereignisprozedur erstellen, die auf das <b>Click<\/b>-Ereignis reagiert. Da wir hier eine unbestimmte Anzahl von Kontextmen&uuml;-Schaltfl&auml;chen erstellen m&uuml;ssen und nicht f&uuml;r jede einzelne eine eigene Variable deklarieren wollen, arbeiten wir mit einer eigenen Klasse, welche jeweils eine Variable zum Aufnehmen des <b>CommandBarButton<\/b>-Steuerelements und die Implementierung des Click-Ereignisses enth&auml;lt &#8211; dazu sp&auml;ter mehr.<\/p>\n<p>Zun&auml;chst deklarieren wir im Modul <b>mdl-VBE-Kontextmenue <\/b>eine <b>Collection<\/b>, die sp&auml;ter die einzelnen Klassen f&uuml;r jedes einzelne <b>CommandBarButton<\/b>-Element aufnimmt:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>colCommandBarButtons<span style=\"color:blue;\"> As <\/span>Collection<\/pre>\n<p>Dann kommen wir zu der Prozedur, welche den Gro&szlig;teil der Arbeit erledigt. Diese hei&szlig;t <b>VBEKontextmenueErstellen <\/b>und sieht wie in Listing 5 aus. Die Prozedur referenziert zun&auml;chst das weiter oben ermittelte Kontextmen&uuml; <b>Code Window<\/b>. Dann instanziert sie die oben deklarierte Collection <b>colCommandBarButtons<\/b> und l&ouml;scht ein eventuell im Kontextmen&uuml; vorhandenes Element namens <b>Datenbank-Objekte<\/b>. Dieses wird danach neu erstellt, allerdings nur als tempor&auml;res Element, und mit der gew&uuml;nschten Bezeichnung versehen.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabellenAbfragenFelderKontextmenue()\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>cbr<span style=\"color:blue;\"> As <\/span>CommandBar, cbp<span style=\"color:blue;\"> As <\/span>CommandBarPopup\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset, rstSteuerelemente<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>cbpTabellen<span style=\"color:blue;\"> As <\/span>CommandBarPopup, cbpAbfragen<span style=\"color:blue;\"> As <\/span>CommandBarPopup\r\n    Dim cbpFormulare<span style=\"color:blue;\"> As <\/span>CommandBarPopup\r\n    <span style=\"color:blue;\">Dim <\/span>cbpElement<span style=\"color:blue;\"> As <\/span>CommandBarPopup, objcbb<span style=\"color:blue;\"> As <\/span>clsCommandBarButton\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> cbr = VBE.CommandBars(\"Code Window\")\r\n    <span style=\"color:blue;\">Set<\/span> colCommandBarButtons = <span style=\"color:blue;\">New<\/span> Collection\r\n    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n    cbr.Controls(\"Datenbank-Objekte\").Delete\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n    <span style=\"color:blue;\">Set<\/span> cbp = cbr.Controls.Add(msoControlPopup, , , , <span style=\"color:blue;\">True<\/span>)\r\n    cbp.Caption = \"Datenbank-Objekte\"\r\n    <span style=\"color:blue;\">Set<\/span> cbpTabellen = cbp.Controls.Add(msoControlPopup, , , , <span style=\"color:blue;\">True<\/span>)\r\n    cbpTabellen.Caption = \"Tabellen\"\r\n    <span style=\"color:blue;\">Set<\/span> cbpAbfragen = cbp.Controls.Add(msoControlPopup, , , , <span style=\"color:blue;\">True<\/span>)\r\n    cbpAbfragen.Caption = \"Abfragen\"\r\n    <span style=\"color:blue;\">Set<\/span> cbpFormulare = cbp.Controls.Add(msoControlPopup, , , , <span style=\"color:blue;\">True<\/span>)\r\n    cbpFormulare.Caption = \"Formulare\"\r\n    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblObjekte &quot; _\r\n        &amp; &quot;WHERE UnterobjektVonObjektID IS NULL\", dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n        Select Case rst!Objekttyp\r\n            <span style=\"color:blue;\">Case <\/span>0\r\n                <span style=\"color:blue;\">Set<\/span> cbpElement = cbpTabellen.Controls.Add(msoControlPopup, , , , <span style=\"color:blue;\">True<\/span>)\r\n                <span style=\"color:blue;\">Set<\/span> objcbb = ElementHinzufuegen(cbpElement, \"[Tabelle]\", rst!Referenz)\r\n                colCommandBarButtons.Add objcbb\r\n            <span style=\"color:blue;\">Case <\/span>1\r\n                <span style=\"color:blue;\">Set<\/span> cbpElement = cbpAbfragen.Controls.Add(msoControlPopup, , , , <span style=\"color:blue;\">True<\/span>)\r\n                <span style=\"color:blue;\">Set<\/span> objcbb = ElementHinzufuegen(cbpElement, \"[Abfrage]\", rst!Referenz)\r\n                colCommandBarButtons.Add objcbb\r\n            <span style=\"color:blue;\">Case <\/span>-1\r\n                <span style=\"color:blue;\">Set<\/span> cbpElement = cbpFormulare.Controls.Add(msoControlPopup, , , , <span style=\"color:blue;\">True<\/span>)\r\n                <span style=\"color:blue;\">Set<\/span> objcbb = ElementHinzufuegen(cbpElement, \"[Forms]\", rst!Referenz)\r\n                colCommandBarButtons.Add objcbb\r\n        <span style=\"color:blue;\">End Select<\/span>\r\n        <span style=\"color:blue;\">With<\/span> cbpElement\r\n            .Caption = rst!Objekt\r\n            <span style=\"color:blue;\">Set<\/span> rstSteuerelemente = db.OpenRecordset(_\r\n                \"SELECT * FROM tblObjekte WHERE UnterobjektVonObjektID = \" _\r\n                & rst!ObjektID, dbOpenDynaset)\r\n            <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstSteuerelemente.EOF\r\n                <span style=\"color:blue;\">Set<\/span> objcbb = ElementHinzufuegen(cbpElement, rstSteuerelemente!Objekt, rst!Referenz, _\r\n                    Nz(rstSteuerelemente!EnthaeltUnterformular, \"\"))\r\n                colCommandBarButtons.Add objcbb\r\n                rstSteuerelemente.Move<span style=\"color:blue;\">Next<\/span>\r\n            <span style=\"color:blue;\">Loop<\/span>\r\n        End <span style=\"color:blue;\">With<\/span>\r\n        rst.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Auslesen der Elemente der Tabelle tblObjekte und Erstellen des Kontextmen&uuml;s<\/span><\/b><\/p>\n<p>Die Prozedur erstellt nun drei <b>CommandBarPopup<\/b>-Elemente mit den Beschriftungen <b>Tabellen, Abfragen <\/b>und <b>Formulare<\/b>. Dann &ouml;ffnet Sie ein Recordset auf Basis aller Datens&auml;tze der Tabelle <b>tblObjekte<\/b>, deren Feld <b>UnterobjektVonObjektID <\/b>den Wert <b>NULL <\/b>hat. Dies entspricht den Objekten der obersten Ebene, also den Tabellen, Abfragen und Formularen. Die Prozedur durchl&auml;uft alle Datens&auml;tze des Recordsets und pr&uuml;ft dabei den Wert des Feldes <b>Objekttyp<\/b>. Im Falle des Wertes <b>0 <\/b>(Tabelle) erstellt sie ein neues <b>CommandBarPopup<\/b>-Element unterhalb des mit <b>cbpTabellen <\/b>referenzierten Eintrags mit dem Text <b>Tabellen<\/b> und speichert den Verweis auf das neue Element in der Variablen <b>cbpElement<\/b>.<\/p>\n<p>Die folgenden beiden Anweisungen legen &uuml;ber die Funktion <b>ElementHinzufuegen <\/b>ein neues Objekt auf Basis der Klasse <b>clsCommandBarButton <\/b>an und speichern dieses als Element der oben erstellten Collection <b>colCommandBarButtons<\/b>.<\/p>\n<p>In diesem Fall soll f&uuml;r jede Tabelle, jede Abfrage und jedes Formular eine Schaltfl&auml;che mit der Beschriftung <b>[Tabelle]<\/b>, <b>[Abfrage]<\/b> oder <b>[Formular]<\/b> erstellt werden &#8211; je nach Objekttyp. Diese kann der Benutzer anklicken, wenn er nur den Namen der Tabelle, der Abfrage oder des Formulars (in diesem Fall mit f&uuml;hrendem <b>Forms!<\/b>) in das Codefenster &uuml;bernehmen will und nicht den Ausdruck inklusive eines Feld- oder Steuerelementnamens. Was die Funktion <b>ElementHinzufuegen <\/b>im Detail erledigt, beschreiben wir weiter unten. Wichtig ist an dieser Stelle, dass die Funktion einen Verweis auf ein neu erzeugtes Objekt des Typs <b>clsCommandBarButton <\/b>zur&uuml;ckliefert, das unbedingt als Element der Collection <b>colCommandBarButtons <\/b>hinzugef&uuml;gt werden muss. Anderenfalls w&uuml;rde die soeben erzeugte Instanz beim n&auml;chsten Durchlauf der Schleife &uuml;berschrieben &#8211; und das ist schlecht, denn genau die Instanzen dieser Klasse enthalten die Ereignisprozedur, die beim Anklicken eines der Eintr&auml;ge ausgel&ouml;st werden soll.<\/p>\n<p>Gleiches geschieht f&uuml;r den Wert <b>1 <\/b>im Feld <b>Objekttyp<\/b>, nur dass dann ein Abfrage-Element angelegt wird.<\/p>\n<p>Beim Wert <b>-1 <\/b>f&uuml;gt die Prozedur einen Formular-Datensatz hinzu.<\/p>\n<p><b>Felder und Steuerelemente hinzuf&uuml;gen<\/b><\/p>\n<p>Die folgenden Zeilen greifen das mit <b>cbpElement <\/b>referenzierte neue Element, das unterhalb des Elements <b>Tabellen<\/b>, <b>Abfragen <\/b>oder <b>Formulare <\/b>angelegt wurde, auf. Sie tragen zun&auml;chst den Wert des Feldes <b>Objekt <\/b>des Recordsets als Beschriftung (<b>Caption<\/b>) des neuen Elements ein &#8211; also beispielsweise <b>tblTabelle<\/b>, <b>qryAbfrage <\/b>oder <b>frmFormular<\/b>.<\/p>\n<p>Dann erstellt die Prozedur ein neues Recordset, das alle Datens&auml;tze der Tabelle <b>tblObjekte <\/b>enth&auml;lt, die dem soeben erstellten Element (Tabelle, Abfrage oder Formular) untergeordnet sind (also Felder oder Steuerelemente).<\/p>\n<p>In einer <b>Do While<\/b>-Schleife wird erneut die <b>ElementHinzufuegen<\/b>-Funktion aufgerufen, die f&uuml;r jedes Feld und jedes Steuerelement je einen Eintrag unterhalb des Eintrags mit dem Namen der Tabelle, der Abfrage oder des Formulars anlegt.<\/p>\n<p>Dieser Vorgang wird f&uuml;r alle Tabellen, Abfragen und Formulare sowie die enthaltenen Felder und Steuerelemente wiederholt.<\/p>\n<p><b>Routine zum Erstellen von Objektinstanzen<\/b><\/p>\n<p>Die Funktion <b>ElementHinzufuegen <\/b>aus Listing 6 erwartet die folgenden Parameter:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ElementHinzufuegen(cbpElement<span style=\"color:blue;\"> As <\/span>CommandBarPopup, _\r\n        strCaption<span style=\"color:blue;\"> As String<\/span>, strText<span style=\"color:blue;\"> As String<\/span>, _\r\n        <span style=\"color:blue;\">Optional<\/span> strEnthaeltUnterformular<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>clsCommandBarButton\r\n    <span style=\"color:blue;\">Dim <\/span>cbb<span style=\"color:blue;\"> As <\/span>CommandBarButton\r\n    <span style=\"color:blue;\">Dim <\/span>objcbb<span style=\"color:blue;\"> As <\/span>clsCommandBarButton\r\n    <span style=\"color:blue;\">Set<\/span> cbb = cbpElement.Controls.Add(msoControlButton, , , , <span style=\"color:blue;\">True<\/span>)\r\n    <span style=\"color:blue;\">With<\/span> cbb\r\n        .Caption = strCaption\r\n        <span style=\"color:blue;\">Set<\/span> objcbb = <span style=\"color:blue;\">New<\/span> clsCommandBarButton\r\n        <span style=\"color:blue;\">With<\/span> objcbb\r\n            <span style=\"color:blue;\">Set<\/span> .CommandBarButton = cbb\r\n            .Text = strText\r\n        End <span style=\"color:blue;\">With<\/span>\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strEnthaeltUnterformular) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n        ''...Unterformular-Elemente hinzuf&uuml;gen\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> ElementHinzufuegen = objcbb\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Erstellen der Objekte f&uuml;r die einzelnen CommandBarButton-Elemente auf Basis der Klasse clsCommandBarButton<\/span><\/b><\/p>\n<ul>\n<li><b>cbpElement<\/b>: Verweis auf das <b>CommandBarPopup<\/b>-Element beziehungsweise den Eintrag, unter dem die Schaltfl&auml;che im Kontextmen&uuml; angelegt werden soll<\/li>\n<li><b>strCaption<\/b>: Beschriftung des Elements<\/li>\n<li><b>strText<\/b>: Text, der beim Anklicken des Elements in den Code im VBA-Codefenster eingef&uuml;gt werden soll<\/li>\n<li><b>strEnthaeltUnterformular<\/b>: Name des Unterformulars, sofern es sich um ein Unterformular-Steuerelement handelt<\/li>\n<\/ul>\n<p>Die Funktion deklariert ein Objekt des Typs <b>CommandBarButton<\/b>, um den Verweis auf die neu zu erstellende Kontextmen&uuml;-Schaltfl&auml;che aufzunehmen. Au&szlig;erdem verwendet sie mit <b>objcbb <\/b>eine Objektvariable des Typs <b>clsCommandBarButton<\/b>. Die erste ausf&uuml;hrbare Anweisung der Prozedur erstellt das neue <b>CommandBarButton<\/b>-Objekt als Unterelement des mit <b>cbpElement <\/b>referenzierten Elements, also beispielsweise des Eintrags f&uuml;r eine Tabelle oder ein Formular. F&uuml;r dieses Element stellt die Funktion dann die Beschriftung ein und erstellt ein neues Objekt auf Basis der Klasse <b>clsCommandBarButton<\/b>. Diese Klasse bietet zwei Eigenschaften an, die wir f&uuml;llen m&uuml;ssen:<\/p>\n<ul>\n<li><b>CommandBarButton <\/b>f&uuml;llen wir mit dem Verweis auf die neue Kontextmen&uuml;-Schaltfl&auml;che und an<\/li>\n<li><b>Text <\/b>&uuml;bergeben wir den beim Anklicken in den VBA-Editor einzuf&uuml;genden Text.<\/li>\n<\/ul>\n<p>Als Funktionswert gibt die Funktion dann den Verweis auf das neu erstellte Objekt des Typs <b>clsCommandBarButton <\/b>zur&uuml;ck.<\/p>\n<p><b>Die Klasse clsCommandBarButton<\/b><\/p>\n<p>Damit kommen wir zur Klasse <b>clsCommandBarButton<\/b>. Diese enth&auml;lt die in Listing 7 aufgef&uuml;hrten Elemente. Bevor wir diese beschreiben, m&uuml;ssen Sie einen Verweis auf die Bibliothek <b>Microsoft Visual Basics for Applications Extensibility 5.3 <\/b>zum VBA-Projekt hinzuf&uuml;gen.<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>WithEvents m_cbb<span style=\"color:blue;\"> As <\/span>CommandBarButton\r\n<span style=\"color:blue;\">Private <\/span>m_Text<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>CommandBarButton(cbb<span style=\"color:blue;\"> As <\/span>CommandBarButton)\r\n     <span style=\"color:blue;\">Set<\/span> m_cbb = cbb\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>Text(strText<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Text = strText\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>m_cbb_Click(ByVal Ctrl<span style=\"color:blue;\"> As <\/span>Office.CommandBarButton, CancelDefault<span style=\"color:blue;\"> As Boolean<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>lngStartLine<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngStartColumn<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngEndLine<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngEndColumn<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strLineBefore<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strLineAfter<span style=\"color:blue;\"> As String<\/span>\r\n    VBE.ActiveCodePane.GetSelection lngStartLine, lngStartColumn, lngEndLine, lngEndColumn\r\n    strLineBefore = VBE.ActiveCodePane.CodeModule.Lines(lngStartLine, 1)\r\n    strLineAfter = <span style=\"color:blue;\">Left<\/span>(strLineBefore, lngStartColumn - 1) & m_Text _\r\n        & <span style=\"color:blue;\">Mid<\/span>(strLineBefore, lngStartColumn)\r\n    VBE.ActiveCodePane.CodeModule.ReplaceLine lngStartLine, strLineAfter\r\n    VBE.ActiveCodePane.SetSelection lngStartLine, lngStartColumn + <span style=\"color:blue;\">Len<\/span>(m_Text), _\r\n        lngEndLine, lngStartColumn + <span style=\"color:blue;\">Len<\/span>(m_Text)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Code des Klassenmoduls clsCommandBarButton<\/span><\/b><\/p>\n<p>Die Variable <b>m_Text <\/b>ist als String definiert und nimmt &uuml;ber die <b>Property Let<\/b>-Prozedur <b>Text <\/b>den beim Anklicken der Schaltfl&auml;che einzuf&uuml;genden Text auf. F&uuml;r das F&uuml;llen ist diese Zeile aus der oben beschriebenen Funktion <b>ElementHinzufuegen <\/b>verantwortlich:<\/p>\n<pre>.Text = strText<\/pre>\n<p>Die Variable <b>m_cbb <\/b>nimmt den Verweis auf das <b>CommandBarButton<\/b>-Element auf. Sie wird mit dem Schl&uuml;sselwort <b>WithEvents <\/b>deklariert, damit wir das Ereignis dieses Objekts im Klassenmodul implementieren k&ouml;nnen. Auch hier gibt es eine <b>Property Set<\/b>-Prozedur, mit der man von au&szlig;en den Wert der Variablen <b>m_cbb <\/b>einstellen kann. In diesem Fall wird dieser Variable von der oben beschriebenen Funktion <b>ElementHinzufuegen <\/b>gef&uuml;llt:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> .CommandBarButton = cbb<\/pre>\n<ul>\n<li>dem Text vom Start der Zeile aus <b>strLineBefore <\/b>bis zum Zeichen vor dem ersten Zeichen der Markierung,<\/li>\n<li>dem einzuf&uuml;genden Text und<\/li>\n<li>dem Text vom ersten Zeichen der Markierung bis zum Ende der Zeile.<\/li>\n<\/ul>\n<p><b>L&ouml;sung in Add-In verwandeln<\/b><\/p>\n<p>Nun fehlt nur noch eine M&ouml;glichkeit, diese Anwendung nach dem &ouml;ffnen der aktuellen Datenbank auch einzusetzen. Hier wird es etwas schwierig: Eigentlich m&uuml;ssten die beiden Funktionen <b>ObjekteEinlesen <\/b>und <b>TabellenAbfragenFelderKontextmenue <\/b>gleich beim &ouml;ffnen der Datenbank ausgef&uuml;hrt werden. Es gibt jedoch kein Ereignis, dass beim &ouml;ffnen einer Datenbank ausgel&ouml;st wird. Wir k&ouml;nnten noch daf&uuml;r sorgen, das die beiden Funktionen als Teil eines Add-Ins beim Starten von Access ausgel&ouml;st werden. Das hilft aber auch nicht weiter, da zu diesem Zeitpunkt ja noch keine Datenbank geladen ist, deren Elemente wir einlesen k&ouml;nnten.<\/p>\n<p>Au&szlig;erdem haben wir noch nicht ber&uuml;cksichtigt, dass die L&ouml;sung ja nicht nur mit einer, sondern gleich mit mehreren Anwendungen zusammenarbeiten sollte &#8211; wer programmiert denn schon die ganze Zeit nur eine einzige Datenbankanwendung Die Frage ist also: Wenn wir ein Add-In erstellen, wie speichern wir die Elemente f&uuml;r die unterschiedlichen Datenbanken teilen wir die Elemente des Add-Ins dann auf Wir k&ouml;nnten die komplette Funktionalit&auml;t in einer Add-In-Datenbank vorhalten und auch die Daten &uuml;ber die Elemente der Anwendung dort speichern. Dann m&uuml;ssten wir der Tabelle <b>tblObjekt <\/b>jedoch noch ein Feld hinzuf&uuml;gen, das den Pfad oder zumindest den Namen der betroffenen Datenbankanwendung speichert. Alternativ schreiben wir die Tabelle <b>tblObjekte <\/b>in die jeweilige Anwendung. Das Add-In k&ouml;nnte dann jeweils auf diese Tabelle zugreifen und wir sparen das aufwendige Verwalten von Objekten aus mehreren Datenbanken.<\/p>\n<p>So machen wir es! Wir wandeln die Datenbank also in eine Add-In-Datenbank um, indem wir die Dateiendung von <b>.mdb <\/b>auf <b>.mda <\/b>&auml;ndern. Au&szlig;erdem f&uuml;gen Sie eine Tabelle namens <b>USysRegInfo <\/b>hinzu und f&uuml;llen diese (siehe Beispieldatenbank). Dies k&ouml;nnen Sie mit der L&ouml;sung aus dem Beitrag <b>Add-In-Creator <\/b>(<b>www.access-im-unternehmen\/907<\/b>) erledigen.<\/p>\n<p>Dann f&uuml;gen Sie der Datenbank ein Modul namens <b>mdlGlobal<\/b> hinzu, das die Funktion aus Listing 8 enth&auml;lt. Die Funktion versucht zun&auml;chst, mit der Variablen <b>tdf <\/b>eine Tabelle namens <b>tblObjekte_Kontextmenue <\/b>in der aktuellen Datenbank zu referenzieren.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Autostart()\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database, dbc<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> tdf = db.TableDefs(\"tblObjekte_Kontextmenue\")\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n    <span style=\"color:blue;\">If <\/span>tdf Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        If <span style=\"color:blue;\">MsgBox<\/span>(\"F&uuml;r den Einsatz des Add-Ins muss eine &quot; _\r\n                &amp; &quot;Tabelle in der Zieldatenbank erstellt werden. Fortsetzen\", _\r\n                vbYesNo) = vbYes Then\r\n            dbc.Execute \"SELECT tblObjekte.* INTO tblObjekte_Kontextmenue IN ''\" _\r\n                & db.Name & \"'' FROM tblObjekte\"\r\n            db.Execute \"DELETE FROM tblObjekte_Kontextmenue\", dbFailOnError\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            <span style=\"color:blue;\">Exit Function<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">MsgBox<\/span> \"Das Add-In liest nun Tabellen, Abfragen und Formulare ein. &quot; _\r\n        &amp; &quot;Diese stehen dann im Kontexmen&uuml; des Codefensters \" _\r\n        & \"zur Verf&uuml;gung.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n        & \"Nach dem &ouml;ffnen der Anwendung und nach &auml;nderungen an den genannten \" _\r\n        & \"Objekten sollten Sie das Add-In erneut aufrufen, um die Kontextmen&uuml;s zu aktualisieren.\"\r\n    ObjekteEinlesen\r\n    VBEKontextmenueErstellen\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Aktionen beim Aufrufen des Add-Ins<\/span><\/b><\/p>\n<p>Bleibt <b>tdf <\/b>leer, ist die Tabelle noch nicht vorhanden und soll nach R&uuml;ckfrage erstellt werden. Dies erledigt die Funktion mit einer <b>SELECT&#8230;INTO<\/b>-Aktionsabfrage, die einfach die Tabelle <b>tblObjekte <\/b>aus dem Add-In unter dem Namen <b>tblObjekte_Kontextmenue <\/b>in die Zieltabelle schreibt und diese anschlie&szlig;end vorsichtshalber leert. Will der Benutzer die Tabelle nicht anlegen, wird das Add-In beendet. Anderenfalls setzt die Funktion ihre Arbeit fort und startet gleich mit dem Aufruf der beiden Prozeduren <b>ObjekteEinlesen <\/b>und <b>VBEKontextmenueErstellen <\/b>ihre Hauptarbeit. Diese lesen die Tabellen, Abfrage und Formulare samt Feldern und Steuerelementen in die Tabelle <b>tblObjekte_Kontextmenue <\/b>ein und erstellen das Kontextmen&uuml; f&uuml;r den VBA-Editor. Damit der Code noch funktioniert, haben wir in der Beispieldatenbank (fast) alle Referenzen auf die Tabelle <b>tblObjekte <\/b>durch <b>tblObjekte_Kontextmenue <\/b>ersetzt.<\/p>\n<p>Nun brauchen Sie das Add-In nur noch mit dem Add-In-Manager zu installieren (Ribbon-Eintrag <b>Datenbanktools|Add-Ins|Add-Ins|Add-In-Manager<\/b>) und dieses anschlie&szlig;end &uuml;ber den Eintrag <b>VBE-Kontextmen&uuml;s<\/b> unter dem gleichen Men&uuml; anzuklicken.<\/p>\n<p>Ein kleiner Nachteil ist, dass das Add-In nach dem &ouml;ffnen der Anwendung jeweils neu gestartet werden muss. Es gibt jedoch einen kleinen Trick, wenn Sie sicherstellen wollen, dass das Add-In beim &ouml;ffnen einer Anwendung ebenfalls gestartet wird. F&uuml;gen Sie einer beim Start der Anwendung ausgef&uuml;hrten VBA-Prozedur die folgende Zeile hinzu &#8211; Sie m&uuml;ssen nur das Verzeichnis an Ihr Add-In-Verzeichnis anpassen:<\/p>\n<pre>Application.Run \"C:\\Users\\Andre\\AppData\\\r\nRoaming\\Microsoft\\AddIns\\\r\nVBEKontextmenue.Autostart\"<\/pre>\n<p>Das Add-In wird dann ebenfalls gestartet.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>VBEKontextmenue.mda<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{E2B21742-2521-45B7-BA9B-0135E649DF44}\/aiu_921.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kennen Sie das auch Sie konzentrieren sich gerade mal wieder voll auf die Programmierung einer Prozedur und wollen eine SQL-Anweisung zusammenstellen. Dummerweise f&auml;llt Ihnen der Name der Tabelle und\/oder des Feldes nicht ein, das Sie dort verwenden m&ouml;chten. Also wechseln Sie zum Access-Fenster, ermitteln dort den gesuchten Namen und kehren wieder zum VBA-Editor zur&uuml;ck. Dort erg&auml;nzen Sie dann die gesuchte Anweisung. Damit ist jetzt Schluss: Dieser Beitrag stellt n&auml;mlich eine einfache L&ouml;sung vor, mit der Sie die Namen aller Tabellen, Abfragen und Felder ganz einfach per Kontextmen&uuml; nachschlagen und zum Code hinzuf&uuml;gen 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":[66012014,662014,44000025],"tags":[],"class_list":["post-55000921","post","type-post","status-publish","format-standard","hentry","category-66012014","category-662014","category-VBA_und_Programmiertechniken"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Objekt- und Feldnamen per Kontextmen&uuml; - 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\/Objekt_und_Feldnamen_per_Kontextmenue\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Objekt- und Feldnamen per Kontextmen&uuml;\" \/>\n<meta property=\"og:description\" content=\"Kennen Sie das auch Sie konzentrieren sich gerade mal wieder voll auf die Programmierung einer Prozedur und wollen eine SQL-Anweisung zusammenstellen. Dummerweise f&auml;llt Ihnen der Name der Tabelle und\/oder des Feldes nicht ein, das Sie dort verwenden m&ouml;chten. Also wechseln Sie zum Access-Fenster, ermitteln dort den gesuchten Namen und kehren wieder zum VBA-Editor zur&uuml;ck. Dort erg&auml;nzen Sie dann die gesuchte Anweisung. Damit ist jetzt Schluss: Dieser Beitrag stellt n&auml;mlich eine einfache L&ouml;sung vor, mit der Sie die Namen aller Tabellen, Abfragen und Felder ganz einfach per Kontextmen&uuml; nachschlagen und zum Code hinzuf&uuml;gen k&ouml;nnen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T21:18:58+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/7d360348c1fc442e81e1e194740b8cc0\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"31\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Objekt- und Feldnamen per Kontextmen&uuml;\",\"datePublished\":\"2020-05-22T21:18:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/\"},\"wordCount\":4898,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7d360348c1fc442e81e1e194740b8cc0\",\"articleSection\":[\"1\\\/2014\",\"2014\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/\",\"name\":\"Objekt- und Feldnamen per Kontextmen&uuml; - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7d360348c1fc442e81e1e194740b8cc0\",\"datePublished\":\"2020-05-22T21:18:58+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7d360348c1fc442e81e1e194740b8cc0\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7d360348c1fc442e81e1e194740b8cc0\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Objekt_und_Feldnamen_per_Kontextmenue\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Objekt- und Feldnamen per Kontextmen&uuml;\"}]},{\"@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":"Objekt- und Feldnamen per Kontextmen&uuml; - 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\/Objekt_und_Feldnamen_per_Kontextmenue\/","og_locale":"de_DE","og_type":"article","og_title":"Objekt- und Feldnamen per Kontextmen&uuml;","og_description":"Kennen Sie das auch Sie konzentrieren sich gerade mal wieder voll auf die Programmierung einer Prozedur und wollen eine SQL-Anweisung zusammenstellen. Dummerweise f&auml;llt Ihnen der Name der Tabelle und\/oder des Feldes nicht ein, das Sie dort verwenden m&ouml;chten. Also wechseln Sie zum Access-Fenster, ermitteln dort den gesuchten Namen und kehren wieder zum VBA-Editor zur&uuml;ck. Dort erg&auml;nzen Sie dann die gesuchte Anweisung. Damit ist jetzt Schluss: Dieser Beitrag stellt n&auml;mlich eine einfache L&ouml;sung vor, mit der Sie die Namen aller Tabellen, Abfragen und Felder ganz einfach per Kontextmen&uuml; nachschlagen und zum Code hinzuf&uuml;gen k&ouml;nnen.","og_url":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T21:18:58+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/7d360348c1fc442e81e1e194740b8cc0","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"31\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Objekt- und Feldnamen per Kontextmen&uuml;","datePublished":"2020-05-22T21:18:58+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/"},"wordCount":4898,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/7d360348c1fc442e81e1e194740b8cc0","articleSection":["1\/2014","2014","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/","url":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/","name":"Objekt- und Feldnamen per Kontextmen&uuml; - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/7d360348c1fc442e81e1e194740b8cc0","datePublished":"2020-05-22T21:18:58+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/7d360348c1fc442e81e1e194740b8cc0","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/7d360348c1fc442e81e1e194740b8cc0"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Objekt_und_Feldnamen_per_Kontextmenue\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Objekt- und Feldnamen per Kontextmen&uuml;"}]},{"@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\/55000921","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=55000921"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000921\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}