In der bisherigen Version der Rechnungsverwaltung haben wir nur eine Kundenadresse in der Tabelle “tblKunden” gespeichert. Im Bestreben, diese Rechnungsverwaltung flexibler zu gestalten, wollen wir in diesem Beitrag zwei Dinge durchführen: Das Aufteilen der Kundentabelle in eine Tabelle mit den Basisdaten des Kunden und mehrere weitere Tabellen zum Speichern der Adressen dieses Kunden sowie das Anpassen des Formulars “frmKundenDetails” an diese Änderung des Datenmodells. Dies soll die Grundlage bilden, mehrere Adressen je Kunde zu speichern und diese dann nach Bedarf in Bestellungen, Lieferungen, Rechnungen und weitere Vorgänge zu übernehmen.
Das bisherige Datenmodell sah eine Tabelle namens tblKunden vor, die genau einen Satz von Adressdaten enthielt. Das wird den modernen Anforderungen nicht mehr gerecht, sodass wir unsere Rechnungsverwaltung, noch anpassen möchten, bevor wir die auf den Kundendaten aufbauenden Tabellen und Formulare für die Bestelldaten und die Rechnungs- und Lieferdaten erstellen.
Grundlage dafür sind einige Überlegungen aus dem Beitrag Datenmodelle für die Rechnungsverwaltung (www.access-im-unternehmen.de/1459), die wir hier nicht genau, aber ansatzweise übernehmen. Im bisherigen Datenmodell sah die Tabelle unserer Beispiellösung wie in Bild 1 aus. Hier haben wir noch nicht einmal verschiedene Adressen für die Rechnung und die Lieferung gepflegt – es war eben ein recht einfaches Datenmodell.
Bild 1: Ausgangstabelle
Aufteilung der Kundendaten auf mehrere Tabellen
Nun fügen wir zwei Tabellen zum Verwalten von Rechnungsadressen und Lieferadressen hinzu, die wir über zwei Fremdschlüsselfelder mit der Tabelle tblKunden verbinden. Aus der Tabelle tblKunden entfernen wir einige Felder, die hier nicht mehr gebraucht werden. Welche Daten man in dieser Tabelle noch benötigt, ist ohnehin wie vieles andere vom Anwendungsfall abhängig. In unserem Fall behalten wir die Felder Kundennummer, Firma, Vorname, Nachname, EMail und Telefon in dieser Tabelle.
Außerdem legen wir zwei neue Tabellen namens tblLieferadressen_Kunde und tblRechnungsadressen_Kunde an. Diese erhalten jeweils ein Fremdschlüsselfeld namens KundeID, mit dem wir die Beziehung der jeweiligen Adresse mit dem Kundendatensatz aus der Tabelle tblKunden herstellen können. Außerdem enthalten diese Tabellen die üblichen Adressfelder, aber auch nochmal Firma, AnredeID, Vorname und Nachname.
Die Tabelle tblRechnungsadressen_Kunde enthält außerdem noch das Feld UstIDNr. Warum hier und nicht in der Tabelle tblKunden? Weil es durchaus sein kann, dass ein Kunde verschiedene Firmen mit unterschiedlichen Umsatzsteuer-Identifikationsnummern hat, für die er Rechnungen benötigt.
Standardadresse für Rechnung und Lieferung festlegen
Die Tabelle tblRechnungsadressen_Kunde sieht in der Entwurfsansicht wie in Bild 2 aus. Ein weiteres wichtiges Feld neben den genannten ist das Feld Standardadresse. Es ist ein Ja/Nein-Feld, mit dem wir für jeden Kunden eine Standardlieferadresse und eine Standardrechnungsadresse festlegen können.
Bild 2: Die Tabelle für die Rechnungsadressen der Kunden
Die Pflege dieses Feldes erfordert Aufwand, den wir nicht über das Datenmodell erledigen können: Wir müssen sicherstellen, dass bei mehreren Adressen je Kunde immer genau eine Adresse den Wert True in diesem Feld aufweist. Das erledigen wir später beim Programmieren der Benutzeroberfläche.
Das Datenmodell für die Kundenadressen sieht nun wie in Bild 3 aus. Die beiden Tabellen tblLieferadressen_Kunde und tblRechnungsadressen_Kunde sind über Fremdschlüsselfelder mit der Tabelle tblKunden verknüpft. Auf diese Weise können wir nun mehrere Adressen für Rechnungen und Lieferungen für jeden Kunden anlegen und jeweils eine als Standardadresse definieren.
Bild 3: Die Kundendaten liegen nun in drei verschiedenen Tabellen.
Formulare für die Kunden und ihre Adressen
Nun benötigen wir ein Formular zur Darstellung der Sachverhalte in diesen Tabellen. Ein Teil scheint offensichtlich zu sein: Ein Hauptformular wird an die Tabelle tblKunden gebunden und zeigt die Daten dieser Tabelle an.
Für die Rechnungs- und Lieferadressen gibt es jedoch sehr viele Möglichkeiten zur Darstellung, von denen viele nicht ergonomisch sind. Was genau wollen wir in dem Formular erledigen?
- Übersichten der Rechnungsadressen und Lieferadressen anzeigen
- Details jeweils einer Rechnungs- und Lieferadresse anzeigen
- Wechsel zu den übrigen Detaildatensätzen für Rechnungen und Lieferungen auswählbar machen
- Neue Rechnungs- und Lieferadressen anlegen
- Bestehende Adressen bearbeiten
- Jeweils eine der Adressen als Standardadresse für Rechnungen und Lieferungen einstellen
- Standardadresse für Rechnungen und Lieferungen für neue Bestellungen übernehmen
- Rechnungs- und Lieferadressen löschen
Rechnungs- und Lieferadressen löschen? Aber brauchen wir die nicht dauerhaft? Nicht mit dem Modell, das wir auf den hier genannten Tabellen aufbauen. Erstellen wir eine Bestellung, werden die aktuellen Standardadressen für Rechnung und Lieferung automatisch in weitere Tabellen übernommen, die wiederum mit der Bestellung verknüpft sind.
Dementsprechend können wir die Adressen für Rechnungen und Lieferungen für einen Kunden löschen, denn diese befinden sich ja in den Datensätzen für die Bestellungen, Rechnungen und Lieferungen.
Umsetzung des Kundendetail-Formulars
Wie aber können wir das Formular so gestalten, dass die obigen Anforderungen alle erfüllt werden können? Dies erledigen wir wie in Bild 4. Im Gegensatz zu der Version, die wir im Beitrag Rechnungsverwaltung: Kundendetails (www.access-im-unternehmen.de/1383) vorgestellt haben, haben wir die Adressdaten aus dem Hauptformular herausgenommen und stellen diese nun in zwei Unterformularen dar.
Bild 4: So sollen die Kundendetails im Formular angezeigt werden
Diese beiden fügen wir wiederum auf zwei Seiten eines Registersteuerelements ein, sodass diese nicht gleichzeitig angezeigt werden müssen.
Diese Unterformulare zeigen alle Liefer- und Rechnungsadressen zum Kunden aus dem Hauptformular an. Wir können über die Navigationsschaltflächen durch diese Datensätze navigieren, aber auch eine der Adressen über das Kombinationsfeld oberhalb des Unterformulars auswählen. Außerdem wollen wir ermöglichen, eine neue Adresse durch die Auswahl des Eintrags Neu… zu erzeugen (siehe Bild 5).
Bild 5: Neuanlage einer Adresse per Auswahlfeld
Schauen wir uns nun an, wie wir dies auf Basis der vorhandenen Tabellen im Formular abbilden.
Unterformular für die Lieferadressen
Das erste Unterformular namens sfmKunde_Lieferadressen statten wir mit der Tabelle tblLieferadressen_Kunde als Datensatzquelle aus. Wir ziehen alle Felder aus der Feldliste in den Detailbereich und ordnen die Felder wie in Bild 6 an.
Bild 6: Entwurf des Unterformulars für die Lieferadressen
Es gibt einige Ereignisse im Unterformular, auf die wir reagieren wollen und die sich meist auf die Aktualisierung von Steuerelementen auswirken. Um die Ereignisse zur Steuerung des gesamten Formulars samt Unterformularen im Hauptformular zu belassen, können wir im dortigen Klassenmodul Objektvariablen deklarieren, die wir mit Verweisen auf die Unterformulare füllen.
Dadurch können wir die Ereignisse der Unterformulare im Klassenmodul des Hauptformulars implementieren und haben den kompletten Code in einem Modul. Im Unterformular müssen wir dazu nur einen Schritt durchführen, nämlich die Eigenschaft Enthält Modul auf Ja einzustellen (siehe Bild 7).
Bild 7: Hinzufügen eines Moduls zum Unterformular
Damit sind die Arbeiten am Unterformular für die Lieferadressen bereits abgeschlossen und wir können uns den Rechnungsadressen zuwenden.
Unterformular für die Rechnungsadressen
Bei diesem Unterformular bestehen die gleichen Anforderungen wie beim Unterformular für die Lieferadressen. Allerdings fügen wir hier die Tabelle tblRechnungsadressen als Datensatzquelle hinzu und speichern das Formular unter dem Namen sfmKunden_Rechnungsadressen.
Warum können wir nicht einfach nur ein solches Unterformular verwenden und per Code zur Laufzeit die Datensatzquelle anpassen? Weil die Tabelle mit den Rechnungsadressen ein zusätzliches Feld namens UstIDNr enthält, das wir ebenfalls abbilden müssen (siehe Bild 8). Auch dieses Formulars enthält keinen eigenen Code, aber wir wollen die Eigenschaft Enthält Modul aktivieren, damit wir im Hauptformular die Ereignisse für dieses Unterformular implementieren können.
Bild 8: Entwurf des Unterformulars für die Rechnungsadressen
Registersteuerelement für die Unterformulare
Im Hauptformular legen wir nun ein Registersteuerelement namens regAdressen an. Dieses soll zwei Registerseiten mit den Beschriftungen Lieferadresse und Rechnungsadresse aufweisen. Sie haben den Seitenindex 0 und 1.
Um der ersten Registerseite das Unterformular für die Lieferadressen zuzuweisen, markieren wir diese Seite durch einen Klick auf den Registerreiter. Es sollte nun ein Rahmen unterhalb des Registerreiters erscheinen. In diesen Bereich können wir nun das Formular frm_KundeLieferadressenaus dem Navigationsbereich hineinziehen. Wenn sich beim Hineinziehen der Hintergrund dieser Registerseite schwarz färbt, können wir das Unterformular fallen lassen. Nun fügen wir den Registerseiten noch weitere Steuerelemente hinzu, aber auf unterschiedliche Weise:
- Im oberen Bereich legen wir ein Kombinationsfeld an, mit dem wir die Auswahl einer der Lieferadressen ermöglichen wollen. Dieses soll ebenfalls auf der Registerseite abgelegt werden und den Namen cboRechnungsadresseAuswaehlen erhalten. Daher achten wir beim Hinzufügen auch wieder darauf, dass sich der Zielbereich der Registerseite schwarz färbt, bevor wir das Steuerelement fallen lassen.
- Unter dem Unterformular legen wir zwei Schaltflächen an. Diese sollen jedoch nicht Teil der Registerseite werden. Wieso das? Im Gegensatz zum Kombinationsfeld, das wir mit einer eigenen Datensatzherkunft und eigenen Prozeduren für die Liefer- und Rechnungsadressen ausstatten, wollen wir die beiden Schaltflächen zum Hinzufügen und Entfernen von Adressen nur einmalig anlegen. Deshalb fügen wir diese zunächst unterhalb des Registersteuerelements zum Detailbereich des Formularentwurfs hinzu und ziehen diese dann an die gewünschte Position. So wirkt es, als ob die Schaltflächen auf den beiden Registerseiten liegen, aber tatsächlich liegen sie darüber. Beim Wechsel der Registerseite können wir diese also einfach weiterverwenden. Die Schaltflächen benennen wir mit cmdAdresseLoeschen und cmdNeueAdresse. Außerdem fügen wir für beide ein Icon hinzu.
- Der zweiten Registerseite brauchen wir so nur noch das Kombinationsfeld cboRechnungsadresseAuswaehlen hinzuzufügen. Die beiden Schaltflächen werden ja automatisch auch für diese Registerseite angezeigt.
Danach sieht das Formular wie in Bild 9 aus.
Bild 9: Erste Seite des Registersteuerelements
Hauptformular mit den Unterformularen verknüpfen
Wie unter Access üblich, sollte die Beziehung zwischen Haupt- und Unterformular automatisch hergestellt werden, wenn diese die Daten aus Tabellen anzeigen, die über Primärschlüsselfeld und Fremdschlüsselfeld miteinander verknüpft sind. Zur Sicherheit prüfen wir das noch einmal nach, indem wir das Unterformular-Steuerelement sfmKunde_Lieferadressen markieren und uns die Eigenschaften ansehen. Hier finden wir für die Eigenschaft Verknüpfen nach den Wert ID und für Verknüpfen von den Wert KundeID vor – es hat also alles nach Wunsch geklappt (siehe Bild 10). Im zweiten Unterformular-Steuerelement sfmKunde_Rechnungsadressen sollte dies genauso aussehen. Wenn das Hauptformular einen Datensatz der Tabelle tblKunden anzeigt, liefern die Unterformulare die Datensätze der Tabellen tblLieferadressen_Kunde und tblRechnungsadressen_Kunde, die mit diesem Kunden verknüpft sind.
[
Bild 10: Verknüpfung zwischen Haupt- und Unterformular
Gleichzeitig wird das Fremdschlüsselfeld KundeID für neu angelegte Datensätze der Tabellen tblLieferadressen_Kunde und tblRechnungsadressen_Kunde automatisch mit dem Wert des Feldes ID des Kunden aus dem Hauptformular gefüllt.
Auswahl von Adressen per Kombinationsfeld
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