Datenmakros verwalten

Datenmakros dienen dazu, Aktionen automatisch beim ändern der Daten einer Tabelle auszulösen – nämlich beim Anlegen, Bearbeiten oder Löschen eines Datensatzes. Diese legt man in der Regel über die Benutzeroberfläche an. Leider kann man damit immer nur sehen, welche Datenmakros für die aktuelle im Entwurf oder in der Datenblattansicht angezeigte Tabelle zur Verfügung stehen. Dieser Beitrag zeigt, wie Sie sich einen besseren überblick über die vorhandenen Datenmakros verschaffen, diese anzeigen und bearbeiten und sogar neue Datenmakros anlegen können – und das auch noch parametrisiert für gleichartige Datenmakros und mehrere Tabellen gleichzeitig.

Genau genommen sind wir durch die Lösung des Beitrags Zugriffsrechte mit Datenmakros (www.access-im-unternehmen.de/1193) auf die Idee zu diesem Beitrag gekommen. Dort haben wir die Tabellen der Beispieldatenbank mit einigen Datenmakros ausgestattet, die dafür sorgen, dass die Daten der Tabelle nur durch Benutzer mit entsprechenden Zugriffsrechten geändert werden dürfen.

Es wäre etwas mühselig, diese Datenmakros bei großen Datenbankanwendungen für jede Tabelle einzelnen hinzuzufügen. Daher haben wir dort schon gezeigt, wie Sie per VBA-Funktion ein Datenmakro zu der im Parameter der Funktion genannten Tabelle hinzufügen können. Aber wir wollen etwas grundlegender starten.

Datenmakros erkunden

Die erste Frage ist: Wie können wir überhaupt auf die bereits in den Tabellen der Anwendung vorhandenen Datenmakros zugreifen Gibt es eine Art VBA-Auflistung Oder auf welche Technik können wir zugreifen, um die vorhandenen Datenmakros zu analysieren

Datenmakros per Benutzeroberfläche

Schauen wir uns erst einmal an, wie wir über die Benutzeroberfläche auf die Datenmakros zugreifen. Der erste Weg ist über die Entwurfsansicht einer Tabelle. Dann finden Sie im Ribbon-Tab Entwurf unter Feld-, Datensatz- und Tabellenereignisse den Befehl Datenmakros erstellen. Wenn man diese Schaltfläche anklickt, öffnet sich eine Liste aller möglichen Daten-makros. In Bild 1 sind beispielsweise noch keine Datenmakros angelegt.

Datenmakros über die Entwurfsansicht verwalten

Bild 1: Datenmakros über die Entwurfsansicht verwalten

Wenn wir hier das Makro Nach Einfügung anlegen, wird das Icon mit einem roten Rand versehen (siehe Bild 2).

Kennzeichnung eines vorhandenen Datenmakros

Bild 2: Kennzeichnung eines vorhandenen Datenmakros

Datenmakros per Datenblatt

In der Datenblattansicht ist es noch übersichtlicher (siehe Bild 3). Hier finden Sie im Ribbon-Tab Tabelle einige Schaltflächen, mit denen Sie Datenmakros anlegen oder bearbeiten können. Wenn das Daten-makro bereits vorhanden ist, hinterlegt Access die Schaltfläche mit einem Hintergrund wie hier beim Datenmakro Nach Einfügung.

Datenmakros über die Datenblattansicht verwalten

Bild 3: Datenmakros über die Datenblattansicht verwalten

Wenn Sie auf eine der Schaltflächen klicken, öffnet Access die Entwurfsansicht für das Erstellen und Bearbeiten von Datenmakros. Diese steht aber in diesem Beitrag nicht im Mittelpunkt – daher schauen wir uns diese nun nicht im Detail an.

Per VBA auf die Datenmakros zugreifen

Nun möchten wir herausfinden, wie wir per VBA auf die Datenmakros einer Tabelle beziehungsweise der kompletten Datenbank zugreifen können. Welches Werkzeug im VBA-Editor hilft uns weiter, etwas über die Befehle in Zusammenhang mit Makros herauszufinden Der Objektkatalog.

Diesen öffnen wir und suchen nach dem Schlüsselwort Macro. Hier finden wir zunächst einige acCmd…-Konstanten, die letztlich zum Ausführen der Ribbonbefehle per VBA dienen. Außerdem entdecken wir allerdings auch ein paar weitere Elemente, die interessant sein könnten: besonders die Auflistung AllMacros (siehe Bild 4).

Befehle, welche die Zeichenkette Macro enthalten

Bild 4: Befehle, welche die Zeichenkette Macro enthalten

