Home > Artikel > Ausgabe 5/2017 > Handyverwaltung IV: Verträge und SIM-Karten

Handyverwaltung IV: Verträge und SIM-Karten

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

Im vierten Teil der Artikelreihe zum Thema »Handyverwaltung« setzen wir die Arbeit an den Formularen der Lösung fort. Diesmal fügen wir die Formulare zum Verwalten gleich zweier Objekttypen hinzu: für die Verträge und die SIM-Karten. Die Verträge und die SIM-Karten stehen in einem 1:n-Verhältnis, wobei wir jedem Vertrag mehrere SIM-Karten zuordnen können wollen. Sehen Sie selbst, wie dies umgesetzt wird!

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1705_Handyverwaltung.accdb.

Vorüberlegungen

In diesem Teil der Artikelreihe bilden wir die Formulare für den Ausschnitt des Datenmodells ab, den Sie in Bild 1 erkennen können. Die Tabelle tblProvider haben wir ja bereits im Artikel Handyverwaltung III: Provider verwalten über ein Formular für den Benutzer verfügbar gemacht. Hinzu kommen nun die beiden Tabellen tblVertraege und tblSIMKarten. Für jeden Vertrag wollen wir dabei zunächst einen Provider auswählen lassen, und zwar über ein Kombinationsfeld.

Teil des Datenmodells, den dieser Teil der Artikelreihe abdeckt

Bild 1: Teil des Datenmodells, den dieser Teil der Artikelreihe abdeckt

Die Vorbereitungen dazu haben wir ja bereits getroffen, indem wir im Entwurf der Tabelle tblVertraege ein entsprechendes Nachschlagefeld angelegt haben. Als weiteres Datum für die Verträge wollen wir die Vertragsnummer speichern. Später kümmern wir uns um weitere interessante Eigenschaften eines Vertrags, nämlich zum Beispiel die Laufzeit, das Vertragsdatum, die einmalig und monatlich anfallenden Kosten und so weiter.

Die Tabelle tblSIMKarten enthält die Daten für die jeweilige SIM-Karte wie die Kartennummer, die Telefonnummer, die PINs und PUKs sowie den Vertrag, dem die Karte zugeordnet ist. Auch hier verwenden wir wieder ein Fremdschlüsselfeld als Basis für das Kombinationsfeld, mit dem der Benutzer den zugehörigen Vertrag auswählen kann.

In diesem Fall wollen wir allerdings nicht nur in dem Formular, das die Details einer SIM-Karte anzeigt, die verknüpften Verträge anzeigen (es kann ja für Verträge auch einmal mehr als eine SIM-Karte geben – zum Beispiel für ein zweites Gerät wie ein Tablet). Wir wollen auch im Formular für die Vertragsdetails alle mit dem Vertrag verknüpften SIM-Karten anzeigen, und zwar in einem Unterformular.

Das Formular frmSIMKarten

Beginnen wir also mit dem einfacher zu entwerfenden Formular, nämlich dem für die SIM-Karten. Dieses soll die Tabelle tblSIMKarten als Datenherkunft verwenden. Wollen wir zur Verwaltung der SIM-Karten wieder zwei Formular erstellen, also ein Übersichtsformular und ein Detailformular wie bei den Personen, oder fassen wir die Übersicht und die Details in einem Formular zusammen wie bei den Providern? Wir entscheiden uns für die letztere Variante. Allerdings soll diesmal kein Listenfeld, sondern ein Unterformular mit allen Datensätzen der Tabelle tblSIMKarten zum Einsatz kommen. Wir wollen mit der Lösung ja auch einmal verschiedene Ansätze zur Darstellung der auf unterschiedliche Art verknüpften Daten liefern. Also legen wir zunächst eine Abfragenamens qrySIMKartenNachKartennummer an, welche die alle Felder der Tabelle tblSIMKarten liefert und die Einträge nach dem Feld SIMKarte sortiert (siehe Bild 2).

Abfrage, welche die Felder der Tabelle tblSIMKarten nach Kartennummer sortiert liefert

