Zeitpläne mit Access erstellen

Karl Donaubauer, Wien

Reservierungen für ein Hotel oder Restaurant, Belegungen von Konferenz- oder Schulungsräumen, Auslastung von Maschinen, Urlaubspläne oder Terminkalender. Der Bedarf für die grafische Darstellung von Ressourcen oder Belegungen auf einer Zeitachse ist vielfältig. Access bietet keine eingebauten Zeitpläne, aber mit relativ wenig Aufwand lassen sich durchaus vorzeigbare Ergebnisse erzielen.

Es gibt verschiedene Ansätze für die Erstellung von Zeitplänen. In Versionen vor Access 2000 wurden oft ungebundene Formulare und Steuerelemente verwendet. Dabei stößt man schnell an die Grenzen von Access, denn die maximale Anzahl von Steuerelementen in einem Formular oder Bericht liegt bis Access 97 abhängig von den Steuerelementtypen bei 754 Stück. Die Dokumentationen von Microsoft nennen diese Zahl auch noch für neuere Versionen. Das ist falsch. Richtig ist: In Access 2000 kann ein Formular maximal 801 Steuerelemente und in Access 2002 und 2003 895 Steuerelemente enthalten.

Diese leichte Anhebung entschärft das Problem mit ungebundenen Steuerelementen jedoch nur geringfügig. Zum Glück hat Microsoft mit Access 2000 die Bedingte Formatierung eingeführt, die das Erstellen grafischer Zeitpläne wesentlich erleichtert. Man kann mit ihrer Hilfe nun vier verschiedene Zustände optisch darstellen und dabei ein gebundenes Formular verwenden. Dadurch spielt die Begrenzung bei den Steuerelementen keine Rolle mehr. Unsere Beispielanwendung funktioniert also mit Versionen ab Access 2000 und kann einfach in neuere Versionen konvertiert werden.

Hinweis

Auf der Begleit-CD finden Sie die Beispiel-Datenbank im Format von Access 2000 mit allen hier behandelten Quellcodes.

Hier sei gleich auf einen Bug der Bedingten Formatierung in Access 2003 hingewiesen: In der ungepatchten Version führt die Bedingte Formatierung beim öffnen eines Formulars oft zu einem Endlosloop, wobei in der Statusleiste der Text “Berechnung läuft” angezeigt wird. Dieser Bug wurde von Microsoft stillschweigend mit dem Service Pack 1 für Office 2003 behoben. Bei Access 2003 sollten Sie also mindestens dieses SP1 installiert haben.

In der Beispieldatenbank geht es um einen Reservierungsplan für ein Hotel, der die Reservierungen monatsweise anzeigt. Wenn Sie sich die Datenbank genau ansehen und als Vorlage verwenden, werden Sie sie sicher Ihren Zeitplan-Zwecken anpassen können, denn das verwendete Schema ist auf viele Anwendungsgebiete übertragbar. Die Feld- und Steuerelementbezeichnungen sind zur leichten Weiterverwendung bewusst abstrakt gehalten. Die Datenbank besteht insgesamt nur aus vier Tabellen und zwei Formularen.

Startformular ist der Reservierungsplan. Bild 1 zeigt den Plan für April 2006, als die Auslastung des Hotels nicht sehr gut war, was aber nicht am Plan, sondern am schlechten Wetter lag. Am oberen und unteren Rand sehen Sie die Tage des Monats. Samstage und Sonntage sind farblich hervorgehoben. Links und rechts sind alle Zimmer des Hotels aufgelistet. Man könnte leicht nur die belegten Zimmer anzeigen, aber die freien Ressourcen sind bei den meisten Zeitplänen eine wichtige Information.

Bild 1: Zeitplan

Bild 2: Reservierungsformular

Die Reservierungseinträge im Plan zeigen als Beschriftung den Namen des Kunden oder Gastes. Durch ihre unterschiedliche Hintergrundfarbe ist zudem auf den ersten Blick der Status der Reservierung erkennbar. ((sonst 2x zeigen))

Garantierte Reservierungen sind zum Beispiel grün, VIPs rot.

Beim Mausklick auf einen Eintrag öffnet sich das Reservierungsformular mit den Detaildaten zu dieser Reservierung (siehe Bild 2).

Wenn Sie hingegen auf ein nicht belegtes Feld des Planes klicken, öffnet sich ebenfalls das Reservierungsformular, wobei das angeklickte Zimmer und das Startdatum automatisch eingetragen werden, damit die Reservierung nur noch zu ergänzen ist. änderungen im Detailformular werden gleich beim Speichern des Datensatzes, also im Ereigniscode Bei Aktualisierung des Formulars, im Reservierungsplan wiedergegeben. Das Detailformular ist ansonsten einfach gehalten und soll nur die “interaktiven” Möglichkeiten zeigen, die ein grafischer Zeitplan erschließt.

Am oberen Rand des Plan-Formulars können Sie mit zwei Kombinationsfeldern das Jahr und den Monat wählen, wobei der Plan nach jeder Aktualisierung neu aufgebaut wird. Daneben ist noch eine Schaltfläche zum ungefilterten öffnen des Reservierungsformulars hinzugefügt, damit Sie die Testdaten besser einsehen und ändern können.

In der Tabelle tblKunden befinden sich nur ein paar Testdatensätze. ähnlich in der Tabelle tblRaum, in der die Zimmernummern aufgelistet sind. Dort könnten genauso gut die Bezeichnungen für Konferenzräume stehen oder was immer Sie für Ihre Zwecke auf den vertikalen Achsen des Zeitplanes benötigen.