Wir schauen uns einmal in einer kleinen Prozedur an, welches Ergebnis diese Auflistung liefert:

Public Sub AlleMakros()
     Dim mac As Object
     For Each mac In CurrentProject.AllMacros
         Debug.Print TypeName(mac), mac.Name
     Next mac
End Sub

Dies liefert allerdings kein Ergebnis, wenn Sie nur Datenmakros angelegt haben. Die Auflistung dient allein dem Zugriff auf die herkömmlichen Makros, die auch im Navigationsbereich unter Makros angezeigt werden.

Es gibt also in der Tat keine Möglichkeit, per VBA direkt auf die Datenmakros zuzugreifen. Also gehen wir einen kleinen Umweg.

Umweg über SaveAsText

Wir wissen, dass Datenmakros in Zusammenhang mit Tabellen gespeichert werden. Weiterhin wissen wir, dass es eine Möglichkeit gibt, Access-Objekte über die Anweisung SaveAsText auf der Festplatte zu speichern und etwa über einen Texteditor auf diese Dateien zuzugreifen. Also schauen wir uns diesen Befehl einmal genauer an. Dies gelingt etwa über die IntelliSense-Funktion im Direktbereich des VBA-Editors. Dort finden wir dann ganz unten in der Liste eine interessante Konstante, nämlich acTableDataMacro (siehe Bild 5).

Die neue Konstante acTableDataMakro

Bild 5: Die neue Konstante acTableDataMakro

Auch fü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ür den zweiten Parameter den Tabellennamen angeben, dessen Datenmakros wir im Dateisystem speichern wollen.

Also legen wir für die Tabelle tblArtikel einmal je ein Makro für die verschiedenen Typen an (das Ribbon sieht dann für diese Makros wie in Bild 6 aus).

Die Einträge für die Datenmakros im Ribbon

Bild 6: Die Einträge für die Datenmakros im Ribbon

Zusätzlich fügen wir auch ein benanntes Makro zu der Tabelle hinzu, für das wir allerdings im Gegensatz zu den vorgegebenen Makros einen Namen angeben müssen. Das ist logisch, denn es kann mehr als ein benanntes Makro je Tabelle geben.

Danach rufen wir den folgenden Befehl auf, um den Code der Datenmakros auf der Festplatte zu speichern:

SaveAsText acTableDataMacro, "tblArtikel", Currentproject.Path & "\tblArtikel_Makros.txt"

Das Ergebnis sieht dann in der neu angelegten Datei tblArtikel_Makros.txt wie in Listing 1 aus. Hier sehen wir, dass es sich um eine XML-Datei handelt. Diese verwendet als Hauptobjekt das Element DataMacros. Darunter finden Sie einige Elemente namens DataMacro, die mit einem Attribut namens Event ausgestattet sind. Dieses gibt an, durch welches Ereignis das Datenmakro ausgelöst wird:

<xml version="1.0" encoding="UTF-16" standalone="no">
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
   <DataMacro Event="AfterInsert">
     <Statements>
       <Comment>Kommentar Nach Einfügung</Comment>
     </Statements>
   </DataMacro>
   <DataMacro Event="AfterUpdate">
     <Statements>
       <Comment>Kommentar Nach Aktualisierung</Comment>
     </Statements>
   </DataMacro>
   <DataMacro Event="AfterDelete">
     <Statements>
       <Comment>Kommentar Nach Löschung</Comment>
     </Statements>
   </DataMacro>
   <DataMacro Event="BeforeChange">
     <Statements>
       <Comment>Kommentar Vor änderung</Comment>
     </Statements>
   </DataMacro>
   <DataMacro Event="BeforeDelete">
     <Statements>
       <Comment>Kommentar Vor Löschung</Comment>
     </Statements>
   </DataMacro>
   <DataMacro Name="dmkBeispiel">
     <Statements>
       <Comment>Kommentar Benanntes Makro</Comment>
     </Statements>
   </DataMacro>
</DataMacros>

Listing 1: Die in eine Textdatei exportieren Datenmakros

  • AfterInsert: Nach Einfügung
  • AfterUpdate: Nach Aktualisierung
  • AfterDelete: Nach Löschung
  • BeforeChange: Vor änderung
  • BeforeDelete: Vor Löschung

Das ist aber nicht das einzige mögliche Attribut. Genau genommen wird dieses nur für die Datenmakros eingesetzt, die durch ein Ereignis ausgelöst werden. Für die anderen Makros von Tabellen, also die benannten Makros, gibt es das Attribut Name.

