Kombinationsfeld mit Bearbeitungsfunktion

Kombinationsfelder dienen in der Regel der Auswahl eines Eintrags aus einer Lookup-Tabelle. In manchen Fällen programmiert man noch Funktionen hinzu, mit denen ein noch nicht vorhandener Eintrag in der zugrunde liegenden Tabelle gespeichert werden kann. Wir gehen noch einen Schritt weiter und erlauben dem Benutzer, Einträge zu löschen oder zu bearbeiten. Das Ganze natürlich unter Berücksichtigung dessen, dass bereits verwendete Einträge nicht gelöscht werden können.

Kombinationsfelder sind sehr flexible Steuerelemente, sind sie doch grundsätzlich bereits dazu ausgelegt, Daten per Auswahl oder per Eingabe anzunehmen – oder auch beides in Kombination.

Wenn Sie ein Kombinationfeld dazu verwenden, die Daten einer Lookup-Tabelle anzuzeigen, also einer Tabelle, die lediglich die normalerweise in ein Textfeld einer anderen Tabelle einzutragenden Werte aufnimmt und zum Zwecke der Vermeidung von Redundanzen und Inkonsistenzen speichert, können Sie noch mehr aus diesem Steuerelement herausholen. Dazu wollen wir drei Funktionen zum TreeView hinzufügen:

  • Anlegen eines neuen Datensatzes
  • ändern eines bestehenden Datensatzes
  • Löschen eines Datensatzes

Dazu wollen wir nicht viel mehr nutzen als das Kombinationsfeld und drei zusätzliche Schaltflächen beziehungsweise Kontextmenü-Einträge (s. Bild 1). Die drei Schaltflächen heißen cmdNeu, cmdAendern und cmdLoeschen. Die erste soll eine Inputbox anzeigen, die den Wert für den neuen Datensatz entgegennimmt. Wenn der Benutzer einen Wert eingetragen hat, soll dieser in der zugrunde liegenden Tabelle gespeichert und im Kombinationsfeld ausgewählt werden. Die gleiche Funktion soll der Benutzer noch über zwei weitere Wege aufrufen können: erstens über den Kontextmenü-Eintrag namens Neuer Eintrag und zweitens, indem er den neuen Wert direkt in das Kombinationsfeld einträgt.

So soll das Formular später aussehen.

Bild 1: So soll das Formular später aussehen.

Dieses soll dann nach Rückfrage ebenfalls in der Tabelle gespeichert und gleich im Kombinationsfeld ausgewählt werden.

Die zweite Aktion, das Bearbeiten des aktuellen Datensatzes, wird über die Schaltfläche cmdBearbeiten oder über den Kontextmenü-Eintrag Eintrag bearbeiten aufgerufen. Dies kann nicht durch direktes Bearbeiten des aktuellen Eintrags im Kombinationsfeld erfolgen, da so ja schon neue Datensätze angelegt werden sollen.

Die dritte Aktion ist das Löschen des aktuell angezeigten Eintrags. Diese Aktion ist mit großer Vorsicht zu behandeln: Schließlich kann es ja sein, dass bereits Datensätze des Formulars mit dem aktuellen Eintrag im Kombinationsfeld verknüpft sind. In diesem Fall geschieht nichts (wenn keine Löschweitergabe definiert ist) oder der Datensatz im Formular wird gleich mit dem Eintrag des Kombinationsfeldes mit gelöscht – mehr dazu weiter unten.

Wir müssen also auf irgendeine Weise dafür sorgen, dass ein bereits verknüpfter Eintrag der Lookup-Tabelle nicht gelöscht werden kann – entweder durch Deaktivieren des entsprechenden Kontextmenü-Eintrags beziehungsweise der Schaltfläche oder durch Ausgabe einer passenden Meldung, wenn der Benutzer es versucht. Der erste Ansatz ist hier vorzuziehen, weil er ergonomischer ist – der Benutzer weiß so direkt, dass er den aktuellen Eintrag nicht löschen kann.

Datenmodell-Voraussetzungen