In der Tabelle tblReservierung mit den Reservierungsdetails sind die Kunden und Zimmer als Fremdschlüssel enthalten, das Start- und Enddatum sowie der Status der Reservierung. Diese drei schlichten Tabellen enthalten also die eigentlichen Anwendungsdaten.

Spannender ist die vierte Tabelle tblPlan, denn sie ist die Datenherkunft für den Zeitplan. Es handelt sich um eine reine Arbeitstabelle, deren Daten bei jedem Neuaufbau des Zeitplans gelöscht und durch die aktuellen ersetzt werden. Bild 3 zeigt die Liste der Tabellen und die wichtigsten Felder von tblPlan.

Abb. 3 Entwurfsansicht von tblPlan

Bild 4: Datenblattansicht von tblPlan

Bild 4 zeigt Beispieldaten in tblPlan. Das erste Feld RowCaption1 wird mit den Zimmernummern befüllt.

RowCaption2 könnte nach dem gleichen Muster eine weitere Zeilenbeschriftung aufnehmen, wird hier aber nicht verwendet.

In den Feldern, die nur Item + Nummer heißen, also Item1, Item2 und so weiter, landet der Status der Reservierung.

Er bestimmt im Zeitplan-Formular unter Verwendung der Bedingten Formatierung das Aussehen der Einträge. Die Felder ItemTxt1, ItemTxt2 und so weiter enthalten die Beschriftung der Planeinträge, hier also die Kunden- oder Gästenamen.

Quellcode 1: Diese Routine füllt den Zeitplan.

Sub procFill()
    Dim db As DAO.Database
    Dim rsPlan As DAO.Recordset, rsDat As DAO.Recordset
    Dim ctl As Control
    Dim strSQL As String
    Dim dteComp As Date
    Dim intLastDay As Integer, i As Integer
    Dim lngColor As Long
    Set db = CurrentDb
    db.Execute "DELETE FROM tblPlan", dbFailOnError
    db.Execute "INSERT INTO tblPlan (RowCaption1) SELECT RmBez FROM tblRaum", dbFailOnError
    strSQL = "SELECT a.RmBez, a.RSStart, a.RSEnde, a.RSId, a.RSStatus, b.KDNachname" & _
            " FROM tblReservierung AS a LEFT JOIN tblKunde AS b ON a.KDId = b.KDId" & _
            " WHERE a.RSStart<=" & CLng(DateSerial(Me!cboJahr, Me!cboMonat + 1, 0)) & _
            " And a.RSEnde>" & CLng(DateSerial(Me!cboJahr, Me!cboMonat, 1)) & _
            " ORDER BY a.RSStart, a.RSEnde"
    Set rsPlan = db.OpenRecordset("tblPlan", dbOpenDynaset)
    Set rsDat = db.OpenRecordset(strSQL, dbOpenDynaset)
    For i = 1 To 31
        Me("cptItem" & i).Caption = ""
        Me("cpt2Item" & i).Caption = ""
        Me("cptItem" & i).BackColor = vbWhite
        Me("cpt2Item" & i).BackColor = vbWhite
    Next
    intLastDay = Day(DateSerial(Me!cboJahr, Me!cboMonat + 1, 0))
    For i = 1 To intLastDay
        Me("cptItem" & i).Caption = i
        Me("cpt2Item" & i).Caption = i
        Select Case Weekday(DateSerial(Me!cboJahr, Me!cboMonat, i), vbMonday)
            Case 6
                lngColor = vbBlue
            Case 7
                lngColor = vbRed
            Case Else
                lngColor = vbBlack
        End Select
        Me("cptItem" & i).BackColor = lngColor
        Me("cpt2Item" & i).BackColor = lngColor
    Next i
    Do Until rsDat.EOF
        rsPlan.FindFirst "RowCaption1 = ''" & rsDat!RmBez & "''"
        rsPlan.Edit
        For i = 1 To intLastDay
            dteComp = DateSerial(Me!cboJahr, Me!cboMonat, i)
            If dteComp >= rsDat!RSStart And dteComp < rsDat!RSEnde Then
                rsPlan("Item" & i) = rsDat!RSStatus
                rsPlan("ItemTxt" & i) = rsDat!KDNachname
                rsPlan("ItemVal" & i) = rsDat!RSId
            End If
        Next i
        rsPlan.Update
        rsDat.MoveNext
    Loop
    procFormat
    Me.Requery
End Sub

Die Felder ItemVal1, ItemVal2 und so weiter enthalten die eindeutige Id der Reservierung. Damit ist es im Zeitplan möglich, bei Klick auf ein Textfeld das Reservierungsformular mit der gewählten Reservierung zu öffnen.

Zwecks übersichtlichkeit wurde praktisch der komplette Code der Anwendung im Modul des Formulars frmPlan belassen.

Wenn Sie mehrere Zeitpläne nach diesem Muster aufbauen möchten, ist es eventuell effizienter, Teile des Codes in ein Standardmodul auszulagern. frmPlan hat als Datenherkunft die Tabelle tblPlan, die zuerst per Code gefüllt werden muss.

Zur Darstellung der Reservierungen gibt es im Detailbereich, das heißt für jedes Hotelzimmer, pro Monatstag ein ungebundenes Textfeld.

Diese Textfelder sind benannt nach dem Muster “txtItem” + Monatstag, also txtItem1 bis txtItem31 (siehe Bild 5).

In der Ereignisprozedur Beim öffnen des Formulares wird die Sub procFill aufgerufen. Das passiert bei jedem Neuaufbau des Plans, etwa beim ändern des Jahres oder Monats oder Nach Aktualisierung des Reservierungsformulars.

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