Unterhalb der DataMacro-Elemente finden wir ein Statements-Element, das dann die eigentlichen Befehle enthält. In unserem Beispiel haben wir für alle Makros einfach nur den Makrobefehl Kommentar eingefügt.

Hier finden dann auch die übrigen Befehle und Strukturen Platz, wobei bei den Strukturen noch untergeordnete Elemente integriert werden. Gleiches gilt für die Datenmakros.

Datenmakro analysieren

Wie aber nun können wir ermitteln, für welche Tabelle welche Datenmakros existieren und diese etwa im Direktfenster ausgeben Wir müssen tatsächlich über den Umweg des Dateiexports auf die Festplatte gehen. Dort würden wir die so gespeicherte Datei dann mit der Open-Anweisung öffnen und mit den Methoden der Bibliothek Microsoft XML, v3.0 analysieren.

Diese Bibliothek fügen Sie zunächst über den Verweise-Dialog hinzu (siehe Bild 7). Achtung: Mit der Version v6.0 funktioniert der nachfolgend angegebene VBA-Code nicht.

Hinzufügen eines Verweises auf die XML-Bibliothek

Bild 7: Hinzufügen eines Verweises auf die XML-Bibliothek

Alle Tabellen durchlaufen

Danach bauen wir zunächst ein Grundgerüst, mit dem wir alle Tabellen einer Datenbank durchlaufen. Dieses sieht wie folgt aus:

Public Sub TabellenAnalysieren()
     Dim db As dao.Database
     Dim tbl As dao.TableDef
     Dim objXML As MSXML2.DOMDocument60
     Set db = CurrentDb
     For Each tbl In db.TableDefs
         If Not (Left(tbl.Name, 4) = "MSys") Then
             If EnthaeltMakros(tbl.Name, objXML) = True Then
                 Debug.Print "Makros vorhanden in '"  & tbl.Name & "'."
             Else
                 Debug.Print "Keine Makros in '"  & tbl.Name & "'."
             End If
         End If
     Next tbl
End Sub

Damit durchlaufen wir alle Tabellen der Anwendung, deren Name nicht mit MSys… beginnt – also alle Tabellen außer den Systemtabellen. Innerhalb der If…Then-Bedingung können wir dann den Aufruf einer weiteren Prozedur unterbringen, welche die Makros in eine Datei exportiert und in ein XML-Dokument einliest – in diesem Fall eine Funktion namens EnthaeltMakros.

Diese soll den Wert True liefern, wenn eine Tabelle Datenmakros enthält und False, wenn dies nicht der Fall ist.

Makros nach XML

Die Funktion EnthaeltMakros erwartet den Namen der zu untersuchenden Tabelle als Parameter sowie eine Variable des Typs MSXML2.DOMDocument. Aus diesen bildet sie zunächst einen Dateinamen, der aus dem Pfad zur aktuellen Datenbank, einem Backslash, dem Namen der Tabelle und der Dateiendung .xml besteht:

Public Function EnthaeltMakros(strTabelle As String,  objXML As MSXML2.DOMDocument60) As Boolean
     Dim strDateiname As String
     strDateiname = CurrentProject.Path & "\"  & strTabelle & ".xml"

Dann versuchen wir, bei deaktivierter Fehlerbehandlung die SaveAsText-Anweisung mit dem Namen der Tabelle für die zu exportierenden Datenmakros und dem Dateinamen als Parameter aufzurufen. Wenn die Tabelle keine Datenmakros enthält, wird der Fehler mit der Nummer 2950 ausgelöst (Reservierter Fehler). In diesem Fall soll die Funktion enden, ohne den Funktionswert auf True einzustellen:

     On Error Resume Next
     SaveAsText acTableDataMacro, strTabelle, strDateiname
     If Err.Number = 2950 Then
         Exit Function
     End If
     On Error GoTo 0

Konnten die Datenmakros hingegen erfolgreich exportiert werden, erstellt die Funktion ein neues Objekt des Typs DOMDocument60, das wir im nächsten Schritt mit dem XML-Dokument aus der soeben mit SaveAsText angelegten Datei füllen und danach den Inhalt des XML-Dokuments testweise im Direktbereich ausgeben:

     Set objXML = New MSXML2.DOMDocument60
     objXML.Load strDateiname
     Debug.Print objXML.XML
     EnthaeltMakros = True
End Function

In diesem Fall gibt die Funktion den Wert True zurück – und auch der Parameter objXML liefert das gewünschte XML-Dokument.

XML-Dokument analysieren