Für die betroffenen Tabellen der hier vorgestellten Technik gibt es die eine oder andere Voraussetzung. Zum Ersten benötigen Sie natürlich eine Tabelle mit den im Formular angezeigten Werten sowie eine weitere Tabelle mit Lookupdaten.

Die erste Tabelle enthält ein Fremdschlüsselfeld, mit dem ein Datensatz der Lookup-Tabelle ausgewählt werden kann. In unserem Beispiel sind dies die Tabellen tblEinzelteile und tblEinzelteilkategorien (siehe auch den Beitrag Stücklisten, www.access-im-unternehmen.de/923). Bild 2 zeigt die beiden Tabellen im Beziehungen-Fenster.

Tabellen für das Beispiel zu diesem Beitrag

Bild 2: Tabellen für das Beispiel zu diesem Beitrag

Damit das Löschen eines Eintrags der Tabelle tblEinzelteilkategorien im Kombinationsfeld, was ja sonst nicht so einfach möglich ist, nicht zum Löschen eines Datensatzes in der verknüpften Tabelle tblEinzelteile führt, dürfen Sie in diesem Fall auf keinen Fall die Löschweitergabe an verwandte Datensätze aktivieren (s. Bild 3).

Eigenschaften der Beziehung

Bild 3: Eigenschaften der Beziehung

Desweiteren müssen Sie aber auf jeden Fall die referenzielle Integrität aktivieren. Anderenfalls könnte man problemlos auch Datensätze aus der Lookup-Tabelle tblEinzelteilkategorien löschen, die bereits einem oder mehreren Datensätzen der Tabelle tblEinzelteile zugewiesen sind.

Schließlich sollten Sie für das Feld Einzelteilkategorie der Tabelle tblEinzelteilkategorien einen eindeutigen Index anlegen, damit jede Kategorie nur einmal in der Tabelle gespeichert werden kann.

Beispielformular erstellen

Das Beispielformular frmEinzelteile enthält die Tabelle tblEinzelteile als Datenherkunft und zeigt all ihre Felder an (s. Bild 4). Das Feld EinzelteilkategorieID haben wir als Kombinationsfeld ausgeführt und diesem den Namen cboEinzelteilkategorieID gegeben.

Entwurf des Formulars

Bild 4: Entwurf des Formulars

Das Feld verwendet die folgende SQL-Abfrage als Datensatzherkunft:

SELECT -EinzelteilkategorieID, -Einzelteilkategorie -FROM -tblEinzelteilkategorien 
-ORDER BY Einzelteilkategorie;

Die beiden Eigenschaften Spaltenanzahl und Spaltenbreiten sind auf die Werte 2 und 0cm eingestellt, damit nur die Werte der zweiten Spalte angezeigt werden.

Nebem dem Kombinationsfeld platzieren Sie drei Schaltflächen namens cmdLoeschen, cmdBearbeiten und cmdNeu. Diese versehen Sie, wenn vorhanden, am besten mit entsprechenden Icons – mit diesen sparen Sie eine Menge Platz gegenüber Schaltlfächen mit Beschriftungen.

Eintrag löschen per Schaltfläche

Die Schaltfläche cmdLoeschen soll eine Prozedur auslösen, die den aktuellen Eintrag im Kombinationsfeld löscht.

Moment mal: Soll man denn nicht nur solche Einträge der Tabelle tblEinzelteilkategorien löschen können, die mit keinem Datensatz der Tabelle tblEinzelteile verknüpft sind Und sollte nicht der aktuelle Eintrag des Kombinationfeldes cboEinzelteilkategorieID auch dem aktuellen Datensatz im Hauptformular zugeordnet sein Das ist zu einigen Gelegenheiten der Fall – zum Beispiel beim öffnen des Formulars, beim Wechseln des Datensatzes oder auch nach dem Auswählen eines Eintrags im Kombinationsfeld und dem anschließenden Speichern des Datensatzes.

