Eine besondere Anforderung an das Datenmodell und die Gestaltung der Formulare zur Bearbeitung der Daten stellt sich immer dann, wenn sich der Inhalt eines oder mehrerer Felder ändert, die bereits mit anderen Tabellen verknüpft wurden. Ein Beispiel sind Bestellungen, und hier speziell die Preise von Artikeln: Diese werden meist mit der Zeit teurer, oder der Mehrwertsteuersatz ändert sich und hin und wieder gibt es Währungsreformen. Welche Probleme dies mit sich bringt und wie Sie diese lösen, zeigt dieser Beitrag.
Bestellungen verwalten – naive Variante
Eine Artikeltabelle enthält mindestens Informationen wie den Artikelnamen und den Preis des Artikels (s. Bild 2). Zur Vereinfachung verwenden wir zunächst keine separate Kundentabelle, deren Einträge wir über ein Fremdschlüsselfeld in der Tabelle tblBestellungen auswählen, sondern einfach nur ein Feld namens Kunde – dieses soll lediglich den Namen des Kunden aufnehmen.
Bild 1: Die denkbar einfachste Variante einer Artikeltabelle
Bild 2: Eine weitere Tabelle speichert die Basisdaten einer Bestellung.
Wie kombinieren wir nun eine Bestellung mit den gewünschten Artikeln Durch eine weitere Tabelle namens tblBestellpositionen. Diese enthält zwei Fremdschlüsselfelder: Das erste heißt BestellungID und verknüpft die Tabelle mit dem Feld BestellungID der Tabelle tblBestellungen, das zweite heißt ArtikelID und sorgt dafür, dass Sie einer Bestellung Einträge aus der Tabelle tblArtikel zuweisen können. Das Feld ArtikelID der Tabelle tblBestellpositionen legen Sie als Nachschlagefeld aus, welches die Felder ArtikelID und Artikel der Tabelle tblArtikel enthält – dies spart später bei der Formulargestaltung einige Arbeit. Ein drittes Feld namens Anzahl enthält die Anzahl des jeweiligen Artikels für diese Bestellung. Den Entwurf dieser Tabelle zeigt Bild 4 aus.
Bild 3: Die Tabelle tblBestellpositionen kombiniert Bestellungen und Artikel.
Bild 4: Datenmodell der naiven Variante der Bestellverwaltung
Sie finden diese Version der Bestellverwaltung übrigens in der Beispieldatei PreiseVerwalten_1.mdb. Da wir später andere Versionen mit geänderten Datenmodellen vorstellen, haben wir für jede Version eine eigene Beispieldatenbank angelegt.
Das Verwalten von Bestellungen geschieht in Haupt- und Unterformular. Das Hauptformular verwendet die Tabelle tblBestellungen als Datenherkunft und zeigt all ihre Felder an. Das Unterformular verwendet die Abfrage aus AbbBild 5. 5 als Datenherkunft. Diese Abfrage enthält alles, was wir brauchen: Das Feld ArtikelID der Tabelle tblBestellpositionen, um den gewünschten Artikel auszuwählen, das Feld Anzahl sowie das Feld Preis der Tabelle tblArtikel – diese soll nach dem Auswählen des Artikels den Preis beisteuern. Das erste Feld, BestellungID, wird im Unterformular nicht angezeigt, aber es soll die Beziehung zum Datensatz im Hauptformular herstellen – mehr dazu gleich.
Bild 5: Die neue Datenherkunft für das Unterformular
Wenn Sie das Unterformular sfmBestellungen erstellt und mit den drei Feldern ArtikelID, Anzahl und Preis versehen haben, können Sie es zum Hauptformular hinzufügen. Dazu öffnen Sie das Formular frmBestellungen in der Entwurfsansicht und ziehen das Unterformular sfmBestellungen per Drag and Drop aus dem Datenbankfenster (Access 2003 und älter) beziehungsweise dem Navigationsbereich (Access 2007 und jünger) in den Detailbereich. Das Ergebnis soll etwa wie in Bild 6 aussehen.
Bild 6: Entwurfsansicht des Formulars frmBestellungen mit dem Unterformular sfmBestellungen
Wie sorgen Sie dafür, dass das Unterformular nur solche Artikel anzeigt, die Sie für eine bestimmte Bestellung angelegt haben Dies erledigt Access unter den gegebenen Umständen automatisch: Es erkennt, dass das Unterformular eine Datenherkunft enthält, deren Fremdschlüsselfeld mit dem Primärschlüsselfeld der Datenherkunft des Hauptformulars verknüpft ist, und stellt die beiden Eigenschaften Verknüpfen von und Verknüpfen nach des Unterformular-Steuerelements auf die Namen der an der Verknüpfung beteiligten Felder ein.
Wenn Sie das Formular nun in der Formularansicht öffnen und im Hauptformular eine Bestellung angelegt haben, können Sie über das Kombinationsfeld im Unterformular ganz einfach Artikel zur Bestellung hinzufügen (s. Bild 8).
Bild 7: Eingabe der Artikel einer Bestellung
Bild 8: Die Einstellung des Standardwerts sorgt dafür, dass das Feld beim Anlegen eines neuen Datensatzes den angegebenen Wert erhält.
Meldung bei doppelten Artikeln vermeiden
Da wir weiter oben einen zusammengesetzten, eindeutigen Index für die beiden Felder BestellungID und ArtikelID der Tabelle tblBestellpositionen erstellt haben, zeigt Access eine Meldung an, wenn Sie versuchen, einen Artikel der gleichen Bestellung zweimal zuzuweisen.
Diese Meldung ist für den Benutzer jedoch unter Umständen nicht besonders aussagekräftig, sodass wir diese durch eine eigene Meldung ersetzen. Auf diese Meldung können Sie im Ereignis Bei Fehler des Unterformulars reagieren. Wählen Sie für diese Eigenschaft des Unterformulars den Wert [Ereignisprozedur] aus und klicken Sie auf die Schaltfläche mit den drei Punkten. Der VBA-Editor öffnet sich und zeigt gleich eine leere Prozedur an, die Access beim Auftreten eines Fehlers im Formular ausführt.
Ergänzen Sie diese Prozedur wie in Listing 1. Die erste Zeile prüft die Fehlernummer, die in unserem Fall 3022 lautet. Die Fehlernummer finden Sie heraus, indem Sie in der gleichen Prozedur ganz oben die folgende Zeile einfügen:
MsgBox "Fehlernummer: " & DataErr
Listing 1: Abfangen des Fehlers, der beim mehrfachen Anlegen eines Artikels in derselben Bestellung ausgelöst wird
Private Sub Form_Error(DataErr As Integer, Response As Integer) If DataErr = 3022 Then MsgBox "Sie haben diesen Artikel bereits zur Bestellung hinzugefügt." & vbCrLf & vbCrLf _ & "ändern Sie die Anzahl, um den Artikel mehrfach zu bestellen.", _ vbOKOnly + vbExclamation, "Doppelter Artikel" Me.Undo Response = acDataErrContinue End If End Sub
Die erste Zeile innerhalb der If…Then-Bedingung gibt eine Meldung aus, die den Benutzer darauf hinweist, dass er einen bereits vorhandenen Artikel zur Bestellung hinzugefügt hat (s. Bild 9). Die zweite macht die zuletzt am aktuell bearbeiteten Datensatz durchgeführten änderungen rückgängig (beim Neuanlegen einer Bestellposition wird diese wieder entfernt, und wenn der Benutzer den Artikel einer bereits bestehenden Bestellposition geändert hat, wird der zuvor ausgewählte Artikel wiederhergestellt). Fertig: Sie können nun einfache Bestellungen eingeben.
Bild 9: Diese Meldung erscheint, wenn ein Artikel mehrfach zu einer Bestellung hinzugefügt wird.
Probleme beim ändern des Preises
Mit der aktuellen Lösung geben Sie die Daten ein, die beispielsweise zum Erstellen von Berichten zur Ausgabe von Bestellscheinen oder Rechnungen nötig sind (mit Ausnahme der Kundendaten: Wir haben hier nur den Kundennamen in die Tabelle tblBestellungen eingetragen – normalerweise würden wir hier auf eine Tabelle namens tblKunden mit den detaillierten Kundendaten verweisen).
Diese Lösung funktioniert so lange zuverlässig, bis sich der Preis eines Artikels ändert, der bereits in einer Bestellung erfasst wurde. Nehmen wir an, Sie hätten eine Bestellung aufgenommen, bei der ein Artikel 10 Euro kostet, und dem Kunden eine anschließend eine entsprechende Rechnung geschickt. Kurze Zeit später erhöht sich der Preis des Artikels auf 11 Euro. Der Kunde meldet sich, weil er die Rechnung verlegt hat und eine Kopie der Rechnung benötigt. Diese lässt sich aus der Anwendung heraus nun zwar noch erstellen, allerdings wird der neue Preis von 11 Euro für den Artikel ausgewiesen.
Behandlung von Preisänderungen
Grundsätzlich gibt es mehrere Möglichkeiten, das Problem zu umgehen. Die erste und einfachste ist, dass die Rechnung als PDF-Dokument ausgegeben und archiviert wird. Damit wäre dem Auftragnehmer und auch dem Kunden gedient, denn beide können nun auf eine korrekte Version der Rechnung zugreifen.