In der aufrufenden Prozedur TabellenAnalysieren ersetzen wir nun die Debug.Print-Anweisung im If-Teil der If…Then-Bedingung durch den Aufruf der Prozedur XMLAnalysieren. Diesem stellen wir die Ausgabe des Tabellennamens voran. Dann übergeben wir das mit objXML referenzierte XML-Dokument als Parameter, sodass die Prozedur nun wie folgt aussieht:

Public Sub TabellenAnalysieren()
     Dim db As dao.Database
     Dim tbl As dao.TableDef
     Dim objXML As MSXML2.DOMDocument
     Set db = CurrentDb
     For Each tbl In db.TableDefs
         If Not (Left(tbl.Name, 4) = "MSys") Then
             If EnthaeltMakros(tbl.Name, objXML) = True Then
                 Debug.Print "Tabelle: " & tbl.Name
                 Debug.Print String(Len("Tabelle: "  & tbl.Name), "=")
                 XMLAnalysieren objXML
                 Debug.Print
             End If
         End If
     Next tbl
End Sub

Die dadurch aufgerufene Prozedur XMLAnalysieren finden Sie in Listing 2.

Public Sub XMLAnalysieren(objXML As MSXML2.DOMDocument)
     Dim objDataMacro As MSXML2.IXMLDOMElement
     Dim objAttribute As MSXML2.IXMLDOMAttribute
     For Each objDataMacro In objXML.selectNodes("DataMacros/DataMacro")
         Set objAttribute = objDataMacro.selectSingleNode("@Event")
         If Not objAttribute Is Nothing Then
             Debug.Print "  Event: " & objAttribute.nodeTypedValue
         Else
             Set objAttribute = objDataMacro.selectSingleNode("@Name")
             If Not objAttribute Is Nothing Then
                 Debug.Print "  Name: " & objAttribute.nodeTypedValue
             End If
         End If
     Next objDataMacro
End Sub

Listing 2: Diese Prozedur analysiert den Code der enthaltenen Makrodefinitionen anhand der Attribute.

Die Prozedur erwartet das XML-Dokument als Parameter. Sie deklariert zwei Variablen: Eine für ein Element des Typs Element des XML-Dokuments und eines für ein Attribut-Element. Die erste verwendet sie als Laufvariable für eine For Each-Schleife über alle mit einer per selectNodes abgesetzten XPath-Abfrage. Die Abfrage lautet DataMacros/DataMacro und liefert alle DataMacro-Elemente unterhalb des DataMacros-Elements. Das sind für unser obiges Beispiel sechs Elemente – die fünf Daten-makros, die durch die verschiedenen Ereignisse ausgelöst werden, und ein benanntes Makro.

Innerhalb der Schleife versucht die Prozedur, mit einer weiteren XPath-Abfrage, diesmal für das bereits in objDataMacro gespeicherte XML-Element des Typs DataMacro, das Attribut Event zu referenzieren. Um Attribute zu referenzieren, stellt man unter XPath dem Attributnamen das @-Zeichen voran.

Wenn objAttribute danach nicht leer ist, wurde das Attribut gefunden und die Prozedur gibt den Wert des Attributs über die Eigenschaft NodeTyped-Value aus. Wurde kein Attribut namens Event gefunden, versucht die Prozedur im Else-Teil, auf die gleiche Art ein Attribut namens Name zu finden. Ist dieses vorhanden, gibt die Prozedur auch dessen Wert samt Attributnamen aus.

Auf diese Weise durchläuft die Prozedur alle Elemente des Typs DataMacro. Wenn wir noch für eine weitere Tabelle namens tblBestelldetails ein Datenmakro hinzufügen, sieht die Ausgabe im Direktfenster wie folgt aus:

Tabelle: tblArtikel
===================
   Event: AfterInsert
   Event: AfterUpdate
   Event: AfterDelete
   Event: BeforeChange
   Event: BeforeDelete
   Name: dmkBeispiel
Tabelle: tblBestelldetails
==========================
   Event: AfterInsert

Datenmakros in Tabelle speichern

Wir wollen nun nicht weiter ins Detail gehen, was die in den Datenmakros enthaltenen Makroaktionen angeht, sondern eine Möglichkeit schaffen, die Tabellen und die enthaltenen Makros übersichtlich in der Datenbank anzuzeigen, damit der Benutzer diese auf die Schnelle öffnen und bearbeiten kann. Dazu benötigen wir zwei Tabellen zum Speichern der Tabellennamen und der enthaltenen Datenmakros. Auf diese greifen wir dann später von einer Kombination aus Formular und Bericht zu.

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access im Unternehmen:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 1.000 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar