Ligaverwaltung, Teil 2: Formulare

Für die meisten Sportarten gibt es Wettbewerbe in Ligen. Oder zumindest Turniere, die ja meist auch als kleine Liga angesehen werden können mit Spielpaarungen und Tabellen. Jedenfalls gibt eine Verwaltung solcher Ligen jede Menge Stoff für eine Datenbankanwendung – mit Datenmodell, Abfragen, Formularen zur Eingabe der Daten und Berichten, um Spielpläne und Tabellen auszugeben. Im zweiten Teil der Artikelreihe programmieren wir die Formulare, die zur Eingabe der Daten der Ligaverwaltung nötig sind.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1905_Ligaverwaltung.accdb.

Rapid Prototyping

Ich betreibe immer Rapid Prototyping. Das heißt, ich konzipiere nicht die komplette Anwendung durch, bevor ich sie programmiere, sondern ich fange einfach an zu programmieren. Dafür ist Microsoft Access auch das perfekte Tool, denn es gibt keine andere Entwicklungsumgebung für Datenbanken für Windows-Systeme, mit der Sie so schnell Ergebnisse erhalten.

Im ersten Teil dieser Artikelreihe haben wir ein Datenmodell für eine Ligaverwaltung erstellt, wie es uns sinnvoll erscheint und dabei die eine oder andere Abwägung getroffen. Beim Definieren des Datenmodells sollte man sorgfältig arbeiten, denn jede Entscheidung, die nachträglich revidiert werden muss, wirkt sich auf alle folgenden Ebenen aus – auf die Abfragen, Formulare und Berichte sowie auf den VBA-Code der Anwendung.

Wenn wir nun starten, die Benutzeroberfläche für die Ligaverwaltung zu programmieren, werden wir möglicherweise noch auf Probleme im Datenmodell stoßen, die wir dann direkt beheben werden.

Wie starten wir beim Prototyping Wir wollen eine Anwendung erschaffen, die dem Benutzer eine Vorstellung von der Bedienung und den enthaltenen Funktionen gibt. Dazu gehört, dass der Benutzer damit auch alle Daten eingeben kann, die für den Betrieb der Anwendung nötig sind. Wir arbeiten uns deshalb am Datenmodell entlang und erstellen zuerst die Formulare, die für die Eingabe der grundlegenden Daten nötig sind – zum Beispiel die Ligen und die Spieljahre. Die Tabelle tblLigenSpieljahre kombiniert die Ligen und die Spieljahre. Als Nächstes benötigen wir die Mannschaften. Wenn wir diese eingegeben haben, können wir sie einer Kombination aus Liga und Spieljahr zuordnen. Erst dann können wir die Spieltage und somit den Spielplan für eine Liga festlegen. Dazu wollen wir später einen praktischen Editor bereitstellen. Stehen die Spieltage, soll der Benutzer in einem eigenen Formular die Ergebnisse von Spieltagen eingeben können. Aus den Ergebnissen eines oder mehrerer Spieltage resultieren dann die Tabellenstände, die nur noch ausgegeben werden sollen. Dazu stellen wir geeignete Berichte bereit – das allerdings erst in einem späteren Teil der Artikelreihe. Nun starten wir erst einmal mit den Tabellen für die Basisdaten.

Formular frmLigen

Das erste Formular soll der Eingabe und der Verwaltung der Ligen dienen. Dazu erstellen wir zunächst ein Unterformular namens sfmLigenVerwalten. über die Eigenschaft Datensatzquelle weisen wir ihm die Tabelle tblLigen als Datenquelle zu. Damit es alle Daten dieser Tabelle in der Datenblattansicht ausgibt, ziehen wir alle drei Felder der Tabelle aus der Feldliste in den Detailbereich der Entwurfsansicht. Sie brauchen die Felder dort nicht ordentlich anzuordnen, denn wir stellen die Ansicht ohnehin über die Eigenschaft Standardansicht auf Datenblatt um. Das Ergebnis finden Sie in Bild 1.

Entwurf des Unterformulars sfmLigenVerwalten

Bild 1: Entwurf des Unterformulars sfmLigenVerwalten

Nun schließen wir das Unterformular und erstellen das Hauptformular namens frmLigenVerwalten. Diesem fügen wir per Drag and Drop den Eintrag für das Unterformular sfmLigenVerwalten zum Detailbereich hinzu. Darunter ordnen wir noch eine Schaltfläche zum Schließen des Formulars an. Außerdem entfernen wir das Beschriftungsfeld, das automatisch mit dem Unterformular zum Formular hinzugefügt wurde und ändern die Eigenschaften Bildlaufleisten, Navigationsschaltflächen und Datensatzmarkierer auf Nein sowie Automatisch zentrieren auf Ja, sodass dieses wie in Bild 2 aussieht.