Bild 2: Abfrage, welche die Felder der Tabelle tblSIMKarten nach Kartennummer sortiert liefert

Diese Abfrage wählen Sie dann für das neu erstellte Formular sfmSIMKarten für die Eigenschaft Datenherkunft ein. Wechseln Sie dann zur Anzeige der Feldliste und ziehen Sie die drei Felder SIMKarteID, SIMKarte und Telefonnummer dieser Abfrage in den Detailbereich des Formularentwurfs (siehe Bild 3). Anschließend stellen Sie die Eigenschaft Standardansicht auf Datenblatt ein. Schließen Sie das Formular nun.

Unterformular für die Anzeige aller SIM-Karten

Bild 3: Unterformular für die Anzeige aller SIM-Karten

Das Hauptformular frmSIMKarten

Nun folgt das Hauptformular, dem Sie auch die Abfrage qrySIMKartenNachKartennummer zuweisen. Auch wenn dieses Formular immer nur einen Datensatz anzeigt, verwenden wir diese sortierte Variante der Abfrage – warum, werden Sie weiter unten sehen. Und welcher beim Öffnen des Formulars angezeigt wird, legen wir später fest.

Erstellen Sie also ein neues Hauptformular namens frmSIMKarten. Stellen Sie als Datenherkunft die Abfrage qrySIMKartenNachKartennummer ein. Da wir immer nur einen Datensatz anzeigen und die Navigation über die im Unterformular angezeigten Datensätze erfolgen soll, wollen wir hier die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen, Trennlinien und Bildlaufleisten auf Nein einstellen sowie die Eigenschaft Automatisch zentrieren auf den Wert Ja.

Ziehen Sie dann als Erstes das Unterformular sfmSIMKarten aus dem Navigationsbereich in den Entwurf des Hauptformulars frmSIMKarten. Positionieren Sie es am linken Rand, sodass sie die übrigen Steuer­elemente, welche die Details zum aktuell im Unterformular ausgewählten Datensatz anzeigen sollen, rechts noch ausreichend Platz haben.

Nun blenden Sie die Feldliste ein und ziehen alle Felder der Datenherkunft so in das Formular, dass diese rechts vom Unterformular angezeigt werden. Das Ergebnis soll dann etwa wie in Bild 4 aussehen.

Hauptformular mit Unterformular

Bild 4: Hauptformular mit Unterformular

Wenn Sie nun in die Formularansicht wechseln, erhalten Sie die Ansicht aus Bild 5. Hier ist noch nicht alles Gold, was glänzt – selbst mit fehlenden Daten noch nicht. Zunächst einmal scheint die Anzeige des Feldes SIMKarteID im Unterformular in der Datenblattansicht nicht unbedingt nötig zu sein. Wenn diese wegfällt, haben die übrigen beiden Felder vermutlich auch schon genug Platz. Aber können wir dieses Feld einfach entfernen? Im Artikel Handyverwaltung III: Provider verwalten, wo wir ein Listenfeld zur Anzeige aller Provider verwendet haben, musste die ProviderID ja explizit aufgeführt werden, damit wir diese als gebundene Spalte nutzen und ihren Wert ermitteln konnten. Also sollen wir das Feld SIMKarteID nun aus dem Entwurf des Unterformulars entfernen oder können wir dieses irgendwie ausblenden?

Formularansicht ohne Daten

Bild 5: Formularansicht ohne Daten

Ein Einstellen der Eigenschaft Sichtbar für das Textfeld auf den Wert Nein hilft jedenfalls in der Datenblattansicht nichts: Die Spalte wird nach wie vor angezeigt. Um zu prüfen, was geschieht, wenn wir das Feld entfernen, müssen wir zunächst die synchrone Darstellung der Daten im Haupt- und Unterformular realisieren.

Haupt- und Unterformular synchronisieren