In dem Moment aber, in dem Sie gerade einen neuen Eintrag aus dem Kombinationsfeld ausgewählt, den Datensatz aber noch nicht gespeichert haben, ist dieser nicht dem aktuellen Datensatz zugeordnet. Sie können also einen Eintrag auswählen und diesen löschen, sofern er auch keinem anderem Datensatz der Datenherkunft des Formulars zugeordnet ist.

Kommen wir nun zu der Funktion, die durch die Schaltfläche cmdLoeschen ausgelöst wird. Diese sieht wie in Listing 1 aus und und ruft lediglich eine weitere Funktion namens EintragLoeschen auf. Dabei übergibt sie zwei Werte als Parameter:

Private Sub cmdLoeschen_Click()
     EintragLoeschen Me!cboEinzelteilkategorieID, Me!cboEinzelteilkategorieID.Column(1)
End Sub

Listing 1: Aufruf der Prozedur zum Löschen des Datensatzes zum aktuellen Eintrag des Kombinationsfeldes cboEinzelteilkategorieI

  • den aktuellen Wert des Kombinationsfeldes und
  • den aktuell angezeigten Eintrag.

Die Prozedur EintragLoeschen finden Sie in Listing 2. Sie verarbeitet zunächst den zweiten übergebenen Parameter, der in einem Meldungsfenster angezeigt wird, das den Benutzer fragt, ob der Eintrag wirklich gelöscht werden soll. Ist dies der Fall, führt die Prozedur mit der Execute-Methode eine DELETE-Abfrage aus, die den entsprechenden Datensatz löscht. Als Vergleichswert des Kriteriums verwendet sie dabei den mit dem ersten Parameter übergebenen Wert. Nach dem Löschen aktualisiert die Prozedur die Daten des Kombinationsfeldes mit der Requery-Methode. Das Kombinationsfeld ist nach diesem Aufruf leer, da der zuletzt gespeicherte Wert gelöscht wurde. Man könnte hier auch einen anderen Wert eintragen – zum Beispiel eine Aufforderung wie . Dies würde jedoch voraussetzen, dass wir diesen Eintrag in der Datensatzherkunft des Kombinationsfeldes berücksichtigen.

Public Function EintragLoeschen(lngID As Long, strEintrag As String)
     Dim db As DAO.Database
     If MsgBox("Möchten Sie den Eintrag ''" & strEintrag & "'' wirklich löschen", _
             vbYesNo + vbExclamation, "Eintrag löschen") _
             = vbYes Then
         Set db = CurrentDb
         db.Execute "DELETE FROM tblEinzelteilkategorien WHERE EinzelteilkategorieID = " & lngID
         Me!cboEinzelteilkategorieID.Requery
     End If
End Function

Listing 2: Prozedur zum Löschen des aktuellen Kombinationsfeld-Eintrags

Also passen wir die Datensatzherkunft wie folgt an:-

SELECT 0 AS -EinzelteilkategorieID, -"<Kategorie -auswählen>" -AS -Einzelteilkategorie 
FROM -tblEinzelteilkategorien
UNION
SELECT EinzelteilkategorieID, -Einzelteilkategorie
FROM tblEinzelteilkategorien
ORDER BY Einzelteilkategorie;

Für das Feld EinzelteilkategorieID der Tabelle tblEinzelteile stellen wir außerdem als Standardwert den Wert 0 ein. Auf diese Weise zeigt das Formular bei einem neuen Datensatz gleich den Eintrag an (s. Bild 5).

Standardeintrag für das Kombinationsfeld anzeigen

Bild 5: Standardeintrag für das Kombinationsfeld anzeigen

Damit dieser Eintrag nach dem Löschen eines vorhandenen Eintrags angezeigt wird, ergänzen Sie die Routine um die folgende Zeile, die Sie als letzte Anweisung innerhalb der If…Then-Bedingung einfügen:

Me!cboEinzelteilkategorieID = 0

Bearbeiten eines Eintrags