Entwurf des Formulars frmLigenVerwalten

Bild 2: Entwurf des Formulars frmLigenVerwalten

Für die Schaltfläche cmdOK hinterlegen wir die folgende Ereignisprozedur:

Private Sub cmdOK_Click()
    DoCmd.Close acForm, Me.Name
End Sub

Danach können wir schon die ersten Ligen eingeben, wie Bild 3 zeigt.

Formular zur Eingabe von Ligen

Bild 3: Formular zur Eingabe von Ligen

Spieljahre verwalten

Danach kümmern wir uns direkt um ein Formular beziehungsweise ein Formular samt Unterformular zur Eingabe von Spieljahren. Das Unterformular soll sfmSpieljahreVerwalten heißen und verwendet die Tabelle tblSpieljahre als Datensatzquelle. Wir fügen auch hier alle Felder der Tabelle zum Detailbereich des Formulars hinzu. Dann stellen wir die Eigenschaft Standardansicht auf Datenblatt ein.

Das Formular fügen wir nach dem Speichern und Schließen ebenfalls per Drag and Drop aus dem Navigationsbereich von Access in ein neues Formular namens frmSpieljahreVerwalten ein. Hier führen wir die gleichen Schritte wie zuvor beim Hauptformular frmLigenVerwalten durch, sodass sich in der Entwurfsansicht die Ansicht aus Bild 4 ergibt.

Formular zur Eingabe von Spieljahren

Bild 4: Formular zur Eingabe von Spieljahren

Spieljahre und Ligen zusammenführen

An dieser Stelle taucht die erste interessante Frage auf: Zu welchem Zeitpunkt erstellen wir die Kombinationen aus Liga und Spieljahr Diese Kombination speichern wir ja in einer eigenen Tabelle namens tblLigenSpieljahre. Die Einträge sollen unter anderem eine Bezeichnung wie Bundesliga 2019/2020 liefern. Die Idee ist: Wir legen immer neue Einträge an, wenn der Benutzer entweder eine neue Liga oder ein neues Spieljahr hinzufügt. Wir können in beiden Fällen die gleiche Prozedur aufrufen, die wie in Listing 1 aussieht. Diese Prozedur definiert zwei Recordsets auf Basis der Tabellen tblLigen und tblSpieljahre. Sie durchläuft die Datensätze der Tabelle tblLigen in einer äußeren Do While-Schleife und die der Tabelle tblSpieljahre in einer inneren Do While-Schleife. Damit die Einträge der inneren Schleife nach dem ersten Durchlauf der inneren und äußeren Schleife erneut durchlaufen werden, müssen wir den Datensatzzeiger der inneren Schleife danach mit rstSpieljahre.MoveFirst wieder auf den ersten Datensatz einstellen. In der inneren Do While-Schleife führen wir bei deaktivierter Fehlerbehandlung eine INSERT INTO-Anweisung aus, die den Wert des Feldes ID der beiden Recordsets sowie die Kombination der beiden Felder Liga aus rstLigen und Spieljahr aus rstSpieljahre in die Felder der Tabelle tblLigenSpieljahre einträgt.

<font color=blue>Public Sub </font>LigenUndSpieljahreAktualisieren()
     <font color=blue>Dim </font>db<font color=blue> As </font>DAO.Database
     <font color=blue>Dim </font>rstLigen<font color=blue> As </font>DAO.Recordset
     <font color=blue>Dim </font>rstSpieljahre<font color=blue> As </font>DAO.Recordset
     <font color=blue>Set</font> db = CurrentDb
     <font color=blue>Set</font> rstLigen = db.OpenRecordset("tblLigen", dbOpenDynaset)
     <font color=blue>Set</font> rstSpieljahre = db.OpenRecordset("tblSpieljahre", dbOpenDynaset)
     <font color=blue>Do While</font> <font color=blue>Not</font> rstLigen.EOF
         <font color=blue>Do While</font> <font color=blue>Not</font> rstSpieljahre.EOF
             On Error Resume <font color=blue>Next</font>
             db.Execute "INSERT INTO tblLigenSpieljahre(LigaSpieljahr, LigaID, SpieljahrID) VALUES('" & rstLigen!Liga & " " _
                 & rstSpieljahre!Spieljahr & "', " & rstLigen!ID & ", " & rstSpieljahre!ID & ")", dbFailOnError
             <font color=blue>If </font>Err.Number = 3022<font color=blue> Then</font>
                 db.Execute "UPDATE tblLigenSpieljahre SET LigaSpieljahr = '" & rstLigen!Liga & " " & rstSpieljahre!Spieljahr _
                     & "' WHERE LigaID = " & rstLigen!ID & " AND SpieljahrID = " & rstSpieljahre!ID, dbFailOnError
             <font color=blue>End If</font>
             <font color=blue>On Error GoTo</font> 0
             rstSpieljahre.Move<font color=blue>Next</font>
         <font color=blue>Loop</font>
         rstSpieljahre.MoveFirst
         rstLigen.Move<font color=blue>Next</font>
     <font color=blue>Loop</font>