Um dafür zu sorgen, dass das Hauptformular immer den aktuell im Unterformular markierten Datensatz anzeigt, haben wir mehrere Möglichkeiten. Man mag vermuten, dass hier der Effekt eintritt, der auch beim Erstellen von Haupt- und Unterformular für die Darstellung von Daten aus 1:n-Beziehungen eintritt: Hier wird ja das Unterformular-Steuerelement, dass dann schon an die entsprechende Datenherkunft gebunden sein sollte, in das Hauptformular gezogen. Wenn diese an eine Datenherkunft gebunden ist, für das Access eine Beziehung erkennen kann, werden die beiden Eigenschaften Verknüpfen von und Verknüpfen nach des Unterformular-Steuerelements automatisch mit dem Primärschlüsselfeld und dem Fremdschlüsselfeld der Beziehung gefüllt.

Wechseln wir einmal in die Entwurfsansicht und markieren das Unterformular-Steuerelement wie in Bild 6, erkennen wir, dass Access hier automatisch für beide Eigenschaften den Wert SIMKarteID eingetragen hat.

Verknüpfungseigenschaften des Unterformular-Steuerelements

Bild 6: Verknüpfungseigenschaften des Unterformular-Steuerelements

Das bedeutet, dass das Formular im Unterformular nur diejenigen Datensätze anzeigt, deren Wert im Feld SIMKarteID mit dem entsprechenden Wert im übergeordneten Formular übereinstimmt. Was wiederum heißt, dass das Unterformular immer nur den Datensatz anzeigt, der momentan im Hauptformular angezeigt wird (siehe Bild 7). So soll es natürlich nicht aussehen, also leeren wir in einem ersten Schritt die beiden Eigenschaften Verknüpfen von und Verknüpfen nach des Unterformular-Steuerelements. Wichtig ist dabei, dass Sie tatsächlich das Unterformular-Steuerelement markieren und nicht das Unterformular selbst. Das erreichen Sie beispielsweise, indem Sie oben links im Access-Fenster den Namen des Unterformular-Steuerelements, hier sfmSIMKarten, auswählen und so das Unterformular-Steuerelement markieren (siehe Bild 8).

Das Unterformular zeigt nur den aktuellen Datensatz des Hauptformulars an.

Bild 7: Das Unterformular zeigt nur den aktuellen Datensatz des Hauptformulars an.

Auswählen des Unterformular-Steuerelements

Bild 8: Auswählen des Unterformular-Steuerelements

Wenn Sie nach dem Leeren der beiden Eigenschaften Verknüpfen von und Verknüpfen nach wieder zur Formularansicht wechseln, zeigt dieses nun alle Datensätze im Unterformular an. Wenn Sie einen davon auswählen, liefert das allerdings nicht die Details des Datensatzes im Hauptformular. Kein Wunder: Es gibt ja auch nun keinerlei Beziehung mehr zwischen den Daten im Haupt- und im Unterformular. Also sorgen wir zunächst dafür, dass das Hauptformular die Daten des im Unterformular ausgewählten Datensatzes anzeigt.

Dazu ist nur eine einzige Anweisung nötig. Diese fügen Sie in einer Ereignisprozedur ein, die durch das Ereignis Beim Laden des Hauptformulars ausgelöst wird. Geben Sie dazu für die Eigenschaft Beim Laden des Hauptformulars den Wert [Ereignisprozedur] ein und klicken Sie auf die Schaltfläche mit den drei Punkten. Die nun erscheinende Ereignisprozedur füllen Sie wie folgt auf:

Private Sub Form_Load()

Set Me!sfmSIMKarten.Form.Recordset = Me.Recordset

End Sub

Der nächste Wechsel zur Formularansicht zeigt, dass wir unser Ziel erreicht haben (siehe Bild 9). Was geschieht hier? Wir haben die Eigenschaft Recordset des Unterformulars im Unterformularsteuerelement sfmSIMKarten auf das Recordset-Element des Hauptformulars eingestellt. Auf diese Weise zeigen das Haupt- und das Unterformular nun immer den gleichen Datensatz an, egal, ob Sie diesen im Haupt- oder im Unterformular wechseln.

Das Hauptformular zeigt nun die Daten des im Unterformular ausgewählten Datensatzes an.

Bild 9: Das Hauptformular zeigt nun die Daten des im Unterformular ausgewählten Datensatzes an.

Unterformular aus der Reihenfolge entfernen

Das können Sie vom Unterformular aus testen, indem Sie dort durch die Datensätze navigieren und betrachten, wie da Hauptformular jeweils die passenden Detaildaten anzeigt. Andersherum ist es nicht so einfach zu testen, da wir bereits die Navigationsschaltflächen ausgeblendet haben.

So können wir nur noch mit der Tabulator-Taste durch die Steuer­elemente navigieren und würden so nach dem Verlassen des letzten Steuerelements zum nächsten Datensatz des Hauptformulars wechseln. Allerdings landen wir vor dem Verlassen des ersten Datensatzes im Unterformular-Steuer­element, weil dieses zuletzt zum Formular hinzugefügt wurde und somit in der Reihenfolge die letzte Position belegt. Das können wir ändern, indem wir das Unterformular-Steuerelement einfach aus der Reihenfolge herausnehmen. Dazu stellen Sie die Eigenschaft In Reihenfolge des Steuerelements auf den Wert Nein ein. Von nun an können Sie testweise durch die Steuer­elemente des Hauptformulars navigieren, bis Sie das letzte Steuer­element des aktuellen Datensatzes verlassen und im nächsten Schritt zum ersten Feld des nächsten Datensatzes wechseln. Dann zeigt auch das Unterformular den nächsten Datensatz an.

Da der Benutzer aber nicht mit den Tabulator-Tasten durch die Datensätze navigieren soll, sondern die Datensätze über die Auswahl im Unterformular ansteuern soll, legen wir noch für die Eigenschaft Zyklus den Wert Aktueller Datensatz fest. So kann der Benutzer mit den Tabulator-Tasten lediglich durch den aktuell angezeigten Datensatz navigieren.

Primärschlüsselfeld aus Unterformular ausblenden

Nun haben wir weiter oben begonnen, die Anzeig des Primärschlüsselfelds im Unterformular loszuwerden. Mit dem Einstellen der Eigenschaft Sichtbar auf den Wert Nein für das Steuer­element SIMKarteID hat es nicht geklappt. Nun wollen wir testen, ob wir das Feld einfach löschen können oder ob dies Auswirkungen auf die Funktion des Formulars hat. Wie Bild 10 zeigt, führt dies zum Erfolg: Die Primärschlüsselfeldspalte ist aus dem Unterformular verschwunden, aber wir können damit immer noch den Datensatz auswählen, dessen Details im Hauptformular angezeigt werden sollen.

Unterformular ohne störendes Primärschlüsselfeld

Bild 10: Unterformular ohne störendes Primärschlüsselfeld

Neuen Datensatz anlegen

Wie aber legen wir in diesem Formular einen neuen Datensatz an? Über das Hauptformular können wir nicht mehr zu einem neuen, leeren Datensatz navigieren. Im Unterformular wird zwar in der untersten Zeile zwar ein solcher Datensatz angezeigt, mit dem wir auch einen neuen, leeren Datensatz im Hauptformular hervorrufen können. Allerdings ist das nicht gerade benutzerfreundlich. Also fügen wir zunächst eine Schaltfläche namens cmdNeu mit der Beschriftung Neu unter dem Unterformular zum Formular hinzu. Für diese Schaltfläche hinterlegen wir die folgende Prozedur:

Private Sub cmdNeu_Click()

DoCmd.GoToRecord Record:=acNewRec

Me!SIMKarte.SetFocus

End Sub

Diese zeigt im aktuellen Formular einen neuen, leeren Datensatz an und verschiebt den Fokus auf das Textfeld SIMKarte. Geben wir nun die Daten für die neue SIM-Karte ein und durchlaufen mit der Tabulator-Taste alle Felder, bis der Datensatz gespeichert wird, aktualisiert dies sogar das Unterformular und zeigt den neuen Datensatz dort direkt an. Da auch dieser Weg nicht für jeden Benutzer offensichtlich ist, fügen wir diesem Formular noch eine Speichern- und eine Abbrechen-Schaltfläche unterhalb der gebundenen Steuer­elemente des Formulars hinzu. Die Schaltfläche zum Speichern soll die folgende Prozedur auslösen:

Private Sub cmdSpeichern_Click()

Me.Dirty = False

End Sub

Die Dirty-Eigenschaft wird auf True eingestellt, sobald der Benutzer mit der Bearbeitung entweder eines bestehenden oder eines neuen Datensatzes beginnt. Stellt man diese per Code wieder auf den Wert False ein, speichert dies den aktuellen Datensatz.

Die Abbrechen-Schaltfläche soll eine Ereignisprozedur auslösen, die lediglich die Undo-Methode des aktuellen Formulars aufruft und damit die seit dem letzten Speichern am aktuellen Datensatz durchgeführten Änderungen zurücknimmt:

Private Sub cmdAbbrechen_Click()

Me.Undo

End Sub

Nun müssen wir noch dafür sorgen, dass die beiden Schaltflächen nur dann aktiviert werden, wenn der Benutzer auch tatsächlich gerade speicherbare Änderungen an den aktuell angezeigten Daten vornimmt. Dazu stellen wir zunächst einmal die Eigenschaft Aktiviert der beiden Schaltflächen auf den Wert Nein ein, damit diese beim Öffnen des Formulars noch nicht aktiviert sind. Dies erledigen Sie über das Eigenschaftsfenster der jeweiligen Steuerelemente. Tipp: Sie können beide Steuer­elemente durch aufziehen eines geeigneten Rahmens gleichzeitig markieren und die Eigenschaft für beide Steuerelemente gleichzeitig ändern. Dann fügen wir für die Ereigniseigenschaft Bei Geändert die folgende Ereignisprozedur hinzu:

Private Sub Form_Dirty(Cancel As Integer)

Me!cmdAbbrechen.Enabled = True

Me!cmdSpeichern.Enabled = True

End Sub

Wenn Sie nun eine Änderung vornehmen, aktiviert diese Prozedur die beiden Schaltflächen. Klicken Sie eine der beiden Schaltflächen an oder wechselt der Benutzer den Datensatz, was auch zum Speichern des Datensatzes führen soll, sollen die beiden Schaltflächen natürlich wieder deaktiviert werden. Einen der Fälle, nämlich den Wechsel zu einem anderen Datensatz, können wir über das Ereignis Beim Anzeigen des Formulars abfangen. Dazu legen Sie die folgende Ereignisprozedur an:

Private Sub Form_Current()

Me!cmdAbbrechen.Enabled = False

Me!cmdSpeichern.Enabled = False

End Sub

Diese deaktiviert beim Auslösen die beiden Schaltflächen cmdSpeichern und cmdAbbrechen wieder (siehe Bild 11). Allerdings sollen die Schaltflächen auch beim Anklicken der beiden Schaltflächen cmdSpeichern und cmdAbbrechen wieder deaktiviert werden, weil dies ja entweder den aktuellen Datensatz speichert oder die Änderungen verwirft, was beides dazu führt, dass keine zu speichernden oder zu verwerfenden Änderungen mehr vorliegen. Also können wir nun zu den beiden Ereignisprozeduren der Schaltflächen cmdSpeichern und cmdAbbrechen auch noch die beiden Anweisungen zum Deaktivieren der Schaltflächen hinzufügen. Das wäre aber dann redundanter Code, daher gliedern wir die beiden Anweisungen in eine eigene Prozedur aus, die Sie wie folgt zum Klassenmodul des Formulars frmSIMKarten hinzufügen.

Die beiden Schaltflächen sind beim Öffnen des Formulars noch deaktiviert.

Bild 11: Die beiden Schaltflächen sind beim Öffnen des Formulars noch deaktiviert.

Private Sub SchaltflaechenDeaktivieren()

Me!cmdAbbrechen.Enabled = False

Me!cmdSpeichern.Enabled = False

End Sub

