Bestellpositionen speichern wir in einer eigenen Tabelle beispielsweise namens tblBe-stellpositionen, die als m:n-Verknüpfungstabelle zwischen Tabellen wie tblBestellungen und tblProdukte dient. Diese Tabelle nimmt dann jeweils noch Felder auf wie Einzelpreis, Mehrwertsteuersatz und Einheit, die wir aus der Produkte-Tabelle in die Bestellpositionen-Tabelle kopieren. Damit das automatisch beim Anlegen einer Bestellposition geschieht, fügen wir normalerweise ein Ereignis zum Eingabeformular für die Bestellpositionen hinzu, das diese Daten ausliest und in die Bestellposition einträgt. Es gibt jedoch noch eine Alternative: Dabei verwenden wir ein Datenmakro, das durch das Ereignis „Vor Änderung“ des Datensatzes ausgelöst wird und verlegen die Logik damit in die Tabelle selbst. Wie das gelingt, zeigt der vorliegende Beitrag.
Beteiligte Tabellen
Die hier vorgestellte Lösung soll dazu dienen, die Daten aus mehreren Tabellen zum Zwecke der Archivierung direkt in die Tabelle tblBestellpositionen zu schreiben. Der Hintergrund ist, dass sich die Daten von Produkten wie Einzelpreis und Mehrwertsteuersatz sowie die Einheiten immer mal ändern können. Wenn wir diese Informationen dann nicht mit einer Bestellposition gespeichert haben und zu einem späteren Zeitpunkt beispielsweise die Umsätze für einen Zeitraum in der Vergangenheit untersuchen wollen, müssen wir die Daten aus den Tabellen tblBestellpositionen, tblProdukte und tblMehrwertsteuersaetze zusammensuchen. Das Problem dabei ist, dass die Daten in diesen Tabellen sich mittlerweile geändert haben könnten und wir nicht die in diesem Zeitraum tatsächlich gültigen Preise und Mehrwertsteuersätze berücksichtigen können.
Die an dieser Situation beteiligten Tabellen sehen Sie in Bild 1.
Bild 1: Beteiligte Tabellen dieser Lösung
Damit das geschilderte Problem nicht auftritt und wir zu jedem Zeitpunkt die tatsächlichen Umsätze für die jeweiligen Rechnungspositionen zusammentragen können, müssen wir die zu diesem Zeitpunkt gültigen Preise und Mehrwertsteuersätze irgendwo speichern. Dazu nutzen wir die Verknüpfungstabelle tblBestellpositionen und fügen dieser drei Felder namens Einzelpreis, Mehrwertsteuersatz und EinheitID hinzu, die wir beim Hinzufügen einer Bestellposition aus den verknüpften Tabellen füllen. Zusätzlich finden Sie hier noch das Feld Rabatt, dass auch für jede Bestellposition individuell festgelegt werden kann.
Übliche Vorgehensweise
Normalerweise würden Sie für das Hinzufügen der genannten Daten zu einer Bestellposition ein Ereignis nutzen, das nach dem Auswählen des entsprechenden Produkts ausgelöst wird.
Dies geschieht in einem Formular etwa namens frmBestellungen, das an die Daten der Tabelle tblBestellungen gebunden ist. Dieses enthält wiederum ein Unterformular namens sfmBestellungen, das die Daten der Tabelle tblBestellpositionen anzeigt, und zwar in der Datenblattansicht (siehe Bild 2).
Bild 2: Formular zum Verwalten von Bestellungen und Bestellpositionen
Dieses Unterformular zeigt alle Felder der Tabelle tblBestellpositionen mit Ausnahme des Primärschlüsselfeldes ID und des Fremdschlüsselfeldes BestellungID an. Die Daten des Unterformulars werden über dieses Fremdschlüsselfeld mit dem Feld ID des Datensatzes im übergeordneten Formular frmBestellungen verknüpft, sodass das Unterformular immer nur die zur aktuellen Bestellung gehörenden Bestellpositionen anzeigt. Durch diese Verknüpfung erhalten außerdem neu angelegte Bestellpositionen automatisch den Wert des Feldes ID der Bestellung im Hauptformular als Wert für das Fremdschlüsselfeld BestellungID der Tabelle tblBestellpositionen.
Damit nach der Auswahl eines neuen Produkts aus dem Nachschlagefeld ProduktID im Unterformular direkt die Daten aus den verknüpften Tabellen in den aktuellen Datensatz geschrieben werden, hinterlegen wir eine Ereignisprozedur für das Ereignis Vor Aktualisierung des Nachschlagefeldes. Dieses haben wir zu diesem Zweck in cboProduktID umbenannt.
Die Prozedur finden Sie in Listing 1. Sie deklariert eine Database-Objektvariable, die wir mit einem Verweis auf das aktuelle Database-Objekt füllen sowie eine Variable für ein Recordset-Objekt, das auf die Daten der Tabelle tblProdukte verweisen soll – hier genau auf den Datensatz, den der Benutzer mit dem Kombinationsfeld cboProduktID ausgewählt hat.
Private Sub cboProduktID_BeforeUpdate(Cancel As Integer) Dim db As DAO.Database Dim rstProdukte As DAO.Recordset Dim curMehrwertsteuersatz As Currency Set db = CurrentDb Set rstProdukte = db.OpenRecordset("SELECT * FROM tblProdukte WHERE ID = " & Me!ProduktID, dbOpenDynaset) Me!Einzelpreis = rstProdukte!Einzelpreis Me!EinheitID = rstProdukte!EinheitID curMehrwertsteuersatz = DLookup("Mehrwertsteuersatzwert", "tblMehrwertsteuersaetze", "ID = " _ & rstProdukte!MehrwertsteuersatzID) Me!Mehrwertsteuersatz = curMehrwertsteuersatz End Sub
Listing 1: Ereignisprozedur beim Auswählen eines Produkts für eine Bestellposition
Nach dem Ermitteln dieses Datensatzes schreibt die Prozedur die Werte der Felder Einzelpreis und EinheitID dieses Datensatzes in die entsprechenden Felder des aktuell im Unterformular angezeigten Datensatzes der Tabelle tblBestellpositionen. Schließlich ermittelt sie noch mit einer DLookup-Funktion den Mehrwertsteuersatzwert aus der Tabelle tblMehrwertsteuersaetze für die MehrwertsteuersatzID des gewählten Produkts.
Das Ergebnis dieser Abfrage landet in der Variablen curMehrwertsteuersatzwert und von dort im Feld Mehrwertsteuersatz der Bestellposition.
Wählt der Benutzer nun eines der Produkte aus, werden die Felder automatisch wie in Bild 3 mit den gewünschten Daten gefüllt.
Bild 3: Ergänzte Daten einer Bestellposition
Bevor wir nun die Alternative ausprobieren, sollten Sie die Ereignisprozedur cboProduktID_BeforeUpdate wieder entfernen oder zumindest auskommentieren – anderenfalls bearbeiten wir die gleichen Felder durch zwei unterschiedliche Mechanismen und können die Ergebnisse nicht mehr sauber interpretieren.
Bestellpositionen erweitern per Datenmakro
Das hier beschriebene Verhalten wollen wir nun mit einem Datenmakro für die Tabelle tblBestellpositionen abbilden.
Die Datenmakros von Access arbeiten so ähnlich wie die Trigger, die Sie vielleicht vom SQL Server kennen. Dort gibt es die Möglichkeit, für bestimmte Aktionen wie das Anlegen, Ändern oder Löschen von Daten Ereignisse zu definieren, die wiederum Änderungen an Daten vornehmen oder andere Aktionen auslösen können.
Access bietet gleich fünf solcher Ereignisse an, die wir hier nicht im Detail auflisten wollen – denn wir benötigen nur eines davon. Dieses heißt Vor Änderung.
Es gibt zwei Möglichkeiten, durch Ereignisse ausgelöste Datenmakros anzulegen. Die erste finden Sie in der Entwurfsansicht einer Tabelle, wenn Sie im Ribbon unter Tabellenentwurf die Schaltfläche Datenmakro erstellen anklicken. Dies öffnet eine Liste der verfügbaren Datenmakros (siehe Bild 4). Diese Möglichkeit können Sie nutzen, allerdings müssen Sie zum Ausprobieren jedesmal zurück zur Datenblattansicht wechseln, dort testen und dann für notwendige Korrekturen wieder zurückwechseln.
Bild 4: Anlegen eines Datenmakros per Ribbonbefehl aus der Entwurfsansicht einer Tabelle
Wesentlich produktiver finden wir dagegen die Möglichkeit, Datenmakros direkt von der Datenblattansicht aus zu manipulieren. Dazu aktivieren Sie bei geöffneter Tabelle im Ribbon die Registerseite Tabelle. Hier finden Sie die Befehle zum Anzeigen der verschiedenen Datenmakros direkt im Ribbon und müssen nicht erst noch eine Liste aufklappen, um die Befehle auszuführen (siehe Bild 5). Der Hauptpunkt dieser Variante ist jedoch, dass Sie das Datenmakro nach Änderungen direkt in der aktuellen Ansicht ausprobieren können und nicht erst noch von der Entwurfsansicht in die Datenblattansicht wechseln müssen.
Bild 5: Anlegen eines Datenmakros per Ribbonbefehl aus der Datenblattansicht einer Tabelle
Anlegen eines Datenmakros für die Aktion „Vor Änderung“
Wir benötigen das Datenmakro, das durch die Aktion Vor Änderung ausgelöst wird. Warum nicht Nach Aktualisierung? Weil wir während der Ausführung des Makros noch Änderungen am aktuellen Datensatz vornehmen wollen. Wenn wir das Ereignis Nach Aktualisierung wählen würden und darin Daten im aktuellen Datensatz ändern, würden wir dieses Ereignis immer wieder neu auslösen, weil wir ja immer wieder Daten ändern.
Aktionen nur beim Aktualisieren der ProduktID ausführen
Bevor wir beginnen, die Aktionen, die wir oben per VBA programmiert haben, im Makro nachzubilden, wollen wir zunächst eine wichtige Bedingung festlegen: Wir wollen die verknüpften Daten nämlich nur nachträglich in die Tabelle tblBestellpositionen schreiben, wenn der Benutzer ein neues Produkt für die Bestellposition ausgewählt hat. Wenn er andere Felder ändert, beispielsweise die Menge, den Einzelpreis oder den Rabatt, soll nichts geschehen.
Also legen wir als Erstes eine Bedingung fest, indem wir die Makroaktion Wenn hinzufügen (siehe Bild 6).
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo