Im Beitrag „Rechnungsverwaltung: Bestellformular“ (www.access-im-unternehmen.de/1382) aus der kommenden Ausgabe 5/2022 stellen wir ein Formular zur Eingabe neuer Bestellungen inklusive Bestellpositionen vor. Damit der Benutzer komfortabel auf bereits angelegte Bestellungen zugreifen und neue Bestellungen anlegen kann, stellen wir ihm ein Übersichtsformular für die Bestellungen zur Seite. Wie Sie dieses erstellen, zeigen wir im vorliegenden Beitrag. Dabei wollen wir nicht nur die Bestellungen in der Übersicht anzeigen, sondern auch Möglichkeiten zum Durchsuchen der Rechnungen sowie für die Anzeige der zuletzt verwendeten Rechnungen anbieten.
Listenfeld oder Unterformular in der Datenblattansicht?
Wenn man eine Übersicht wie die hier geplante darstellen möchte, stellt sich immer die Frage, ob man ein Listenfeld oder ein Datenblatt zur Auflistung der Einträge verwenden soll. Wenn der Benutzer in der Lage sein soll, auf einfache Weise selbst die Datensätze zu sortieren oder nach verschiedenen Kriterien zu filtern, bietet sich ein Unterformular in der Datenblattansicht an.
Im Gegensatz zum Listenfeld kann der Benutzer hier jedoch standardmäßig die Daten bearbeiten, was Sie gegebenenfalls unterbinden müssen. Wie das gelingt, zeigen wir ebenfalls in diesem Beitrag. Die Datenblattansicht bietet noch weitere Vorteile: Der Benutzer kann die Anordnung der Spalten variieren und auch Spalten ein- und ausblenden.
Unterformular erstellen
Im Gegensatz zu üblichen Gepflogenheiten starten wir in diesem Beitrag einmal nicht mit dem Hauptformular, sondern legen direkt das Unterformular zur Anzeige der Bestellungen an. Dieses soll sfmBestellungenUebersicht heißen und die Tabelle tbl-Be-stel-lungen als Datensatzquelle verwenden. Wir ziehen alle Felder aus dieser Tabelle mit Ausnahme des Feldes ID in den Detailbereich der Entwurfsansicht. Außerdem stellen wir die Eigenschaft Standardansicht auf Datenblatt ein und schließen das Formular (siehe Bild 1).
Bild 1: Das Unterformular sfmBestellungenUebersicht
Hauptformular erstellen
Das Hauptformular für die Bestellübersicht soll frmBe-stel-lun-gen-Uebersicht heißen. Wir fügen ihm als Erstes das Unterformular sfmBestellungenUebersicht hinzu, indem wir dieses aus dem Navigationsbereich in den Detailbereich des Formularentwurfs ziehen.
Damit erhalten wir die Anzeige der Bestellungen in der Datenblattansicht und können gleichzeitig im Hauptformular noch weitere Steuerelemente hinzufügen, was in einem Formular in der Datenblattansicht allein nicht möglich gewesen wäre.
Für das Unterformular-Steuerelement stellen wir die Eigenschaften Horizontaler Anker und Vertikaler Anker jeweils auf den Wert Beide ein. So wird das Unterformular gemeinsam mit dem Hauptformular vergrößert. Außerdem löschen wir das Bezeichnungsfeld des Unterformulars.
Und wir wissen bereits, dass wir im Hauptformular selbst keine Daten anzeigen wollen. Daher können wir die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen, Bildlaufleisten und Trennlinien hier direkt auf den Wert Nein einstellen.
Außerdem soll das Formular, wenn es nicht ohnehin maximiert erscheint, zumindest mittig im Access-Fenster landen. Daher stellen wir Automatisch zentrieren auf Ja ein.
Verwalten von Bestellungen
Ausgehend von hier können wir uns nun überlegen, welche Funktionen wir dem Formular hinzufügen wollen. Hier sind die Ideen, die wir in den folgenden Abschnitten umsetzen:
- Schaltfläche zum Hinzufügen einer neuen Bestellung über das Formular frmBestellungDetails mit anschließender Anzeige dieser Bestellung im Unterformular sfmBestellungenUebersicht
- Anzeigen der Details zu einer Bestellung im Formular frmBestellungDetails, entweder durch Auswahl und anschließendes Betätigen einer Schaltfläche oder per Doppelklick
- Löschen der aktuell markierten Bestellung
- Verhindern von Änderungen der Daten im Unterformular
- Verschiedene Suchkriterien, zum Beispiel Schnellsuche nach Bestellnummer oder Kunde und nach den verschiedenen Datumsangaben
Hinzufügen einer neuen Bestellung
Das Hinzufügen einer neuen Bestellung erfolgt über eine Schaltfläche namens cmdNeueBestellung. Diese soll das Formular frmBestellungDetails zum Eingeben eines neuen Datensatzes öffnen. Nach dem Hinzufügen soll der neue Datensatz direkt mit den übrigen Bestellungen im Unterformular angezeigt und auch markiert werden. Der notwendige Code lautet wie in Listing 1.
Private Sub cmdNeueBestellung_Click() Dim lngNeueBestellungID As Long DoCmd.OpenForm "frmBestellungDetails", WindowMode:=acDialog, DataMode:=acFormAdd If IstFormularGeoeffnet("frmBestellungDetails") Then lngNeueBestellungID = Forms!frmBestellungDetails!ID DoCmd.Close acForm, "frmBestellungDetails" Me!sfmBestellungenUebersicht.Form.Requery Me!sfmBestellungenUebersicht.Form.Recordset.FindFirst "ID = " & lngNeueBestellungID End If End Sub
Listing 1: Code zum Öffnen einer neuen Bestellung
Wir öffnen das Formular frmBestellungDetails als modalen Dialog und im Modus zum Hinzufügen eines Datensatzes (siehe Bild 2). In diesem Formular gibt der Benutzer nun einen neuen Datensatz ein. Mit einem Klick auf die OK-Schaltfläche schließt er die Eingabe ab und macht das Formular unsichtbar, was den aufrufenden Code fortsetzt.
Bild 2: Anlegen einer neuen Bestellung vom Formular frmBestellungenUebersicht aus
Hier prüfen wir mit der Hilfsfunktion IstFormularGeoeffnet, ob das Formular frmBestellungDetails noch geöffnet ist. Ist das der Fall, liest die Prozedur den Wert des dortigen Feldes ID in die Variable lngNeueBestellungID ein und schließt das Formular endgültig. Danach aktualisiert die Prozedur den Inhalt des Unterformulars sfmBestellungenUebersicht und stellt dieses auf den neu angelegten Datensatz ein.
Hier kommt es noch zu einem Problem, wenn die durch den Benutzer eingegebenen Daten nicht erfolgreich validiert werden können. Bisher blendet die Schaltfläche cmdOK im Formular frmBestellungDetails das Formular nur aus, aber die Validierung erfolgt ja nur, wenn der Datensatz gespeichert wird – und das geschieht erst, wenn die aufrufende Prozedur das Formular mit DoCmd.Close acForm, „frmBestellungDetails“ schließt. Damit die Validierung auch beim Ausblenden mit der Schaltfläche cmdOK durchgeführt wird, rufen wir die Prozedur Form_BeforeUpdate explizit auf und werten den darin gesetzten Rückgabeparameter Cancel wie folgt aus:
Private Sub cmdOK_Click() Dim intCancel As Integer If Me.Dirty = False Then DoCmd.Close acForm, Me.Name Exit Sub End If Form_BeforeUpdate intCancel If intCancel = 0 Then Me.Visible = False End If End Sub
Im ersten Teil prüfen wir außerdem noch, ob der Benutzer den angezeigten Datensatz überhaupt geändert hat und ob somit überhaupt eine Validierung nötig ist. Ist das nicht der Fall und die Eigenschaft Me.Dirty liefert den Wert False zurück, schließt cmdOK_Click das Formular direkt und beendet die Prozedur.
Anzeigen der Details einer Bestellung
Wenn der Benutzer einen der Datensätze im Unterformular markiert hat und auf die Schaltfläche cmdBestellungAnzeigen klickt, soll das Formular frmBestellungDetails geöffnet werden und den aktuell markierten Datensatz anzeigen.
Das realisieren wir mit der Prozedur cmdBestellungAnzeigen_Click aus Listing 2. Hier rufen wir das Formular frmBestellungDetails wieder mit der DoCmd.OpenForm-Methode auf, allerdings übergeben wir für den Parameter DataMode diesmal den Wert acFormEdit. Außerdem legen wir mit WhereCondition fest, welchen Datensatz das Formular anzeigen soll.
Private Sub cmdBestellungAnzeigen_Click() Dim lngAktuelleBestellungID As Long lngAktuelleBestellungID = Me!sfmBestellungenUebersicht.Form!ID DoCmd.OpenForm "frmBestellungDetails", WindowMode:=acDialog, DataMode:=acFormEdit, WhereCondition:="ID = " _ & lngAktuelleBestellungID If IstFormularGeoeffnet("frmBestellungDetails") Then DoCmd.Close acForm, "frmBestellungDetails" Me!sfmBestellungenUebersicht.Form.Refresh End If End Sub
Listing 2: Code zum Anzeigen einer vorhandenen Bestellung
Die Vorgehensweise, wenn der Benutzer das Formular mit der OK-Schaltfläche unsichtbar macht, sieht etwas anders aus. Wir prüfen nur noch, ob es bereits geschlossen ist und holen dies gegebenenfalls nach. Außerdem erneuern wir in diesem Fall die angezeigten Daten im Unterformular-Steuerelement mit der Refresh-Methode.
Refresh reicht in diesem Fall aus, da kein neuer Datensatz hinzugefügt wurde, sondern maximal eine Änderung an einem Datensatz durchgeführt wurde, die auch direkt in der Übersicht angezeigt werden soll.
Anzeigen der Details einer Bestellung per Doppelklick
Praktisch wäre es auch, wenn der Benutzer eine Bestellung direkt per Doppelklick anzeigen könnte. Wir wollen nur die Spalte mit der Bestellnummer für diese Funktion vorsehen.
Deshalb markieren wir in der Entwurfsansicht des Formulars das Feld Bestellnummer und legen für dessen Ereignis Beim Doppelklicken eine Ereignisprozedur an (siehe Bild 3).
Bild 3: Anlegen einer Ereignisprozedur für den Doppelklick auf die Bestellnummer
Die dadurch ausgelöste Ereignisprozedur finden Sie in Listing 3. Sie arbeitet wie die zuvor beschriebene Ereignisprozedur, aber da sie für das Unterformular definiert wurde und nicht aus der Perspektive des Hauptformulars, kann sie leichter auf die ID des doppelt angeklickten Datensatzes zugreifen – und auch der Aufruf der Refresh-Methode erfolgt wesentlich einfacher.
Private Sub Bestellnummer_DblClick(Cancel As Integer) Dim lngAktuelleBestellungID As Long lngAktuelleBestellungID = Me!ID DoCmd.OpenForm "frmBestellungDetails", WindowMode:=acDialog, DataMode:=acFormEdit, WhereCondition:="ID = " _ & lngAktuelleBestellungID If IstFormularGeoeffnet("frmBestellungDetails") Then DoCmd.Close acForm, "frmBestellungDetails" Me.Refresh End If End Sub
Listing 3: Code zum Anzeigen einer vorhandenen Bestellung per Doppelklick auf die Bestellnummer im Unterformular
Anzeigen der Details eines Kunden
Natürlich könnte man diese Funktion auch in einem Formular mit einer Kundenübersicht unterbringen, aber warum nicht auch direkt in der Übersicht der Bestellungen? Vielleicht möchten Sie nicht nur eine Bestellung betrachten, sondern gleich den Kundendatensatz mit allen Bestellungen, die der Kunde bis dato aufgegeben hat.
Also fügen wir dem Formular noch zwei Möglichkeiten hinzu, den Kundendatensatz zur aktuell markierten Bestellung zu öffnen. Die erste ist eine Schaltfläche, die wir diesmal cmdKundeAnzeigen nennen. Diese Schaltfläche soll ein Formular namens frmKundeDetails öffnen, das wir in einem weiteren Beitrag mit dem Titel Rechnungsverwaltung: Kundenübersicht (www.access-im-unternehmen.de/****) beschreiben.
Die Schaltfläche cmdKundeAnzeigen löst die Prozedur aus Listing 4 aus. Die Prozedur liest die ID des Kunden aus dem Fremdschlüsselfeld KundeID der markierten Bestellung ein und verwendet diese als Vergleichswert des Parameters WhereCondition beim Öffnen des Formulars frmKundeDetails. Dort kann der Benutzer die gewünschten Änderungen durchführen und die Bearbeitung mit der Schaltfläche OK abschließen. Eventuelle Änderungen werden dann mit der Refresh-Methode in das Feld cboKundeID des Unterformulars sfmBestellungenUebersicht übernommen.
Private Sub cmdKundeAnzeigen_Click() Dim lngAktuellerKundeID As Long lngAktuellerKundeID = Me!sfmBestellungenUebersicht.Form!cboKundeID DoCmd.OpenForm "frmKundeDetails", WindowMode:=acDialog, DataMode:=acFormEdit, WhereCondition:="ID = " _ & lngAktuellerKundeID If IstFormularGeoeffnet("frmKundeDetails") Then DoCmd.Close acForm, "frmKundeDetails" Me!sfmBestellungenUebersicht.Form.Refresh End If End Sub
Listing 4: Öffnen des Kunden der aktuell ausgewählten Bestellung per Klick auf cmdKundeAnzeigen
Die gleiche Funktion möchten wir für einen Doppelklick auf das Steuerelement cboKundeID im Unterformular sfmBestellungenUebersicht abbilden. Dazu hinterlegen wir die Prozedur aus Listing 5 für das Ereignis Beim Doppelklicken dieses Steuerelements.
Private Sub cboKundeID_DblClick(Cancel As Integer) Dim lngAktuellerKundeID As Long lngAktuellerKundeID = Me!cboKundeID DoCmd.OpenForm "frmKundeDetails", WindowMode:=acDialog, DataMode:=acFormEdit, WhereCondition:="ID = " _ & lngAktuellerKundeID If IstFormularGeoeffnet("frmKundeDetails") Then DoCmd.Close acForm, "frmKundeDetails" Me.Refresh End If End Sub
Listing 5: Öffnen des Kunden der aktuell ausgewählten Bestellung per Doppelklick auf den Kundennamen im Unterformular
Löschen einer Bestellung
Die Schaltfläche cmdBestellungLoeschen soll das Löschen einer Bestellung ermöglichen. Hier wird es spannend: Wir haben im Datenmodell angegeben, dass nur Bestellungen gelöscht werden können sollen, für die noch keine Datensätze in der verknüpften Tabelle tblBestellpositionen angelegt wurden.
Ein einfaches Löschen mit einer DELETE-Aktionsabfrage würde daher zu der Fehlermeldung aus Bild 4 führen.
Bild 4: Fehler beim Versuch, eine Bestellung zu löschen, die bereits Bestellpositionen enthält
Daher führen wir die Prozedur, die durch die Schaltfläche cmdBestellungLoeschen ausgeführt wird, wie in Listing 6 aus. Diese ermittelt zunächst die ID der zu löschenden Bestellung und verwendet diese als Vergleichswert der nachfolgend ausgeführten DELETE-Aktionsabfrage. Vorher deaktivieren wir jedoch die eingebaute Fehlerbehandlung, um auf den oben erwähnten Fehler mit einer eigenen Meldung reagieren zu können.
Private Sub cmdBestellungLoeschen_Click() Dim db As DAO.Database Dim lngZuLoeschendeBestellungID As Long Set db = CurrentDb lngZuLoeschendeBestellungID = Me!sfmBestellungenUebersicht.Form!ID On Error Resume Next db.Execute "DELETE FROM tblBestellungen WHERE ID = " & lngZuLoeschendeBestellungID, dbFailOnError If Err.Number = 3200 Then MsgBox "Die Bestellung enthält bereits Bestellpositionen. Bitte entfernen Sie diese nach Prüfung und " _ & "löschen Sie erst dann die Bestellung.", vbOKOnly + vbInformation, "Löschen nicht möglich" DoCmd.OpenForm "frmBestellungDetails", WindowMode:=acDialog, DataMode:=acFormEdit, WhereCondition:="ID = " _ & lngZuLoeschendeBestellungID If IstFormularGeoeffnet("frmBestellungDetails") Then DoCmd.Close acForm, "frmBestellungDetails" Me!sfmBestellungenUebersicht.Form.Refresh Me!sfmBestellungenUebersicht.Form.Recordset.FindFirst "ID = " & lngZuLoeschendeBestellungID End If Else Me!sfmBestellungenUebersicht.Form.Requery End If End Sub
Listing 6: Code zum Löschen einer Bestellung
Diese fordert den Benutzer auf, die Bestellpositionen zu sichten und gegebenenfalls manuell zu entfernen, bevor er einen neuen Anlauf zum Löschen des Bestelldatensatzes startet. Dazu öffnen wir direkt das Formular frmBe-stel-lung-Details und zeigen den zu löschenden Datensatz an. Nachdem der Benutzer dieses Formular mit OK ausgeblendet hat, schließt die Prozedur das Formular und aktualisiert die Bestellübersicht. Dann markiert sie den zu löschenden Datensatz erneut.
Falls beim Löschen des Bestelldatensatzes kein Fehler aufgetreten ist, aktualisiert die Prozedur einfach noch die Bestellübersicht im Unterformular.
Änderungen im Unterformular verhindern
Wir wollen außerdem sicherstellen, dass der Benutzer direkt im Unterformular mit den Bestellungen keine Datensätze ändern kann. Das soll dem Formular frmBestellungDetails vorbehalten sein. Dazu ist nicht viel zu tun: Wir müssen einfach nur in der Entwurfsansicht das Unterformular sfmBestellungenUebersicht markieren und für dieses die Eigenschaften Anfügen zulassen, Löschen zulassen und Bearbeitungen zulassen auf Nein einstellen (siehe Bild 5).
Bild 5: Sperren der Bearbeitung der Daten im Unterformular
Steuerelemente anordnen
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