Den Aufruf dieser Prozedur tragen wir dann bei gleich drei Prozeduren wie folgt ein (in Form_Current entfernen wir die beiden Anweisungen der Prozedur SchaltflaechenDeaktivieren entsprechend):

Private Sub cmdAbbrechen_Click()

Me.Undo

SchaltflaechenDeaktivieren

End Sub

Private Sub cmdSpeichern_Click()

Me.Dirty = False

SchaltflaechenDeaktivieren

End Sub

Private Sub Form_Current()

SchaltflaechenDeaktivieren

End Sub

Tastenkombinationen berücksichtigen

Wir dürfen nun allerdings nicht übersehen, dass der Benutzer die Änderungen auch mit der Tastenkombination Strg + S speichern und mit der Escape-Taste verwerfen kann. Die Escape-Taste können wir leicht mit der Funktion der Abbrechen-Schaltfläche zusammenbringen, indem wir die Abbrechen-Schaltfläche in der Entwurfsansicht markieren und für diese die Eigenschaft Abbrechen auf den Wert Ja ein stellen (siehe Bild 12).

Ein Klick auf die Escape-Taste soll die Prozedur hinter der Abbrechen-Schaltfläche auslösen.

Bild 12: Ein Klick auf die Escape-Taste soll die Prozedur hinter der Abbrechen-Schaltfläche auslösen.

Für die Tastenkombination Strg + S zum Speichern des aktuellen Datensatzes können wir die Ereignisprozedur heranziehen, die beim Aktualisieren eines Datensatzes ausgelöst wird. Die dazugehörige Ereigniseigenschaft heißt Nach Aktualisierung und wir legen die folgende Ereignisprozedur dafür an:

Private Sub Form_AfterUpdate()

SchaltflaechenDeaktivieren

End Sub

Löschen einer SIM-Karte

Natürlich wollen wir auch eine Löschen-Schaltfläche zum Formular hinzufügen, die wir rechts neben der Neu-Schaltfläche unter dem Unterformular hinzufügen. Sie erhält den Namen cmdLoeschen und soll die folgende Ereignisprozedur auslösen:

Private Sub cmdLoeschen_Click()

RunCommand acCmdDeleteRecord

End Sub

Dies löscht den aktuell angezeigten Datensatz. Sollten Sie gerade einen Datensatz bearbeiten oder einen neuen Datensatz anlegen, funktioniert das Löschen ebenfalls wie gewünscht.

Ausblenden des neuen Datensatzes im Unterformular

Das Unterformular zeigt nach wie vor einen neuen, leeren Datensatz an unterster Stelle an. Um die Anzeige zu verhindern, gibt es verschiedene Möglichkeiten. Wenn Sie gleichzeitig vermeiden wollen, dass der Benutzer die Daten im Unterformular bearbeitet, stellen Sie normalerweise am einfachsten die Eigenschaft Recordsettyp auf Snapshot ein (siehe Bild 13). Dadurch wird sowohl das Bearbeiten verhindert also auch das Hinzufügen neuer Datensätze – dies schon deshalb, weil kein neuer, leerer Datensatz mehr angezeigt wird. Die Betonung liegt hier auf »normalerweise«! Denn wenn wir dies hier tun, geschieht nichts von dem zu erwartenden Verhalten.

Das Einstellen der Wertes Snapshot als Recordsettyp verhindert Bearbeitungen im Unterformular.

Bild 13: Das Einstellen der Wertes Snapshot als Recordsettyp verhindert Bearbeitungen im Unterformular.

Das liegt daran, dass wir in der Ereignisprozedur Beim Laden dem Unterformular das Recordset des Hauptformulars zuweisen und die über die Eigenschaften im Entwurf festgelegten Einstellungen damit überschreiben.

Also erledigen wir das Ausblenden des leeren, neuen Datensatzes und das Verhindern der Bearbeitung durch zwei weitere Eigenschaften, nämlich Anfügen zulassen und Bearbeitungen zulassen, die wir beide auf den Wert Nein einstellen. Das Formular bietet nun nicht mehr die Möglichkeit, neue Datensätze anzulegen (siehe Bild 14).

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!