End Sub

Listing 1: Aktualisieren der Kombinationen aus Ligen und Spieljahren

Es kann sein, dass dabei ein Fehler mit der Nummer 3022 auftritt, wenn die Kombination aus Liga und Spieljahr schon in der Tabelle angelegt wurde – und zwar deshalb, weil wir einen eindeutigen, zusammengesetzten Index für diese beiden Tabellen angelegt haben. Wenn dieser Fehler auftritt, brauchen wir den Datensatz natürlich nicht erneut anzulegen. Aber gegebenenfalls hat der Benutzer in der Zwischenzeit den Namen der Liga geändert.

Also prüfen wir nach der INSERT INTO-Anweisung, ob Err.Number den Wert 3022 enthält, und führen in diesem Fall noch eine UPDATE-Anweisung aus, welche die Kombination aus Liga und Spieljahr im Feld LigaSpieljahr der Zieltabelle tblLigenSpieljahre ergänzt. Nachdem wir in beiden Schleifen alle Kombinationen aus Liga und Spieljahr durchlaufen haben, sieht die Tabellen für unsere wenigen Beispieldatensätzen danach wie in Bild 5 aus.

Die Tabelle tblLigenSpieljahre mit einigen Beispieldatensätzen

Bild 5: Die Tabelle tblLigenSpieljahre mit einigen Beispieldatensätzen

Nun müssen wir nur noch den Aufruf dieser Prozedur überall dort einfügen, wo der Benutzer die Liga oder das Spieljahr ändern kann. Am einfachsten ist es, dies beim Schließen der beiden Formulare frmLigenVerwalten und frmSpieljahreVerwalten zu erledigen.

Dazu nutzen wir das Ereignis Beim Entladen der beiden Formulare. Die dadurch ausgelöste Ereignisprozedur sieht so aus:

Private Sub Form_Unload(Cancel As Integer)
    Call LigenUndSpieljahreAktualisieren
End Sub

Zur Sicherheit: Die Namen im Feld LigaSpieljahr werden dabei immer und bei jeder änderung einer der beiden Tabellen an die Werte der dortigen Felder angepasst.

Nun haben wir die beiden Formulare zur Verwaltung von Ligen und Spieljahren so erstellt, dass der Access-kundige Benutzer diese verwenden kann – er muss wissen, dass man zum Löschen beispielsweise einen Datensatz über den Datensatzmarkierer markieren und dann die Entfernen-Taste betätigen muss und er sollte wissen, wie er einen neuen Datensatz anlegen kann.

Mannschaften verwalten

Auch die Mannschaften wollen erst einmal eingegeben werden, bevor man sich um die Zuteilung zu Ligen/Spieljahren und Spielplänen kümmern kann.

Also erstellen wir ein Hauptformular namens frmMannschaftenVerwalten und ein Unterformular namens sfmMannschaftenVerwalten, wobei das Unterformular wieder die Daten der Tabelle tblMannschaften in der Datenblattansicht anzeigt und das Hauptformular das Unterformular sowie die Schaltfläche OK enthält. Das erlaubt dann die Eingabe von Mannschaften wie in Bild 6.

Mannschaften per Formular verwalten

Bild 6: Mannschaften per Formular verwalten

Ligen, Spieljahre und Mannschaften zuordnen

Danach können wir uns an ein etwas aufwendigeres Formular begeben. Dieses soll dazu dienen, die in der Tabelle tblLigenSpieljahre definierten Kombinationen aus Ligen und Spieljahren mit den Mannschaften aus der Tabelle tblMannschaften zu verknüpfen.

Dieses Formular soll so aussehen, dass wir im Hauptformular mit einem Kombinationsfeld die Kombination aus Liga und Spieljahr auswählen und dann über ein Unterformular die Mannschaften zuordnen können. Dazu erstellen wir zunächst das Hauptformular und fügen diesem ein Kombinationsfeld namens cboLigaSpieljahr hinzu. Dieses Kombinationsfeld erhält als Datensatzherkunft die folgende Abfrage auf Basis der Tabelle tblLigenSpieljahre:

SELECT ID, LigaSpieljahr FROM tblLigenSpieljahre;

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar