{"id":55001203,"date":"2019-10-01T00:00:00","date_gmt":"2020-05-13T20:56:14","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1203"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Datenmakros_verwalten","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/","title":{"rendered":"Datenmakros verwalten"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg06.met.vgwort.de\/na\/797f31857d6f4007b5016db4fb33870f\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Datenmakros dienen dazu, Aktionen automatisch beim &Auml;ndern der Daten einer Tabelle auszul&ouml;sen &#8211; n&auml;mlich beim Anlegen, Bearbeiten oder L&ouml;schen eines Datensatzes. Diese legt man in der Regel &uuml;ber die Benutzeroberfl&auml;che an. Leider kann man damit immer nur sehen, welche Datenmakros f&uuml;r die aktuelle im Entwurf oder in der Datenblattansicht angezeigte Tabelle zur Verf&uuml;gung stehen. Dieser Beitrag zeigt, wie Sie sich einen besseren &Uuml;berblick &uuml;ber die vorhandenen Datenmakros verschaffen, diese anzeigen und bearbeiten und sogar neue Datenmakros anlegen k&ouml;nnen &#8211; und das auch noch parametrisiert f&uuml;r gleichartige Datenmakros und mehrere Tabellen gleichzeitig.<\/b><\/p>\n<p>Genau genommen sind wir durch die L&ouml;sung des Beitrags <b>Zugriffsrechte mit Datenmakros <\/b>(<b>www.access-im-unternehmen.de\/1193<\/b>) auf die Idee zu diesem Beitrag gekommen. Dort haben wir die Tabellen der Beispieldatenbank mit einigen Datenmakros ausgestattet, die daf&uuml;r sorgen, dass die Daten der Tabelle nur durch Benutzer mit entsprechenden Zugriffsrechten ge&auml;ndert werden d&uuml;rfen.<\/p>\n<p>Es w&auml;re etwas m&uuml;hselig, diese Datenmakros bei gro&szlig;en Datenbankanwendungen f&uuml;r jede Tabelle einzelnen hinzuzuf&uuml;gen. Daher haben wir dort schon gezeigt, wie Sie per VBA-Funktion ein Datenmakro zu der im Parameter der Funktion genannten Tabelle hinzuf&uuml;gen k&ouml;nnen. Aber wir wollen etwas grundlegender starten.<\/p>\n<h2>Datenmakros erkunden<\/h2>\n<p>Die erste Frage ist: Wie k&ouml;nnen wir &uuml;berhaupt auf die bereits in den Tabellen der Anwendung vorhandenen Datenmakros zugreifen Gibt es eine Art VBA-Auflistung Oder auf welche Technik k&ouml;nnen wir zugreifen, um die vorhandenen Datenmakros zu analysieren<\/p>\n<h2>Datenmakros per Benutzeroberfl&auml;che<\/h2>\n<p>Schauen wir uns erst einmal an, wie wir &uuml;ber die Benutzeroberfl&auml;che auf die Datenmakros zugreifen. Der erste Weg ist &uuml;ber die Entwurfsansicht einer Tabelle. Dann finden Sie im Ribbon-Tab <b>Entwurf<\/b> unter <b>Feld-, Datensatz- und Tabellenereignisse <\/b>den Befehl <b>Datenmakros erstellen<\/b>. Wenn man diese Schaltfl&auml;che anklickt, &ouml;ffnet sich eine Liste aller m&ouml;glichen Daten-makros. In Bild 1 sind beispielsweise noch keine Datenmakros angelegt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_001.png\" alt=\"Datenmakros &uuml;ber die Entwurfsansicht verwalten\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Datenmakros &uuml;ber die Entwurfsansicht verwalten<\/span><\/b><\/p>\n<p>Wenn wir hier das Makro <b>Nach Einf&uuml;gung <\/b>anlegen, wird das Icon mit einem roten Rand versehen (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_002.png\" alt=\"Kennzeichnung eines vorhandenen Datenmakros\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Kennzeichnung eines vorhandenen Datenmakros<\/span><\/b><\/p>\n<h2>Datenmakros per Datenblatt<\/h2>\n<p>In der Datenblattansicht ist es noch &uuml;bersichtlicher (siehe Bild 3). Hier finden Sie im Ribbon-Tab <b>Tabelle <\/b>einige Schaltfl&auml;chen, mit denen Sie Datenmakros anlegen oder bearbeiten k&ouml;nnen. Wenn das Daten-makro bereits vorhanden ist, hinterlegt Access die Schaltfl&auml;che mit einem Hintergrund wie hier beim Datenmakro <b>Nach Einf&uuml;gung<\/b>.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_003.png\" alt=\"Datenmakros &uuml;ber die Datenblattansicht verwalten\" width=\"649,559\" height=\"317,3715\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Datenmakros &uuml;ber die Datenblattansicht verwalten<\/span><\/b><\/p>\n<p>Wenn Sie auf eine der Schaltfl&auml;chen klicken, &ouml;ffnet Access die Entwurfsansicht f&uuml;r das Erstellen und Bearbeiten von Datenmakros. Diese steht aber in diesem Beitrag nicht im Mittelpunkt &#8211; daher schauen wir uns diese nun nicht im Detail an.<\/p>\n<h2>Per VBA auf die Datenmakros zugreifen<\/h2>\n<p>Nun m&ouml;chten wir herausfinden, wie wir per VBA auf die Datenmakros einer Tabelle beziehungsweise der kompletten Datenbank zugreifen k&ouml;nnen. Welches Werkzeug im VBA-Editor hilft uns weiter, etwas &uuml;ber die Befehle in Zusammenhang mit Makros herauszufinden Der Objektkatalog.<\/p>\n<p>Diesen &ouml;ffnen wir und suchen nach dem Schl&uuml;sselwort <b>Macro<\/b>. Hier finden wir zun&auml;chst einige <b>acCmd&#8230;<\/b>-Konstanten, die letztlich zum Ausf&uuml;hren der Ribbonbefehle per VBA dienen. Au&szlig;erdem entdecken wir allerdings auch ein paar weitere Elemente, die interessant sein k&ouml;nnten: besonders die Auflistung <b>AllMacros<\/b> (siehe Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_004.png\" alt=\"Befehle, welche die Zeichenkette Macro enthalten\" width=\"574,61\" height=\"509,6295\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Befehle, welche die Zeichenkette Macro enthalten<\/span><\/b><\/p>\n<p>Wir schauen uns einmal in einer kleinen Prozedur an, welches Ergebnis diese Auflistung liefert:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AlleMakros()\r\n     <span style=\"color:blue;\">Dim <\/span>mac<span style=\"color:blue;\"> As Object<\/span>\r\n     For Each mac In CurrentProject.AllMacros\r\n         <span style=\"color:blue;\">Debug.Print<\/span> TypeName(mac), mac.Name\r\n     <span style=\"color:blue;\">Next<\/span> mac\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Dies liefert allerdings kein Ergebnis, wenn Sie nur Datenmakros angelegt haben. Die Auflistung dient allein dem Zugriff auf die herk&ouml;mmlichen Makros, die auch im Navigationsbereich unter <b>Makros <\/b>angezeigt werden.<\/p>\n<p>Es gibt also in der Tat keine M&ouml;glichkeit, per VBA direkt auf die Datenmakros zuzugreifen. Also gehen wir einen kleinen Umweg.<\/p>\n<h2>Umweg &uuml;ber SaveAsText<\/h2>\n<p>Wir wissen, dass Datenmakros in Zusammenhang mit Tabellen gespeichert werden. Weiterhin wissen wir, dass es eine M&ouml;glichkeit gibt, Access-Objekte &uuml;ber die Anweisung <b>SaveAsText <\/b>auf der Festplatte zu speichern und etwa &uuml;ber einen Texteditor auf diese Dateien zuzugreifen. Also schauen wir uns diesen Befehl einmal genauer an. Dies gelingt etwa &uuml;ber die IntelliSense-Funktion im Direktbereich des VBA-Editors. Dort finden wir dann ganz unten in der Liste eine interessante Konstante, n&auml;mlich <b>acTableDataMacro <\/b>(siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_005.png\" alt=\"Die neue Konstante acTableDataMakro\" width=\"499,6607\" height=\"208,2697\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Die neue Konstante acTableDataMakro<\/span><\/b><\/p>\n<p>Auch f&uuml;r diese Konstante geben wir als zweiten Parameter den Namen des zu speichernden Objekts an sowie als dritten Parameter den Dateinamen, unter dem das Objekt gespeichert werden soll. Nach kurzem Experimentieren wird klar, dass wir f&uuml;r den zweiten Parameter den Tabellennamen angeben, dessen Datenmakros wir im Dateisystem speichern wollen.<\/p>\n<p>Also legen wir f&uuml;r die Tabelle <b>tblArtikel <\/b>einmal je ein Makro f&uuml;r die verschiedenen Typen an (das Ribbon sieht dann f&uuml;r diese Makros wie in Bild 6 aus).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_006.png\" alt=\"Die Eintr&auml;ge f&uuml;r die Datenmakros im Ribbon\" width=\"599,593\" height=\"155,6465\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Die Eintr&auml;ge f&uuml;r die Datenmakros im Ribbon<\/span><\/b><\/p>\n<p>Zus&auml;tzlich f&uuml;gen wir auch ein benanntes Makro zu der Tabelle hinzu, f&uuml;r das wir allerdings im Gegensatz zu den vorgegebenen Makros  einen Namen angeben m&uuml;ssen. Das ist logisch, denn es kann mehr als ein benanntes Makro je Tabelle geben.<\/p>\n<p>Danach rufen wir den folgenden Befehl auf, um den Code der Datenmakros auf der Festplatte zu speichern:<\/p>\n<pre>SaveAsText acTableDataMacro, \"tblArtikel\", Currentproject.Path & \"\tblArtikel_Makros.txt\"<\/pre>\n<p>Das Ergebnis sieht dann in der neu angelegten Datei <b>tblArtikel_Makros.txt <\/b>wie in Listing 1 aus. Hier sehen wir, dass es sich um eine XML-Datei handelt. Diese verwendet als Hauptobjekt das Element <b>DataMacros<\/b>. Darunter finden Sie einige Elemente namens <b>DataMacro<\/b>, die mit einem Attribut namens <b>Event <\/b>ausgestattet sind. Dieses gibt an, durch welches Ereignis das Datenmakro ausgel&ouml;st wird:<\/p>\n<pre>&lt;xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"&gt;\r\n&lt;DataMacros xmlns=\"http:\/\/schemas.microsoft.com\/office\/accessservices\/2009\/11\/application\"&gt;\r\n   &lt;DataMacro Event=\"AfterInsert\"&gt;\r\n     &lt;Statements&gt;\r\n       &lt;Comment&gt;Kommentar Nach Einf&uuml;gung&lt;\/Comment&gt;\r\n     &lt;\/Statements&gt;\r\n   &lt;\/DataMacro&gt;\r\n   &lt;DataMacro Event=\"AfterUpdate\"&gt;\r\n     &lt;Statements&gt;\r\n       &lt;Comment&gt;Kommentar Nach Aktualisierung&lt;\/Comment&gt;\r\n     &lt;\/Statements&gt;\r\n   &lt;\/DataMacro&gt;\r\n   &lt;DataMacro Event=\"AfterDelete\"&gt;\r\n     &lt;Statements&gt;\r\n       &lt;Comment&gt;Kommentar Nach L&ouml;schung&lt;\/Comment&gt;\r\n     &lt;\/Statements&gt;\r\n   &lt;\/DataMacro&gt;\r\n   &lt;DataMacro Event=\"BeforeChange\"&gt;\r\n     &lt;Statements&gt;\r\n       &lt;Comment&gt;Kommentar Vor &Auml;nderung&lt;\/Comment&gt;\r\n     &lt;\/Statements&gt;\r\n   &lt;\/DataMacro&gt;\r\n   &lt;DataMacro Event=\"BeforeDelete\"&gt;\r\n     &lt;Statements&gt;\r\n       &lt;Comment&gt;Kommentar Vor L&ouml;schung&lt;\/Comment&gt;\r\n     &lt;\/Statements&gt;\r\n   &lt;\/DataMacro&gt;\r\n   &lt;DataMacro Name=\"dmkBeispiel\"&gt;\r\n     &lt;Statements&gt;\r\n       &lt;Comment&gt;Kommentar Benanntes Makro&lt;\/Comment&gt;\r\n     &lt;\/Statements&gt;\r\n   &lt;\/DataMacro&gt;\r\n&lt;\/DataMacros&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Die in eine Textdatei exportieren Datenmakros<\/span><\/b><\/p>\n<ul>\n<li><b>AfterInsert<\/b>: Nach Einf&uuml;gung<\/li>\n<li><b>AfterUpdate<\/b>: Nach Aktualisierung<\/li>\n<li><b>AfterDelete<\/b>: Nach L&ouml;schung<\/li>\n<li><b>BeforeChange<\/b>: Vor &Auml;nderung<\/li>\n<li><b>BeforeDelete<\/b>: Vor L&ouml;schung<\/li>\n<\/ul>\n<p>Das ist aber nicht das einzige m&ouml;gliche Attribut. Genau genommen wird dieses nur f&uuml;r die Datenmakros eingesetzt, die durch ein Ereignis ausgel&ouml;st werden. F&uuml;r die anderen Makros von Tabellen, also die benannten Makros, gibt es das Attribut <b>Name<\/b>.<\/p>\n<p>Unterhalb der <b>DataMacro<\/b>-Elemente finden wir ein <b>Statements<\/b>-Element, das dann die eigentlichen Befehle enth&auml;lt. In unserem Beispiel haben wir f&uuml;r alle Makros einfach nur den Makrobefehl <b>Kommentar <\/b>eingef&uuml;gt.<\/p>\n<p>Hier finden dann auch die &uuml;brigen Befehle und Strukturen Platz, wobei bei den Strukturen noch untergeordnete Elemente integriert werden. Gleiches gilt f&uuml;r die Datenmakros.<\/p>\n<h2>Datenmakro analysieren<\/h2>\n<p>Wie aber nun k&ouml;nnen wir ermitteln, f&uuml;r welche Tabelle welche Datenmakros existieren und diese etwa im Direktfenster ausgeben Wir m&uuml;ssen tats&auml;chlich &uuml;ber den Umweg des Dateiexports auf die Festplatte gehen. Dort w&uuml;rden wir die so gespeicherte Datei dann mit der <b>Open<\/b>-Anweisung &ouml;ffnen und mit den Methoden der Bibliothek <b>Microsoft XML, v3.0 <\/b>analysieren.<\/p>\n<p>Diese Bibliothek f&uuml;gen Sie zun&auml;chst &uuml;ber den <b>Verweise<\/b>-Dialog hinzu (siehe Bild 7). Achtung: Mit der Version <b>v6.0 <\/b>funktioniert der nachfolgend angegebene VBA-Code nicht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_007.png\" alt=\"Hinzuf&uuml;gen eines Verweises auf die XML-Bibliothek\" width=\"424,7115\" height=\"334,8159\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Hinzuf&uuml;gen eines Verweises auf die XML-Bibliothek<\/span><\/b><\/p>\n<h2>Alle Tabellen durchlaufen<\/h2>\n<p>Danach bauen wir zun&auml;chst ein Grundger&uuml;st, mit dem wir alle Tabellen einer Datenbank durchlaufen. Dieses sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabellenAnalysieren()\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>tbl<span style=\"color:blue;\"> As <\/span>dao.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument60\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     For Each tbl In db.TableDefs\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> (<span style=\"color:blue;\">Left<\/span>(tbl.Name, 4) = \"MSys\")<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span>EnthaeltMakros(tbl.Name, objXML) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> \"Makros vorhanden in ''\"  & tbl.Name & \"''.\"\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> \"Keine Makros in ''\"  & tbl.Name & \"''.\"\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> tbl\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Damit durchlaufen wir alle Tabellen der Anwendung, deren Name nicht mit <b>MSys&#8230;<\/b> beginnt &#8211; also alle Tabellen au&szlig;er den Systemtabellen. Innerhalb der <b>If&#8230;Then<\/b>-Bedingung k&ouml;nnen wir dann den Aufruf einer weiteren Prozedur unterbringen, welche die Makros in eine Datei exportiert und in ein XML-Dokument einliest &#8211; in diesem Fall eine Funktion namens <b>EnthaeltMakros<\/b>.<\/p>\n<p>Diese soll den Wert <b>True <\/b>liefern, wenn eine Tabelle Datenmakros enth&auml;lt und <b>False<\/b>, wenn dies nicht der Fall ist.<\/p>\n<h2>Makros nach XML<\/h2>\n<p>Die Funktion <b>EnthaeltMakros <\/b>erwartet den Namen der zu untersuchenden Tabelle als Parameter sowie eine Variable des Typs <b>MSXML2.DOMDocument<\/b>. Aus diesen bildet sie zun&auml;chst einen Dateinamen, der aus dem Pfad zur aktuellen Datenbank, einem Backslash, dem Namen der Tabelle und der Dateiendung <b>.xml <\/b>besteht:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>EnthaeltMakros(strTabelle<span style=\"color:blue;\"> As String<\/span>,  objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument60)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strDateiname<span style=\"color:blue;\"> As String<\/span>\r\n     strDateiname = CurrentProject.Path & \"\"  & strTabelle & \".xml\"<\/pre>\n<p>Dann versuchen wir, bei deaktivierter Fehlerbehandlung die <b>SaveAsText<\/b>-Anweisung mit dem Namen der Tabelle f&uuml;r die zu exportierenden Datenmakros und dem Dateinamen als Parameter aufzurufen. Wenn die Tabelle keine Datenmakros enth&auml;lt, wird der Fehler mit der Nummer <b>2950 <\/b>ausgel&ouml;st (<b>Reservierter Fehler<\/b>). In diesem Fall soll die Funktion enden, ohne den Funktionswert auf <b>True <\/b>einzustellen:<\/p>\n<pre>     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     SaveAsText acTableDataMacro, strTabelle, strDateiname\r\n     <span style=\"color:blue;\">If <\/span>Err.Number = 2950<span style=\"color:blue;\"> Then<\/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;\">On Error GoTo<\/span> 0<\/pre>\n<p>Konnten die Datenmakros hingegen erfolgreich exportiert werden, erstellt die Funktion ein neues Objekt des Typs <b>DOMDocument60<\/b>, das wir im n&auml;chsten Schritt mit dem XML-Dokument aus der soeben mit <b>SaveAsText <\/b>angelegten Datei f&uuml;llen und danach den Inhalt des XML-Dokuments testweise im Direktbereich ausgeben:<\/p>\n<pre>     <span style=\"color:blue;\">Set<\/span> objXML = <span style=\"color:blue;\">New<\/span> MSXML2.DOMDocument60\r\n     objXML.Load strDateiname\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objXML.XML\r\n     EnthaeltMakros = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>In diesem Fall gibt die Funktion den Wert <b>True <\/b>zur&uuml;ck &#8211; und auch der Parameter <b>objXML <\/b>liefert das gew&uuml;nschte XML-Dokument.<\/p>\n<h2>XML-Dokument analysieren<\/h2>\n<p>In der aufrufenden Prozedur <b>TabellenAnalysieren <\/b>ersetzen wir nun die <b>Debug.Print<\/b>-Anweisung im <b>If<\/b>-Teil der <b>If&#8230;Then<\/b>-Bedingung durch den Aufruf der Prozedur <b>XMLAnalysieren<\/b>. Diesem stellen wir die Ausgabe des Tabellennamens voran. Dann &uuml;bergeben wir das mit <b>objXML <\/b>referenzierte XML-Dokument als Parameter, sodass die Prozedur nun wie folgt aussieht:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabellenAnalysieren()\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>tbl<span style=\"color:blue;\"> As <\/span>dao.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     For Each tbl In db.TableDefs\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> (<span style=\"color:blue;\">Left<\/span>(tbl.Name, 4) = \"MSys\")<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span>EnthaeltMakros(tbl.Name, objXML) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> \"Tabelle: \" & tbl.Name\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> String(<span style=\"color:blue;\">Len<\/span>(\"Tabelle: \"  & tbl.Name), \"=\")\r\n                 XMLAnalysieren objXML\r\n                 <span style=\"color:blue;\">Debug.Print<\/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;\">Next<\/span> tbl\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die dadurch aufgerufene Prozedur <b>XMLAnalysieren <\/b>finden Sie in Listing 2.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>XMLAnalysieren(objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument)\r\n     <span style=\"color:blue;\">Dim <\/span>objDataMacro<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMElement\r\n     <span style=\"color:blue;\">Dim <\/span>objAttribute<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMAttribute\r\n     For Each objDataMacro In objXML.selectNodes(\"DataMacros\/DataMacro\")\r\n         <span style=\"color:blue;\">Set<\/span> objAttribute = objDataMacro.selectSingleNode(\"@Event\")\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objAttribute Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"  Event: \" & objAttribute.nodeTypedValue\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> objAttribute = objDataMacro.selectSingleNode(\"@Name\")\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objAttribute Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> \"  Name: \" & objAttribute.nodeTypedValue\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> objDataMacro\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Diese Prozedur analysiert den Code der enthaltenen Makrodefinitionen anhand der Attribute.<\/span><\/b><\/p>\n<p>Die Prozedur erwartet das XML-Dokument als Parameter. Sie deklariert zwei Variablen: Eine f&uuml;r ein Element des Typs <b>Element <\/b>des XML-Dokuments und eines f&uuml;r ein <b>Attribut<\/b>-Element. Die erste verwendet sie als Laufvariable f&uuml;r eine <b>For Each<\/b>-Schleife &uuml;ber alle mit einer per <b>selectNodes <\/b>abgesetzten XPath-Abfrage. Die Abfrage lautet <b>DataMacros\/DataMacro <\/b>und liefert alle <b>DataMacro<\/b>-Elemente unterhalb des <b>DataMacros<\/b>-Elements. Das sind f&uuml;r unser obiges Beispiel sechs Elemente &#8211; die f&uuml;nf Daten-makros, die durch die verschiedenen Ereignisse ausgel&ouml;st werden, und ein benanntes Makro.<\/p>\n<p>Innerhalb der Schleife versucht die Prozedur, mit einer weiteren XPath-Abfrage, diesmal f&uuml;r das bereits in <b>objDataMacro <\/b>gespeicherte XML-Element des Typs <b>DataMacro<\/b>, das Attribut <b>Event <\/b>zu referenzieren. Um Attribute zu referenzieren, stellt man unter XPath dem Attributnamen das <b>@<\/b>-Zeichen voran.<\/p>\n<p>Wenn <b>objAttribute <\/b>danach nicht leer ist, wurde das Attribut gefunden und die Prozedur gibt den Wert des Attributs &uuml;ber die Eigenschaft <b>NodeTyped-Value <\/b>aus. Wurde kein Attribut namens <b>Event <\/b>gefunden, versucht die Prozedur im <b>Else<\/b>-Teil, auf die gleiche Art ein Attribut namens <b>Name <\/b>zu finden. Ist dieses vorhanden, gibt die Prozedur auch dessen Wert samt Attributnamen aus.<\/p>\n<p>Auf diese Weise durchl&auml;uft die Prozedur alle Elemente des Typs <b>DataMacro<\/b>. Wenn wir noch f&uuml;r eine weitere Tabelle namens <b>tblBestelldetails <\/b>ein Datenmakro hinzuf&uuml;gen, sieht die Ausgabe im Direktfenster wie folgt aus:<\/p>\n<pre>Tabelle: tblArtikel\r\n===================\r\n   Event: AfterInsert\r\n   Event: AfterUpdate\r\n   Event: AfterDelete\r\n   Event: BeforeChange\r\n   Event: BeforeDelete\r\n   Name: dmkBeispiel\r\nTabelle: tblBestelldetails\r\n==========================\r\n   Event: AfterInsert<\/pre>\n<h2>Datenmakros in Tabelle speichern<\/h2>\n<p>Wir wollen nun nicht weiter ins Detail gehen, was die in den Datenmakros enthaltenen Makroaktionen angeht, sondern eine M&ouml;glichkeit schaffen, die Tabellen und die enthaltenen Makros &uuml;bersichtlich in der Datenbank anzuzeigen, damit der Benutzer diese auf die Schnelle &ouml;ffnen und bearbeiten kann. Dazu ben&ouml;tigen wir zwei Tabellen zum Speichern der Tabellennamen und der enthaltenen Datenmakros. Auf diese greifen wir dann sp&auml;ter von einer Kombination aus Formular und Bericht zu.<\/p>\n<p><!--30percent--><\/p>\n<p>Dazu legen wir zwei Tabellen an. Die erste hei&szlig;t <b>tblTabellen <\/b>und speichert die Namen der Tabellen, die Datenmakros enthalten. Sie enth&auml;lt ein Prim&auml;rschl&uuml;sselfeld namens <b>TabelleID <\/b>und ein Textfeld namens <b>Tabelle<\/b>, welches den Namen der Tabelle speichert. F&uuml;r dieses Feld haben wir einen eindeutigen Index angelegt (siehe Bild 8).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_008.png\" alt=\"Tabelle zum Speichern der Tabellennamen\" width=\"599,593\" height=\"350,2295\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Tabelle zum Speichern der Tabellennamen<\/span><\/b><\/p>\n<p>Die zweite Tabelle hei&szlig;t <b>tblDatenmakros<\/b>. Das Prim&auml;rschl&uuml;sselfeld nennen wir logischerweise <b>DatenmakroID<\/b>. Aber wie speichern wir die Informationen aus den beiden Attributen <b>Event <\/b>und <b>Name<\/b> Wir legen in einem Nachschlagefeld namens <b>DatenmakrotypID <\/b>den Typ des Datenmakros fest, der einen der folgenden sechs Werte annehmen k&ouml;nnen soll:<\/p>\n<ul>\n<li><b>AfterInsert<\/b><\/li>\n<li><b>AfterUpdate<\/b><\/li>\n<li><b>AfterDelete<\/b><\/li>\n<li><b>BeforeChange<\/b><\/li>\n<li><b>BeforeDelete<\/b><\/li>\n<li><b>NamedDataMacro<\/b><\/li>\n<\/ul>\n<p>Diese Werte speichern wir in der Lookuptabelle <b>tblDatenmakrotypen<\/b>, die im Entwurf wie in Bild 9 aussieht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_009.png\" alt=\"Tabelle zum Speichern der Datenmakrotypen\" width=\"599,593\" height=\"339,1727\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Tabelle zum Speichern der Datenmakrotypen<\/span><\/b><\/p>\n<p>Jetzt fehlt noch ein Feld, das den Namen des Datenmakros speichert. Dieses nennen wir Makroname. Es soll f&uuml;r Datenmakros, die durch Ereignisse ausgel&ouml;st werden, den gleichen Wert erhalten, der auch &uuml;ber das Nachschlagefeld ausgew&auml;hlt wurde, also <b>Vor &Auml;nderung<\/b>, <b>Vor L&ouml;schung <\/b>und so weiter. F&uuml;r die benannten Makros hinterlegen wir den angegebenen Namen. Schlie&szlig;lich geben wir in einem weiteren Nachschlagefeld namens <b>TabelleID <\/b>noch an, zu welcher Tabelle das Datenmakro geh&ouml;rt. Der Entwurf der Tabelle <b>tblDatenmakros <\/b>sieht dann wie in Bild 10 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_010.png\" alt=\"Tabelle zum Speichern der Datenmakro-Eigenschaften\" width=\"599,593\" height=\"387,9169\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Tabelle zum Speichern der Datenmakro-Eigenschaften<\/span><\/b><\/p>\n<p>Die Beziehungen der Tabellen haben wir in Bild 11 abgebildet.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_011.png\" alt=\"Beziehung der beteiligten Tabellen\" width=\"424,7115\" height=\"291,9233\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Beziehung der beteiligten Tabellen<\/span><\/b><\/p>\n<h2>Tabellen mit den Datenmakros f&uuml;llen<\/h2>\n<p>Nun passen wir die Prozeduren <b>TabellenAnalysieren <\/b>und <b>XML-Analysieren <\/b>noch so an, dass die ermittelten Daten nicht im Direktbereich des VBA-Editors landen, sondern in den soeben erstellten Tabellen. Die Frage hierbei ist noch, ob wir nur die Tabellen in die Tabelle <b>tblTabellen <\/b>schreiben sollen, die bereits &uuml;ber Datenmakros verf&uuml;gen, oder ob wir dort alle Tabellen eintragen sollen. Das w&auml;re sinnvoll, wenn wir in unserer noch zu erstellenden Benutzeroberfl&auml;che nicht nur per Klick den Entwurf eines Makros &ouml;ffnen, sondern auch noch neue Datenmakros anlegen wollen. Wir belassen es zun&auml;chst bei den Tabellen, die bereits Datenmakros enthalten.<\/p>\n<p>Dazu haben wir die Prozedur <b>TabellenAnalysieren <\/b>wie in Listing 3 angepasst. Sie l&ouml;scht zun&auml;chst alle Eintr&auml;ge der Tabelle <b>tblTabellen<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabellenAnalysieren()\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>tbl<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument\r\n     <span style=\"color:blue;\">Dim <\/span>lngTabelleID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     db.Execute \"DELETE FROM tblTabellen\", dbFailOnError\r\n     For Each tbl In db.TableDefs\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> (<span style=\"color:blue;\">Left<\/span>(tbl.Name, 4) = \"MSys\")<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span>EnthaeltMakros(tbl.Name, objXML) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 db.Execute \"INSERT INTO tblTabellen(Tabelle) VALUES(''\" & tbl.Name & \"'')\", dbFailOnError\r\n                 lngTabelleID = db.OpenRecordset(\"SELECT @@IDENTITY\", dbOpenDynaset).Fields(0)\r\n                 XMLAnalysieren objXML, lngTabelleID, db\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> tbl\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Die neue Version der Prozedur TabellenAnalysieren schreibt direkt die Tabellen in tblTabellen.<\/span><\/b><\/p>\n<p>Damit dies ausreicht, um auch die mit diesen Eintr&auml;gen verkn&uuml;pften Datens&auml;tze der Tabelle <b>tblDatenmakros <\/b>zu l&ouml;schen, haben wir f&uuml;r die Beziehung zwischen diesen beiden Tabellen referenzielle Integrit&auml;t mit L&ouml;schweitergabe definiert (siehe Bild 12).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_012.png\" alt=\"Referenzielle Integrit&auml;t mit L&ouml;schweitergabe\" width=\"424,7115\" height=\"263,8209\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Referenzielle Integrit&auml;t mit L&ouml;schweitergabe<\/span><\/b><\/p>\n<p>Die Prozedur durchl&auml;uft nach wie vor alle benutzerdefinierten Tabellen der Datenbank und pr&uuml;ft mit der Funktion <b>EnthaeltMakros<\/b>, ob die Tabelle Datenmakros enth&auml;lt. In diesem Fall schreibt sie die Tabelle als neuen Datensatz in die Tabelle <b>tblTabellen <\/b>und ermittelt den Prim&auml;rschl&uuml;sselwert des neuen Datensatzes. Damit ausgestattet, ruft sie die Prozedur <b>XMLAnalysieren <\/b>auf.<\/p>\n<p>Diese Prozedur erwartet neben dem Verweis auf das XML-Dokument nun noch zwei weitere Parameter: den Prim&auml;rschl&uuml;sselwert des durch die Prozedur <b>TabellenAnalysieren <\/b>hinzugef&uuml;gten Datensatzes und den Verweis auf das <b>Database<\/b>-Objekt der aktuellen Datenbank (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>XMLAnalysieren(objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument, lngTabelleID<span style=\"color:blue;\"> As Long<\/span>, db<span style=\"color:blue;\"> As <\/span>DAO.Database)\r\n     <span style=\"color:blue;\">Dim <\/span>objDataMacro<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMElement\r\n     <span style=\"color:blue;\">Dim <\/span>objAttribute<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMAttribute\r\n     <span style=\"color:blue;\">Dim <\/span>lngDatenmakrotypID<span style=\"color:blue;\"> As Long<\/span>\r\n     For Each objDataMacro In objXML.selectNodes(\"DataMacros\/DataMacro\")\r\n         <span style=\"color:blue;\">Set<\/span> objAttribute = objDataMacro.selectSingleNode(\"@Event\")\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objAttribute Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n             lngDatenmakrotypID = DLookup(\"DatenmakrotypID\", \"tblDatenmakrotypen\", \"Datenmakrotyp = ''\" _\r\n                 & objAttribute.nodeTypedValue & \"''\")\r\n             db.Execute \"INSERT INTO tblDatenmakros(DatenmakrotypID, Makroname, TabelleID) VALUES(\" _\r\n                 & lngDatenmakrotypID & \", ''\" & objAttribute.nodeTypedValue & \"'', \" & lngTabelleID & \")\", dbFailOnError\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> objAttribute = objDataMacro.selectSingleNode(\"@Name\")\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objAttribute Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                 lngDatenmakrotypID = DLookup(\"DatenmakrotypID\", \"tblDatenmakrotypen\", _\r\n                     \"Datenmakrotyp = ''NamedDataMacro''\")\r\n                 db.Execute \"INSERT INTO tblDatenmakros(DatenmakrotypID, Makroname, TabelleID) VALUES(\" _\r\n                     & lngDatenmakrotypID & \", ''\" & objAttribute.nodeTypedValue & \"'', \" & lngTabelleID & \")\", dbFailOnError\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> objDataMacro\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Die neue Version von XMLAnalysieren hat neue Parameter und tr&auml;gt die gefundenen Daten gleich in die Tabelle tblDatenmakros ein.<\/span><\/b><\/p>\n<p>Sie durchl&auml;uft wieder alle <b>DataMacro<\/b>-Elemente des XML-Dokuments und pr&uuml;ft, ob diese das Attribut <b>Event <\/b>enthalten. Ist das der Fall, ermittelt sie aus der Tabelle <b>tblDatenmakrotypen <\/b>den Prim&auml;rschl&uuml;sselwert zu dem Eintrag, der das passende Event enth&auml;lt. Diesen schreibt sie dann in der folgenden <b>INSERT INTO<\/b>-Anweisung zusammen mit dem Wert des Attributs f&uuml;r das Feld <b>Makroname <\/b>und dem Prim&auml;rschl&uuml;sselwert der Tabelle <b>tblTabellen <\/b>aus <b>lngTabelleID <\/b>in die Tabelle <b>tblDatenmakros<\/b>.<\/p>\n<p>Im <b>Else<\/b>-Zweig untersucht die Prozedur dann wieder, ob das Element ein Attribut namens <b>Name <\/b>enth&auml;lt. In diesem Fall f&uuml;gt sie einen entsprechenden Eintrag f&uuml;r ein benanntes Daten-makro zur Tabelle <b>tblDatenmakros <\/b>hinzu. Auf diese Weise durchl&auml;uft sie alle Datenmakros der Tabelle.<\/p>\n<p>Das Ergebnis sieht dann in der Tabelle <b>tblDatenmakros <\/b>etwa wie in Bild 13 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_013.png\" alt=\"Ergebnis unserer Beispieldatenbank\" width=\"424,7115\" height=\"201,9258\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 13: Ergebnis unserer Beispieldatenbank<\/span><\/b><\/p>\n<h2>Darstellung per Berichtsansicht<\/h2>\n<p>Wie wollen wir die Tabellen und die enthaltenen Daten-makros nun darstellen Die oben verwendete hierarchische Darstellung w&auml;re schon &uuml;bersichtlich, aber diese kann man in herk&ouml;mmlichen Formularen nicht darstellen, wenn man gleichzeitig noch Steuer-elemente etwa zum &Ouml;ffnen des Datenmakros hinzuf&uuml;gen m&ouml;chte.<\/p>\n<p>Aber seit ein paar Access-Ausgaben gibt es ja die Berichtsansicht, in der man Daten wie in einem Bericht hierarchisch darstellen, aber auch Schaltfl&auml;chen einf&uuml;gen kann. Diese Berichte kann man auch innerhalb eines Unterformular-Steuerelements in einem Formular anzeigen.<\/p>\n<p>Als Erstes stellen wir eine Abfrage zusammen, die wir als Datensatzquelle f&uuml;r den Bericht verwenden wollen. Diese Abfrage enth&auml;lt die drei Tabellen <b>tblTabellen<\/b>, <b>tblDaten-makros <\/b>und <b>tblDatenmakrotypen<\/b>. Aus diesen Tabellen f&uuml;gen wir die Felder wie in Bild 14 zum Entwurfsraster hinzu.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_014.png\" alt=\"Entwurf der Abfrage qryDatenmakrosReport\" width=\"649,559\" height=\"341,2608\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 14: Entwurf der Abfrage qryDatenmakrosReport<\/span><\/b><\/p>\n<h2>Bericht erstellen<\/h2>\n<p>Diese Abfrage stellen wir dann auch gleich nach dem &Ouml;ffnen eines neuen, leeren Berichts als Wert der Eigenschaft <b>Datensatzquelle <\/b>ein. Den Bericht speichern wir unter dem Namen <b>rptDatenmakros<\/b>.<\/p>\n<p>Dann f&uuml;gen wir dem Bericht eine Gruppierung hinzu. F&uuml;r diese legen wir unter <b>Gruppieren nach <\/b>zun&auml;chst das Feld <b>TabelleID <\/b>fest (siehe Bild 15).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_015.png\" alt=\"Hinzuf&uuml;gen einer Gruppierung nach dem Feld TabelleID\" width=\"649,559\" height=\"210,2071\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 15: Hinzuf&uuml;gen einer Gruppierung nach dem Feld TabelleID<\/span><\/b><\/p>\n<p>Dann klicken wir im Bereich zum Definieren der Gruppierung auf <b>Mehr<\/b>, um alle Eigenschaften der Gruppierung anzuzeigen. Die dort vorhandenen Einstellungen k&ouml;nnen wir zun&auml;chst beibehalten (siehe Bild 16). Uns reicht ein Kopfzeilenbereich, in dem wir den Namen der Tabelle eintragen, einen Fu&szlig;zeilenbereich ben&ouml;tigen wir nicht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_016.png\" alt=\"Einstellungen f&uuml;r die Gruppierung\" width=\"649,559\" height=\"159,0757\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 16: Einstellungen f&uuml;r die Gruppierung<\/span><\/b><\/p>\n<p>Danach wechseln wir zum Ribbon-Bereich <b>Entwurf|Tools <\/b>und klicken dort auf <b>Vorhandene Felder hinzuf&uuml;gen<\/b>, um die Feldliste zu aktivieren. Das Feld <b>Tabelle <\/b>ziehen wir in den Bereich <b>TabelleID &#8211; Kopfbereich<\/b>.<\/p>\n<p>Anschlie&szlig;end passen wir die Schriftart ein wenig an (gr&ouml;&szlig;er und schwarz) und f&uuml;gen &uuml;ber und unter dem Feld <b>Tabelle <\/b>jeweils eine horizontale Linie ein. Danach f&uuml;gen wir das Feld <b>Makroname <\/b>in den Detailbereich des Berichtsentwurfs. Das Bezeichnungsfeld schneiden wir mit <b>Strg + X <\/b>aus, markieren den Kopfbereich der Gruppe f&uuml;r das Feld <b>TabelleID <\/b>und f&uuml;gen das Bezeichnungsfeld dort mit <b>Strg + C <\/b>wieder ein. Au&szlig;erdem richten wir die Elemente wie in Bild 17 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_017.png\" alt=\"Entwurf des Berichts rptDatenmakros\" width=\"649,559\" height=\"280,0557\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 17: Entwurf des Berichts rptDatenmakros<\/span><\/b><\/p>\n<p>Wechseln wir nun in die Berichtsansicht, erhalten wir den Bericht aus Bild 18. Inhaltlich ist hier schon alles korrekt, allerdings wollen wir noch ein paar optische Anpassungen vornehmen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_018.png\" alt=\"Erster Blick auf den Bericht rptDatenmakros\" width=\"649,559\" height=\"408,9026\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 18: Erster Blick auf den Bericht rptDatenmakros<\/span><\/b><\/p>\n<p>Zum Beispiel entfernen wir f&uuml;r alle Felder die Rahmen, was wir durch Einstellen der Eigenschaft <b>Rahmenart <\/b>auf <b>Transparent <\/b>erreichen. Zuvor haben wir dazu alle Steuer-elemente mit der Tastenkombination <b>Strg + A <\/b>markiert.<\/p>\n<p>Au&szlig;erdem wollen wir keinen alternierenden Hintergrund. Dazu stellen wir die Eigenschaft <b>Alternative Hintergrundfarbe <\/b>sowohl f&uuml;r den Gruppenkopf-Bereich als auch f&uuml;r den Detailbereich auf den gleichen Wert ein, den die Eigenschaft <b>Hintergrundfarbe <\/b>aufweist &#8211; in unserem Fall <b>Hintergrund 1<\/b>.<\/p>\n<p>Das Ergebnis sieht schon besser aus, wie Bild 19 zeigt. Nun wollen wir noch eine Schaltfl&auml;che f&uuml;r jeden Eintrag hinzuf&uuml;gen, &uuml;ber die wir die angezeigten Datenmakros in der Entwurfsansicht anzeigen k&ouml;nnen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_019.png\" alt=\"So sieht der Bericht schon besser aus.\" width=\"349,7625\" height=\"337,3027\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 19: So sieht der Bericht schon besser aus.<\/span><\/b><\/p>\n<p>Dazu f&uuml;gen wir dem Bericht links neben den Eintr&auml;gen im Detailbereich eine Schaltfl&auml;che hinzu. F&uuml;r diese wollen wir zun&auml;chst ein Icon definieren. Dazu markieren Sie die neu hinzugef&uuml;gte Schaltfl&auml;che und klicken dann im Ribbon auf den Befehl <b>Entwurf|Steuerelemente|Bild einf&uuml;gen|Durchsuchen<\/b>. W&auml;hlen Sie im nun erscheinenden Dialog die gew&uuml;nschte Bilddatei aus. Danach stellen wir noch die Eigenschaft <b>Hintergrundfarbe <\/b>auf <b>Transparent <\/b>ein. Den gleichen Wert legen wir auch noch f&uuml;r die Eigenschaft <b>Rahmenart <\/b>fest.<\/p>\n<p>Danach sieht der Bericht in der Berichtsansicht etwa wie in Bild 20 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_020.png\" alt=\"Berichtsansicht mit Schaltfl&auml;chen\" width=\"424,7115\" height=\"321,0418\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 20: Berichtsansicht mit Schaltfl&auml;chen<\/span><\/b><\/p>\n<p>Nun ben&ouml;tigen wir noch eine Ereignisprozedur, die beim Anklicken des Bearbeiten-Symbols ausgel&ouml;st wird. F&uuml;r die meisten F&auml;lle, n&auml;mlich f&uuml;r alle durch Ereignisse ausgel&ouml;sten Datenmakros, kommen wir mit der folgenden Prozedur aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdBearbeiten_Click()\r\n     DoCmd.OpenTable Me!Tabelle\r\n     Select Case Me!Datenmakrotyp\r\n         <span style=\"color:blue;\">Case <\/span>\"AfterInsert\"\r\n             RunCommand acCmdAddDataMacroAfterInsert\r\n         <span style=\"color:blue;\">Case <\/span>\"AfterUpdate\"\r\n             RunCommand acCmdAddDataMacroAfterUpdate\r\n         <span style=\"color:blue;\">Case <\/span>\"AfterDelete\"\r\n             RunCommand acCmdAddDataMacroAfterDelete\r\n         <span style=\"color:blue;\">Case <\/span>\"BeforeChange\"\r\n             RunCommand acCmdAddDataMacroBeforeChange\r\n         <span style=\"color:blue;\">Case <\/span>\"BeforeDelete\"\r\n             RunCommand acCmdAddDataMacroBeforeDelete\r\n         <span style=\"color:blue;\">Case <\/span>\"NamedDataMacro\"\r\n             ''\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Damit die Prozedur auf das Feld <b>Datenmakrotyp<\/b> zugreifen kann, das zwar in der Datensatzquelle vorhanden, aber noch nicht an ein Steuer-element gebunden ist, m&uuml;ssen wir dieses noch zum Detailbereich hinzuf&uuml;gen.<\/p>\n<p>Da wir es nicht anzeigen wollen, stellen wir seine Eigenschaft <b>Sichtbar <\/b>auf <b>Nein <\/b>ein.<\/p>\n<p>In der Prozedur pr&uuml;fen wir, welcher Wert in der Tabelle <b>tblDaten-makrotypen <\/b>f&uuml;r das aktuelle Makro hinterlegt ist und rufen in Abh&auml;ngigkeit davon die <b>RunCommand<\/b>-Anweisung mit einer der Konstanten <b>acCmdAddDataMacroAfterInsert<\/b>, <b>acCmdAddDataMacroAfterUpdate<\/b>, <b>acCmdAddDataMacroAfterDelete<\/b>, <b>acCmdAddDataMacroBeforeChange <\/b>oder <b>acCmdAddDataMacroBeforeDelete <\/b>auf.<\/p>\n<p>Bei den benannten Datenmakros gibt es jedoch keine auf einfache Art aufzurufende Methode, die das benannte Datenmakro &ouml;ffnen w&uuml;rde. Es gibt zwar die Konstante <b>acCmdAddNamedDataMacro<\/b>, aber diese &ouml;ffnet lediglich ein neues, leeres Datenmakro f&uuml;r die entsprechende Tabelle. Davon ab gibt es selbst im Internet aktuell keine weiteren Hinweise zu dieser Konstanten und wie man damit ein bestehendes Datenmakro &ouml;ffnen k&ouml;nnte. <\/p>\n<p>Das ist auch nicht verwunderlich, denn wir k&ouml;nnen die benannten Datenmakros auch nur &uuml;ber den Ribbon-Eintrag mit dem Namen des benannten Datenmakros unterhalb von <b>Tabelle|Benannte Makros|Benannte Makros|Benannte Makros bearbeiten <\/b>&ouml;ffnen (siehe Bild 21) &#8211; es gibt also keine passende <b>RunCommand<\/b>-Konstante. Wir k&ouml;nnen also h&ouml;chstens mit der Konstanten <b>acCmdAddNamedDataMacro <\/b>ein neues Datenmakro anlegen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_021.png\" alt=\"Benannte Datenmakros k&ouml;nnen nur auf diese Weise ge&ouml;ffnet werden.\" width=\"700\" height=\"218,4673\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 21: Benannte Datenmakros k&ouml;nnen nur auf diese Weise ge&ouml;ffnet werden.<\/span><\/b><\/p>\n<h2>Datenmakros anlegen<\/h2>\n<p>Wenn kein Datenmakro f&uuml;r ein bestimmtes Ereignis vorhanden ist, wollen wir dieses neu anlegen und dann direkt bearbeiten k&ouml;nnen. Nun listen wir in dem Bericht in der Berichtsansicht allerdings nur die bereits vorhandenen Datenmakros auf.<\/p>\n<p>Wie k&ouml;nnen wir ein nicht vorhandenes Datenmakro neu anlegen, ohne dass wir jeweils einen Platzhalter-Eintrag f&uuml;r jedes Datenmakro anzeigen m&uuml;ssen und somit vorerst Platz sparen <\/p>\n<p>Dazu f&uuml;gen wir dem Bericht im Entwurf eine neue Schaltfl&auml;che mit einem <b>Hinzuf&uuml;gen<\/b>-Symbol hinzu, und zwar im Kopfbereich neben der &Uuml;berschrift <b>Datenmakros<\/b> (siehe Bild 22). Bei der Gelegenheit f&uuml;gen wir auch gleich noch eine neue Schaltfl&auml;che zum L&ouml;schen eines Datenmakros ein, und zwar rechts neben der Schaltfl&auml;che zum Bearbeiten eines Datenmakros.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_022.png\" alt=\"Neue Schaltfl&auml;chen im Berichtsentwurf\" width=\"499,6607\" height=\"256,7155\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 22: Neue Schaltfl&auml;chen im Berichtsentwurf<\/span><\/b><\/p>\n<p>F&uuml;r die neue Schaltfl&auml;che <b>cmdNeuesDatenmakro <\/b>hinterlegen wir die folgende Ereignisprozedur, mit der wir das Formluar <b>frmNeuesDatenmakro <\/b>als modalen Dialog &ouml;ffnen und dabei den Wert des Feldes <b>TabelleID <\/b>&uuml;bergeben:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdNeuesDatenmakro_Click()\r\n     DoCmd.OpenForm \"frmNeuesDatenmakro\", _\r\n         WindowMode:=acDialog, OpenArgs:=Me!TabelleID\r\n     <span style=\"color:blue;\">If <\/span>IstFormularGeoeffnet(\"frmNeuesDatenmakro\")<span style=\"color:blue;\"> Then<\/span>\r\n         DoCmd.Close acForm, \"frmNeuesDatenmakro\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     TabellenAnalysieren\r\n     Me.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Anschlie&szlig;end pr&uuml;ft die Prozedur, ob das Formular noch ge&ouml;ffnet ist. Es kann sein, dass wir dieses unsichtbar schalten (warum, erfahren Sie weiter unten). In diesem Fall soll es auch noch korrekt geschlossen werden.<\/p>\n<p>Au&szlig;erdem rufen wir die Prozedur <b>TabellenAnalysieren <\/b>erneut auf, um das neue Datenmakro auch in die Tabelle einzuf&uuml;gen. Schlie&szlig;lich aktualisieren wir die Daten des Berichts mit der Requery-Methode.<\/p>\n<p>Das so ge&ouml;ffnete Formular soll wie in Bild 23 aussehen. Es enth&auml;lt ein Kombinationsfeld namens <b>cboDatenmakrotyp<\/b>, mit dem der Benutzer ausw&auml;hlen soll, welchen Typ das neue Datenmakro hat. Dazu weisen wir diesem Kombinationsfeld per VBA beim &Ouml;ffnen eine Datensatzherkunft zu, welche den mit dem &Ouml;ffnungsargument &uuml;bergebenen Wert f&uuml;r das Feld <b>TabelleID <\/b>ber&uuml;cksichtigt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_023.png\" alt=\"Formular zum Ausw&auml;hlen eines neu zu erstellenden Daten-makros\" width=\"424,7115\" height=\"205,0014\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 23: Formular zum Ausw&auml;hlen eines neu zu erstellenden Daten-makros<\/span><\/b><\/p>\n<p>Dies erledigt die Prozedur, die wir f&uuml;r das Ereignis <b>Beim Laden <\/b>des Formulars hinterlegen. Zuvor deklarieren wir im allgemeinen Teil des Klassenmoduls des Formulars noch die folgende Variable:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>lngTabelleID<span style=\"color:blue;\"> As Long<\/span><\/pre>\n<p>Die Prozedur <b>Form_Load <\/b>f&uuml;llt dann diese Variable mit dem &Ouml;ffnungsparameter aus <b>Me.OpenArgs<\/b> (siehe Listing 5).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     lngTabelleID = Me.OpenArgs\r\n     Me!cboDatenmakrotypID.RowSource = \"SELECT * FROM tblDatenmakrotypen WHERE DatenmakrotypID NOT IN (\" _\r\n         & \"SELECT DatenmakrotypID FROM tblDatenmakros WHERE TabelleID = \" & lngTabelleID & \" AND NOT DatenmakrotypID \" _\r\n         & \"IN (SELECT DatenmakrotypID FROM tblDatenmakrotypen WHERE Datenmakrotyp = ''NamedDataMacro''))\"\r\n     Me!cboDatenmakrotypID = Me!cboDatenmakrotypID.ItemData(0)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: F&uuml;llen des Kombinationsfeldes beim &Ouml;ffnen des Formulars<\/span><\/b><\/p>\n<p>Danach weist sie der Eigenschaft <b>RowSource <\/b>eine etwas komplizierter aussehende SQL-Anweisung zu. F&uuml;r einen Aufruf &uuml;ber die Schaltfl&auml;che <b>cmdNeuesDatenmakro <\/b>der Tabelle <b>tblArtikel <\/b>sieht die Abfrage etwa wie folgt aus:<\/p>\n<pre>SELECT * FROM tblDatenmakrotypen \r\n   WHERE DatenmakrotypID NOT IN (\r\n     SELECT DatenmakrotypID FROM tblDatenmakros \r\n     WHERE TabelleID = 3 AND NOT DatenmakrotypID IN (\r\n         SELECT DatenmakrotypID FROM tblDatenmakrotypen\r\n         WHERE Datenmakrotyp = ''NamedDataMacro''\r\n     )\r\n   )<\/pre>\n<p>Die Abfrage enth&auml;lt eine Unterabfrage, die wiederum eine Unterabfrage enth&auml;lt. Die erste Unterabfrage liefert alle Datens&auml;tze, deren Werte im Feld <b>DatenmakrotypID <\/b>der Datens&auml;tze der Tabelle <b>tblDatenmakros <\/b>f&uuml;r die Tabelle <b>tblArtikel <\/b>enthalten sind. Damit schlie&szlig;en wir alle Datens&auml;tze der Tabelle <b>tblDatenmakrotypen <\/b>aus, f&uuml;r die es bereits ein Datenmakro gibt. Allerdings wollen wir immer das Datenmakro mit dem Datenmakrotyp <b>NamedDataMacro <\/b>anzeigen, da ja mehrere benannte Datenmakros f&uuml;r eine Tabelle hinterlegt werden k&ouml;nnen. Also schlie&szlig;en wir aus der ersten Unterabfrage mit einer weiteren Unterabfrage und der Klausel <b>NOT IN <\/b>alle Eintr&auml;ge aus, deren Daten-makrotyp <b>NamedDataMacro <\/b>lautet &#8211; und f&uuml;gen diese so wieder zur Hauptabfrage hinzu.<\/p>\n<p>Schlie&szlig;lich stellen wir das Kombinationsfeld noch so ein, dass es den ersten Datensatz der Datensatzherkunft anzeigt. Damit erhalten wir, wenn wir etwa auf die Schaltfl&auml;che <b>Neues Datenmakro <\/b>f&uuml;r die Tabelle <b>tblBestelldetails <\/b>klicken, das Formular mit den Kombinationsfeld-Eintr&auml;gen wie in Bild 24.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_05\/pic_1203_024.png\" alt=\"Berichtsansicht Popup-Formular\" width=\"549,6265\" height=\"422,0839\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 24: Berichtsansicht Popup-Formular<\/span><\/b><\/p>\n<h2>Neues Datenmakro &ouml;ffnen<\/h2>\n<p>Damit kann der Benutzer nun den Typ des neu zu erstellenden Datenmakros festlegen und auf eine der beiden Schaltfl&auml;chen <b>cmdAnlegen <\/b>oder <b>cmdAbbrechen <\/b>klicken. Die Schaltfl&auml;che <b>cmdAbbrechen <\/b>l&ouml;st schlicht die folgende Prozedur aus und schlie&szlig;t damit das Formular ohne weitere Aktionen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAbbrechen_Click()\r\n     DoCmd.Close acForm, Me.Name\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Schaltfl&auml;che <b>cmdAnlegen <\/b>l&ouml;st die Prozedur aus Listing 6 aus.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAnlegen_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strTabelle<span style=\"color:blue;\"> As String<\/span>\r\n     strTabelle = DLookup(\"Tabelle\", \"tblTabellen\", \"TabelleID = \" & lngTabelleID)\r\n     Me.Visible = <span style=\"color:blue;\">False<\/span>\r\n     DoCmd.OpenTable strTabelle\r\n     Select Case Me!cboDatenmakrotypID.Column(1)\r\n         <span style=\"color:blue;\">Case <\/span>\"AfterInsert\"\r\n             RunCommand acCmdAddDataMacroAfterInsert\r\n         <span style=\"color:blue;\">Case <\/span>\"AfterUpdate\"\r\n             RunCommand acCmdAddDataMacroAfterUpdate\r\n         <span style=\"color:blue;\">Case <\/span>\"AfterDelete\"\r\n             RunCommand acCmdAddDataMacroAfterDelete\r\n         <span style=\"color:blue;\">Case <\/span>\"BeforeChange\"\r\n             RunCommand acCmdAddDataMacroBeforeChange\r\n         <span style=\"color:blue;\">Case <\/span>\"BeforeDelete\"\r\n             RunCommand acCmdAddDataMacroBeforeDelete\r\n         <span style=\"color:blue;\">Case <\/span>\"NamedDataMacro\"\r\n             RunCommand acCmdAddNamedDataMacro\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Anlegen neuer Datenmakros<\/span><\/b><\/p>\n<p>Diese Prozedur liest zun&auml;chst den Tabellennamen zu der Tabelle mit dem Prim&auml;rschl&uuml;sselwert aus <b>lngTabelleID <\/b>ein. Dann stellt sie die Eigenschaft <b>Visible <\/b>des Formulars auf <b>False <\/b>ein.<\/p>\n<p>Warum das Weil wir sonst ein Patt zwischen dem als modalen Dialog ge&ouml;ffneten Diagramm und dem anschlie&szlig;end ge&ouml;ffneten Datenmakroentwurf f&uuml;r das neue Datenmakro erzeugen &#8211; beide blockieren sich dann gegenseitig.<\/p>\n<p>Anschlie&szlig;end &ouml;ffnen wir mit der <b>OpenTable<\/b>-Anweisung zuerst die Tabelle, f&uuml;r die Sie das Datenmakro anlegen wollen. Dann rufen wir mit der <b>RunCommand<\/b>-Anweisung und der entsprechenden Konstante f&uuml;r den gew&auml;hlten Eintrag des Kombinationsfeldes den Entwurf eines neuen, leeren Datenmakros auf.<\/p>\n<p>Nachdem Sie das Datenmakro erstellt, gespeichert und geschlossen haben, werden die &uuml;brigen Codezeilen der aufrufenden Prozedur <b>cmdNeuesDatenmakro_Click <\/b>ausgef&uuml;hrt. Beim Erstellen eines neuen benannten Datenmakro m&uuml;ssen Sie beim Speichern &uuml;brigens noch den Namen f&uuml;r das Makro angeben, da jede Tabelle mehrere benannte Datenmakros enthalten kann.<\/p>\n<h2>Datenmakros l&ouml;schen<\/h2>\n<p>Und auch das L&ouml;schen von Datenmakros ist m&ouml;glich. Das gelingt sogar f&uuml;r benannte Datenmakros &#8211; aber auch nur, weil wir dazu einen inoffiziellen Weg nutzen.<\/p>\n<p>Die Schaltfl&auml;che <b>cmdLoeschen <\/b>haben wir ja bereits weiter oben zum Bericht <b>rptDatenmakros <\/b>hinzugef&uuml;gt. Diese l&ouml;st die Ereignisprozedur aus Listing 7 aus.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdLoeschen_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strTabelle<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strDateiname<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strMakroname<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument\r\n     <span style=\"color:blue;\">Dim <\/span>objDataMacros<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMElement\r\n     <span style=\"color:blue;\">Dim <\/span>objDataMacro<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMElement\r\n     strTabelle = Me!Tabelle\r\n     strDateiname = CurrentProject.Path & \"\" & strTabelle & \".xml\"\r\n     SaveAsText acTableDataMacro, strTabelle, strDateiname\r\n     <span style=\"color:blue;\">Set<\/span> objXML = <span style=\"color:blue;\">New<\/span> MSXML2.DOMDocument\r\n     objXML.Load strDateiname\r\n     <span style=\"color:blue;\">Set<\/span> objDataMacros = objXML.selectSingleNode(\"DataMacros\")\r\n     Select Case Me.Datenmakrotyp\r\n         <span style=\"color:blue;\">Case <\/span>\"NamedDataMacro\"\r\n             strMakroname = Me!Makroname\r\n             <span style=\"color:blue;\">Set<\/span> objDataMacro = objDataMacros.selectSingleNode(\"DataMacro[@Name=''\" & strMakroname & \"']\")\r\n             <span style=\"color:blue;\">Debug.Print<\/span> objDataMacro.XML\r\n             objDataMacros.removeChild objDataMacro\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             strMakroname = Me!Makroname\r\n             <span style=\"color:blue;\">Set<\/span> objDataMacro = objDataMacros.selectSingleNode(\"DataMacro[@Event=''\" & strMakroname & \"']\")\r\n             objDataMacros.removeChild objDataMacro\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n     objXML.Save strDateiname\r\n     LoadFromText acTableDataMacro, strTabelle, strDateiname\r\n     TabellenAnalysieren\r\n     Me.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: L&ouml;schen eines Datenmakros<\/span><\/b><\/p>\n<p>Die Prozedur tr&auml;gt zun&auml;chst den Namen der Tabelle, aus der das Makro gel&ouml;scht werden soll, in die Variable <b>strTabelle <\/b>ein. Dann trifft sie die Vorbereitung f&uuml;r die folgenden Schritte:<\/p>\n<ul>\n<li>Exportieren der Datenmakros in eine Textdatei<\/li>\n<li>Einlesen der Textdatei in ein XML-Dokument<\/li>\n<li>Finden des zu l&ouml;schenden <b>DataMacro<\/b>-Elements<\/li>\n<li>L&ouml;schen des <b>DataMacro<\/b>-Elements<\/li>\n<li>Schreiben des XML-Dokuments in eine Textdatei<\/li>\n<li>Importieren der Textdatei mit allen Datenmakros au&szlig;er dem gel&ouml;schten Datenmakro<\/li>\n<\/ul>\n<p>Im Code sieht das wie folgt aus: Die Prozedur stellt in der Variablen <b>strDateiname <\/b>einen Dateinamen aus dem aktuellen Datenbankverzeichnis, einem Backslash, dem Namen der Tabelle und der Dateiendung <b>.xml <\/b>zusammen. Dann speichert sie die Datenmakros der angegebenen Tabelle in der Datei aus <b>strDateiname<\/b>.<\/p>\n<p>Anschlie&szlig;end erstellt sie ein neues XML-Dokument und f&uuml;llt es &uuml;ber die <b>Load<\/b>-Methode mit dem Inhalt der soeben exportierten XML-Datei. Hier referenziert sie das Element <b>DataMacros<\/b>, das sie mit der <b>selectSingleNode<\/b>-Funktion ermittelt, mit der Variablen <b>objDataMacros<\/b>.<\/p>\n<p>In einer <b>Select Case<\/b>-Bedingung pr&uuml;ft die Prozedur, ob das Feld <b>Datenmakrotyp <\/b>den Wert <b>NamedDataMacro <\/b>oder einen anderen Wert enth&auml;lt.<\/p>\n<p>Im ersten Fall wird das Element etwas anders ermittelt, da es dann das Attribut <b>Name <\/b>mit dem Namen des Daten-makros enth&auml;lt. Diesen ermittelt die Prozedur dann etwa mit dem folgenden XPath-Ausdruck:<\/p>\n<pre>DataMacro[@Name=''dmkBeispiel']<\/pre>\n<p>Dann entfernt sie dieses Element mit der <b>removeChild<\/b>-Methode als Kindelement vom &uuml;bergeordneten Element <b>objDataMacros<\/b>.<\/p>\n<p>Handelt es sich nicht um ein benanntes Makro, sondern um eines der Datenmakros, die durch die Tabellenereignisse ausgel&ouml;st werden, tragen wir den Wert des Feldes <b>Makroname <\/b>in die Variable <b>strMakroname <\/b>ein. Dann ermitteln wir das passende Element des Typs <b>DataMacro <\/b>etwa mit dem folgenden XPath-Ausdruck:<\/p>\n<pre>DataMacro[@Event=''AfterUpdate']<\/pre>\n<p>Auch hier verwenden wir nun die <b>removeChild<\/b>-Methode, um das untergeordnete Element aus <b>objDataMacros <\/b>zu entfernen. Danach speichern wir das XML-Dokument wieder zur&uuml;ck in die Datei aus <b>strDateiname <\/b>und importieren diese mit der <b>LoadFromText<\/b>-Methode.<\/p>\n<p>Schlie&szlig;lich rufen wir erneut die Prozedur <b>TabellenAnalysieren <\/b>auf, um den aktuellen Stand der Makros in die Tabellen <b>tblTabellen <\/b>und <b>tblDatenmakros <\/b>zu schreiben. Diesen neuen Stand &uuml;bertragen wir dann mit der <b>Requery<\/b>-Methode in den angezeigten Bericht.<\/p>\n<h2>Optimierung: Nur eine Tabelle neu einlesen<\/h2>\n<p>Wir haben nun bei mehreren Aktionen im Bericht <b>rptDatenmakros <\/b>die Prozedur <b>TabellenAnalysieren <\/b>aufgerufen. In beiden F&auml;llen wurde nur jeweils ein Datenmakro hinzugef&uuml;gt oder gel&ouml;scht. Wir lesen aber immer dennoch die Datenmakros aller Tabellen neu ein. Das ist nicht n&ouml;tig: Wir brauchen nur die Datenmakros f&uuml;r die betroffene Tabelle neu einzulesen.<\/p>\n<p>Also passen wir die Prozedur noch ein wenig an, indem wir ihr einen optionalen Parameter namens <b>strTabelle <\/b>&uuml;bergeben (siehe Listing 8). Optional deshalb, weil wir diese Prozedur etwa von der Prozedur <b>Form_Load <\/b>des Berichts auch aufrufen, um alle in den Tabellen <b>tblTabellen <\/b>und <b>tblDatenmakros <\/b>gespeicherten Tabellen und Datenmakros einmal zu aktualisieren.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabellenAnalysieren(<span style=\"color:blue;\">Optional<\/span> strTabelle<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>tbl<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument\r\n     <span style=\"color:blue;\">Dim <\/span>lngTabelleID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strTabelle) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         db.Execute \"DELETE FROM tblTabellen\", dbFailOnError\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         db.Execute \"DELETE FROM tblTabellen WHERE Tabelle = ''\" & strTabelle & \"''\", dbFailOnError\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     For Each tbl In db.TableDefs\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> (<span style=\"color:blue;\">Left<\/span>(tbl.Name, 4) = \"MSys\")<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span>(<span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strTabelle) = 0 And tbl.Name = strTabelle) Or (<span style=\"color:blue;\">Len<\/span>(strTabelle) = 0)<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">If <\/span>EnthaeltMakros(tbl.Name, objXML) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                     db.Execute \"INSERT INTO tblTabellen(Tabelle) VALUES(''\" & tbl.Name & \"'')\", dbFailOnError\r\n                     lngTabelleID = db.OpenRecordset(\"SELECT @@IDENTITY\", dbOpenDynaset).Fields(0)\r\n                     XMLAnalysieren objXML, lngTabelleID, db\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 If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> tbl\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Parametrisierte Version der Prozedur TabellenAnalysieren<\/span><\/b><\/p>\n<p>Die erste &Auml;nderung ist, dass wir mit der <b>DELETE<\/b>-Anweisung nicht in jedem Fall alle Tabellen l&ouml;schen k&ouml;nnen, sondern nur noch dann, wenn der Parameter <b>strTabelle <\/b>eine L&auml;nge von 0 Zeichen hat.<\/p>\n<p>Anderenfalls soll nur die in <b>strTabelle <\/b>angegebene Tabelle aus <b>tblTabellen <\/b>gel&ouml;scht werden. Danach durchlaufen wir wie gehabt alle Eintr&auml;ge der Auflistung <b>TableDefs<\/b>. Hier schlie&szlig;en wir per <b>If&#8230;Then<\/b>-Bedingung wieder alle Elemente aus, deren Name mit <b>MSys <\/b>beginnt.<\/p>\n<p>Dann kommt eine interessante <b>If&#8230;Then<\/b>-Bedingung: Diese ist wahr, wenn entweder ein Wert mit <b>strTabelle <\/b>&uuml;bergeben wurde und <b>strTabelle <\/b>dem aktuellen Wert von <b>tdf.Name <\/b>entspricht oder wenn <b>strTabelle <\/b>leer ist.<\/p>\n<p>Sprich: Entweder soll nur eine Tabelle untersucht werden, was dann &uuml;ber den ersten Teil der <b>If&#8230;Then<\/b>-Bedingung geschieht, oder alle &#8211; daf&uuml;r muss dann der zweite Teil wahr sein. Innerhalb dieser Bedingung behalten wir alle Anweisungen wie zuvor bei.<\/p>\n<p>Nun m&uuml;ssen wir nur noch die beiden Prozeduren <b>cmdNeuesDatenmakro_Click <\/b>und <b>cmdLoeschen_Click <\/b>im Klassenmodul des Berichts <b>rptDatenmakros <\/b>wie folgt anpassen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdNeuesDatenmakro_Click()\r\n     ...\r\n     TabellenAnalysieren Me!Tabelle\r\n     Me.Requery\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>cmdLoeschen_Click()\r\n     ...\r\n     TabellenAnalysieren strTabelle\r\n     Me.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Mit der hier vorgestellten L&ouml;sung verschaffen Sie sich einen schnellen und umfassenden &Uuml;berblick &uuml;ber die Datenmakros Ihrer Tabellen und k&ouml;nnen diese per Mausklick aus einer &Uuml;bersicht heraus bearbeiten. Au&szlig;erdem k&ouml;nnen Sie neue Datenmakros anlegen oder vorhandene Daten-makros l&ouml;schen.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>DatenmakrosVerwalten.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/2A98B53A-67BE-448D-82D5-A4E46B209AED\/aiu_1203.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Datenmakros dienen dazu, Aktionen automatisch beim &Auml;ndern der Daten einer Tabelle auszul&ouml;sen &#8211; n&auml;mlich beim Anlegen, Bearbeiten oder L&ouml;schen eines Datensatzes. Diese legt man in der Regel &uuml;ber die Benutzeroberfl&auml;che an. Leider kann man damit immer nur sehen, welche Datenmakros f&uuml;r die aktuelle im Entwurf oder in der Datenblattansicht angezeigte Tabelle zur Verf&uuml;gung stehen. Dieser Beitrag zeigt, wie Sie sich einen besseren &Uuml;berblick &uuml;ber die vorhandenen Datenmakros verschaffen, diese anzeigen und bearbeiten und sogar neue Datenmakros anlegen k&ouml;nnen &#8211; und das auch noch parametrisiert f&uuml;r gleichartige Datenmakros f&uuml;r mehrere Tabellen gleichzeitig.<\/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":[662019,66052019,44000021],"tags":[],"class_list":["post-55001203","post","type-post","status-publish","format-standard","hentry","category-662019","category-66052019","category-Tabellen_und_Datenmodellierung"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Datenmakros verwalten - 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\/Datenmakros_verwalten\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Datenmakros verwalten\" \/>\n<meta property=\"og:description\" content=\"Datenmakros dienen dazu, Aktionen automatisch beim &Auml;ndern der Daten einer Tabelle auszul&ouml;sen - n&auml;mlich beim Anlegen, Bearbeiten oder L&ouml;schen eines Datensatzes. Diese legt man in der Regel &uuml;ber die Benutzeroberfl&auml;che an. Leider kann man damit immer nur sehen, welche Datenmakros f&uuml;r die aktuelle im Entwurf oder in der Datenblattansicht angezeigte Tabelle zur Verf&uuml;gung stehen. Dieser Beitrag zeigt, wie Sie sich einen besseren &Uuml;berblick &uuml;ber die vorhandenen Datenmakros verschaffen, diese anzeigen und bearbeiten und sogar neue Datenmakros anlegen k&ouml;nnen - und das auch noch parametrisiert f&uuml;r gleichartige Datenmakros f&uuml;r mehrere Tabellen gleichzeitig.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-13T20:56:14+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg06.met.vgwort.de\/na\/797f31857d6f4007b5016db4fb33870f\" \/>\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\\\/Datenmakros_verwalten\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Datenmakros verwalten\",\"datePublished\":\"2020-05-13T20:56:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/\"},\"wordCount\":5170,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/797f31857d6f4007b5016db4fb33870f\",\"articleSection\":[\"2019\",\"5\\\/2019\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/\",\"name\":\"Datenmakros verwalten - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/797f31857d6f4007b5016db4fb33870f\",\"datePublished\":\"2020-05-13T20:56:14+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/797f31857d6f4007b5016db4fb33870f\",\"contentUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/797f31857d6f4007b5016db4fb33870f\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Datenmakros_verwalten\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Datenmakros verwalten\"}]},{\"@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":"Datenmakros verwalten - 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\/Datenmakros_verwalten\/","og_locale":"de_DE","og_type":"article","og_title":"Datenmakros verwalten","og_description":"Datenmakros dienen dazu, Aktionen automatisch beim &Auml;ndern der Daten einer Tabelle auszul&ouml;sen - n&auml;mlich beim Anlegen, Bearbeiten oder L&ouml;schen eines Datensatzes. Diese legt man in der Regel &uuml;ber die Benutzeroberfl&auml;che an. Leider kann man damit immer nur sehen, welche Datenmakros f&uuml;r die aktuelle im Entwurf oder in der Datenblattansicht angezeigte Tabelle zur Verf&uuml;gung stehen. Dieser Beitrag zeigt, wie Sie sich einen besseren &Uuml;berblick &uuml;ber die vorhandenen Datenmakros verschaffen, diese anzeigen und bearbeiten und sogar neue Datenmakros anlegen k&ouml;nnen - und das auch noch parametrisiert f&uuml;r gleichartige Datenmakros f&uuml;r mehrere Tabellen gleichzeitig.","og_url":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-13T20:56:14+00:00","og_image":[{"url":"http:\/\/vg06.met.vgwort.de\/na\/797f31857d6f4007b5016db4fb33870f","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\/Datenmakros_verwalten\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Datenmakros verwalten","datePublished":"2020-05-13T20:56:14+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/"},"wordCount":5170,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/797f31857d6f4007b5016db4fb33870f","articleSection":["2019","5\/2019","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/","url":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/","name":"Datenmakros verwalten - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/797f31857d6f4007b5016db4fb33870f","datePublished":"2020-05-13T20:56:14+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/#primaryimage","url":"http:\/\/vg06.met.vgwort.de\/na\/797f31857d6f4007b5016db4fb33870f","contentUrl":"http:\/\/vg06.met.vgwort.de\/na\/797f31857d6f4007b5016db4fb33870f"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Datenmakros_verwalten\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Datenmakros verwalten"}]},{"@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\/55001203","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=55001203"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001203\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}