Terminserien

Zum Eingeben von Terminen gibt es mittlerweile verschiedene eingebaute und zusätzliche Techniken. Aber was ist, wenn der Benutzer in einer Anwendung gleich mehrere Termine anlegen möchte – beispielsweise, um gleich für ein ganzes Jahr eine Erinnerung an die Umsatzsteuervoranmeldung zu speichern oder um die Geburtstage seiner Bekannten in seiner Termindatenbank anzulegen Hier würde ein flexibel einsetzbares Tool eine Menge Arbeit sparen. Wie Sie solch ein Tool programmieren, erfahren Sie in diesem Beitrag.

Der konkrete Anlass für die Erstellung der im vorliegenden Beitrag beschriebenen Lösung ist die Aufgabenmanagement-Datenbank aus dem Beitrag Tomatengetriebene Programmierung (www.access-im-unternehmen.de/791). Dort soll der Benutzer gleich eine ganze Reihe von täglich, wöchentlich, monatlich oder jährlich wiederkehrenden Terminen anlegen können.

Welche Anforderung gibt es an eine solche Lösung Sie sollte eine Benutzeroberfläche bieten, die dem Benutzer das Anlegen der gewünschten Termine erleichtert.

Und sie sollte die Termine in einem Format liefern, das sich leicht weiterverarbeiten lässt. Am leichtgewichtigsten scheint hier ein Array zu sein, das einfach nur die ermittelten Termindaten enthält.

Die Anforderungen an die Ermittlung der Termine sind schon vielfältiger. Die erste Auswahl betrifft die Art der Terminserie. Die vorliegende Lösung soll diese Varianten abdecken:

  • tägliche Termine
  • wöchentliche Termine
  • monatliche Termine
  • jährliche Termine

Eine weitere Option betrifft Feiertage und Wochenenden. Sollen diese einfach als Termine zurückgegeben werden können oder soll die Lösung den vorherigen oder den folgenden Tag liefern, wenn der eigentlich gewünschte Termin auf einen Feiertag oder ein Wochenende fällt (wobei Wochenende noch auf Samstag und Sonntag aufzuteilen ist)

Und was geschieht, wenn der Benutzer als monatliches Datum den 31. Tag auswählt Soll dann der vorherige oder der folgende Tag zurückgegeben werden, wenn der jeweilige Monat keine 31 Tage hat

Schließlich wäre noch zu klären, ob die Termine innerhalb eines bestimmten Zeitraums gefunden werden sollen (etwa vom 1. Januar 2012 bis 30. Juni 2012) oder ob einfach eine bestimmte Anzahl an Terminen ermittelt werden soll.

Dies alles deckt das Formular aus Bild 1 ab.

pic001.png

Bild 1: Formular zur Definition von Terminserien

Eine Rahmenbedingung können wir jedenfalls schon festlegen: Der Benutzer soll schlicht eine Funktion namens Terminserie aufrufen und von dieser ein Array mit den entsprechenden Datumsangaben zurückerhalten.

Wenn Termine auf ungünstige Daten fallen

Je nach der Art der zu ermittelnden Terminserie kann es sein, dass die Lösung Termine nicht auf bestimmte Tage setzen kann, beispielsweise bei Samstagen, Sonntagen oder Feiertagen oder wenn der Benutzer etwa den 31. Tag eines Monats als monatlichen oder jährlichen Termin angibt.

Bei ungültigen Terminen wie etwa dem 31. Februar soll die Anwendung den letzten Tag des jeweiligen Monats zurückliefern.

Die Vorgehensweise für Samstage, Sonntage und Feiertage hingegen behandelt der untere Teil des Formulars. Eigentlich sollte die Lösung maximale Flexibilität bieten, indem Sie für Samstage, Sonntage und Feiertage separat eine der folgenden Aktionen auswählen können:

  • Termin auf den vorherigen Tag verschieben
  • Termin auf den folgenden Tag verschieben
  • Termin komplett stornieren

Wenn Sie aber nun festlegen, dass Termine vom Sonntag auf den folgenden Tag verschoben werden, und angeben, dass Termine, die auf Feiertage fallen, ignoriert werden sollen, haben Sie ein Problem, wenn der Tag nach dem Sonntag zufällig ein Feiertag ist. Der zu verschiebende Sonntagstermin würde dann nämlich auf den Feiertag verschoben werden und somit wegfallen.

Also haben wir eine etwas weniger flexible Variante gewählt: Der Benutzer legt dort zunächst fest, ob er Termine, die auf Samstage, Sonntage und/oder Feiertage fallen, gesondert behandeln möchte. Für alle gewählten Fälle gibt er dann an, ob die Termine auf den vorherigen oder den folgenden Tag fallen oder ob diese ignoriert werden sollen.

Formular zur Eingabe der Datumsinformationen

Bild 2 zeigt den Entwurf des Formulars zur Eingabe der Parameter für die Erstellung der Terminserie. Im oberen Bereich wählt der Benutzer zunächst die Art der Terminserie aus. Die dort verwendete Optionsgruppe heißt ogrSerienart. Die Optionen erhalten von oben bis unten die Werte 1 bis 4.

pic002.png

Bild 2: Entwurf des einzigen Formulars der Lösung

Die Optionsgruppe hat standardmäßig den Wert 1 (Täglich). Bis der Benutzer eine andere Option auswählt, sollen die neben den Optionen angezeigten Steuerelemente zur Eingabe weiterer Parameter deaktiviert sein. Erst bei änderung des Wertes von ogrSerienart werden die entsprechenden Steuerelemente aktiviert. Dafür sorgt die Ereignisprozedur, die durch das Ereignis Nach Aktualisierung der Optionsgruppe ausgelöst wird:

Private Sub ogrSerienart_AfterUpdate()
    Me!ogrWoechentlich.Enabled =
    Me!ogrSerienart = 2
    Me!txtTag.Enabled = Me!ogrSerienart = 3
    Me!txtTagJaehrlich.Enabled =
    Me!ogrSerienart = 4
    Me!txtMonatJaehrlich.Enabled =
    Me!ogrSerienart = 4
End Sub

Dies ist eine etwas platzsparende Schreibweise, deren Funktion möglicherweise erst auf den zweiten Blick deutlich wird. Die folgende Zeile etwa sorgt dafür, dass ogrWoechentlich aktiviert wird, wenn die Optionsgruppe ogrSerienart den Wert 2 hat (dann liefert Me!ogrSerienart = 2 den Wert True, was dazu führt, dass auch die Enabled-Eigenschaft von ogrWoechentlich auf True eingestellt wird):

Me!ogrWoechentlich.Enabled = Me!ogrSerienart = 2

Festlegen des Datumsbereichs

Beim Laden des Formulars werden die beiden Textfelder zur Eingabe des Datumsbereichs, txtStart und txtEnde, mit dem aktuellen Datum bestückt.

Außerdem sollen diese mit den Funktionen zur einfachen Datumseingabe, wie im Beitrag Flexible Datumstextfelder (www.access-im-unternehmen.de/690) beschrieben, bestückt werden. Dazu fügen Sie beiden Klassen clsDateboxes und clsDatebox aus der entsprechenden Beispieldatenbank hinzu. Im Kopf des Klassenmoduls des Formulars wird eine Variable zum Speichern der Referenz auf diese Klasse deklariert:

Dim objDateboxes As clsDateboxes

In der Prozedur, die durch das Ereignis Beim Laden des Formulars ausgelöst wird, wird eine entsprechende Instanz erzeugt. Dieser weisen Sie auch gleich die beiden Textfelder txtStart und txtEnde zu:

Private Sub Form_Load()
    Me!txtStart = Date
    Me!txtEnde = Date
    Set objDateboxes = New clsDateboxes
    With objDateboxes
        .AddDatebox Me!txtStart
        .AddDatebox Me!txtEnde
    End With
End Sub

Aufruf des Formulars

Den Einstiegspunkt für die Lösung zum Erstellen von Terminserien bietet die VBA-Prozedur Terminserie, die Sie im Modul mdlTerminserie finden. Diese Prozedur können Sie von beliebigen anderen Modulen aus aufrufen. Sie öffnet das Formular frmTerminserie, ermöglicht dem Benutzer die Eingabe der gewünschten Parameter und liest nach einem Klick auf die OK-Schaltfläche des Formulars die ermittelten Termine aus der öffentlichen Variablen Termine des Formulars aus.

Public Function Terminserie() As Variant
    Dim dat() As Date
    DoCmd.OpenForm "frmTerminserie",
    WindowMode:=acDialog
    If IstFormularGeoeffnet("frmTerminserie") Then
        dat = Forms!frmTerminserie.Termine
        DoCmd.Close acForm, "frmTerminserie"
    End If
    Terminserie = dat
End Function

Die Terminliste kommt als Array und kann anschließend entsprechend weiterverarbeitet werden. Wenn Sie die Termine einfach im Direktfenster ausgeben möchten, verwenden Sie beispielsweise den folgenden Aufruf:

Public Sub Beispielaufruf()
    Dim intCount As Integer
    Dim datTermine() As Date
    Dim i As Integer
    datTermine = Terminserie
    On Error Resume Next
    For i = LBound(datTermine) To UBound(datTermine)
        Debug.Print datTermine(i)
    Next i
    If Err.Number = 9 Then
         Debug.Print "Keine Termine"
    End If
End Sub

Die Funktion ruft die Funktion Terminserie auf, die dafür sorgt, dass das Formular geöffnet wird und anschließend ein Array mit den gefundenen Daten zurückliefert.

In der folgenden Schleife gibt die Prozedur alle gefundenen Daten im Direktfenster aus. Sollte ein leeres Array zurückgeliefert werden, erzeugt der Zugriff auf die Methode LBound einen Fehler – diesen behandeln wir aber entsprechend mit On Error Resume Next und geben einen Hinweis auf das leere Array im Direktfenster aus.

Terminserie erstellen

Es gibt zwei Möglichkeiten, eine Terminserie zu erstellen. Ein Klick auf die OK-Schaltfläche erstellt eine Terminserie und macht dann das Formular frmTerminserie unsichtbar, damit die aufrufende Funktion Terminserie die ermittelten Termine auslesen kann. Sie können aber auch auf die Schaltfläche Termine anzeigen klicken.

Auch die Prozedur, die durch diese Schaltfläche ausgelöst wird, ruft die Funktion Terminserie auf. Allerdings zeigt sie die ermittelten Termine gleich in einem Meldungsfenster an.

Auf diese Weise kann der Benutzer vor dem Schließen des Formulars prüfen, ob dieses die richtigen Termine zurückliefert (s. Bild 3).

pic003.png

Bild 3: Anzeige der gefundenen Termine im Meldungsfenster

Die wesentlichen Schritte beim Füllen des Termin-Arrays erledigt also die Funktion Terminserie (s. Listing 1). Diese Funktion ermittelt die Liste der Termine entsprechend den Einstellungen im Formular und speichert das resultierende Array in einer Variablen, die im Kopf des Moduls deklariert wird:

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