Das Kombinationsfeld lädt praktisch dazu ein, einen Eintrag direkt im Kombinationsfeld zu bearbeiten. Dies ließe sich auch realisieren, allerdings führt das ändern eines vorhandenen Eintrags in einen Eintrag, der noch nicht vorhanden ist, zum Auslösen des Ereignisses Bei nicht in Liste – und damit legt das Formular einen neuen Datensatz in der Tabelle tblEinzelteileKategorien an (siehe weiter unten unter Neuen Eintrag anlegen).

Also bieten wir rechts neben dem Kombinationsfeld die Schaltfläche cmdBearbeiten an. Diese soll eine Inputbox öffnen, die den vorhandenen Eintrag anzeigt und dem Benutzer die Möglichkeit gibt, diesen zu ändern.

Dabei ist zumindest ein Punkt zu beachten: Wir müssen eine Spezialbehandlung für den Fall vorsehen, dass der Benutzer den Eintrag in einen bereits vorhandenen Eintrag ändert. Dafür gibt es zwei Möglichkeiten:

  • Wir versuchen, den neuen Eintrag zu speichern. Dies löst wegen des eindeutigen Indexes auf dem Feld Einzelpreiskategorie Fehler 3022 aus. Darauf können wir reagieren, indem wir den Benutzer darauf hinweisen, dass ein solcher Eintrag bereits vorhanden ist.
  • Wir können auch eine Möglichkeit vorsehen, die dafür sorgt, dass der geänderte und nun doppelt vorhandene Eintrag gelöscht und alle Datensätze der Tabelle tblEinzelteile im Feld EinzelteilkategorieID den Primärschlüsselwert des Datensatzes der Tabelle tblEinzelteilkategorien erhalten, in den der Benutzer den vorhandenen Eintrag ändern wollte.

Um Letzteres zu verstehen, brauchen wir vielleicht ein Beispiel: Angenommen, es gibt in der Tabelle tblEinzelteilkategorien einen Eintrag Kategorie 1 und einen Eintrag Kategorie 2. Beide sind bereits mit Datensätzen der Tabelle tblEinzelteile verknüpft. Nun möchte der Benutzer den Namen der Kategorie Kategorie 1 in Kategorie 2 ändern. Wenn wir dies per UPDATE-Anweisung versuchen, löst dies den Fehler 3022 aus, weil Kategorie 2 ja schon vorhanden ist. An dieser Stelle können wir dem Benutzer eine Meldung anzeigen, dass die änderung nicht möglich ist. Wir können aber auch fragen, ob er vielleicht alle Einzelteile, die der Kategorie 1 zugeordnet waren, der Kategorie 2 zuordnen möchte. Wenn man es sich recht überlegt, kann man darauf aber auch verzichten: Davon ausgehend, dass der Benutzer die Kategorie 1 durch die Kategorie 2 ersetzen möchte, löschen wir einfach Kategorie 1 und weisen allen Datensätzen der Tabelle tblEinzelteile, die der Kategorie 1 zugeordnet waren, der Kategorie 2 zu. Gut: Wer mag, kann natürlich auch hier noch eine Rückfrage einbauen, um auf Nummer sicher zu gehen. Wir erledigen dies allerdings ohne eine Rückfrage.

Die Schaltfläche cmdBearbeiten löst beim Anklicken schließlich die Prozedur aus Listing 3 aus. Dabei übergibt sie als Parameter den Wert der gebundenen Spalte des Kombinationsfeldes sowie auch den angezeigten Wert, den sie über die Eigenschaft Column(1) ermittelt.

Private Sub cmdEdit_Click()
     EintragBearbeiten Me!cboEinzelteilkategorieID, Me!cboEinzelteilkategorieID.Column(1)
End Sub

Listing 3: Aufruf der Routine zum ändern eines Eintrags

Die Prozedur EintragBearbeiten finden Sie in Listing 4. Sie erwartet die beiden bereits genannten Parameter und speichert diese in den Variablen lngID und strEintrag. Sie fragt zunächst per InputBox den geänderten Wert für den Eintrag ab. Dabei soll die InputBox den bisher verwendeten Wert als Vorschlag anzeigen (s. Bild 6).

Anbieten des vorhandenen Werts als Vorgabe

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

Schreibe einen Kommentar