Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 4/2010.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Zusammenfassung

Erweitern Sie Ihre Anwendung um eine ergonomische Eingabemöglichkeit für Datumsbereiche.

Techniken

Formulare, Bezeichnungsfeld, Klassen

Voraussetzungen

Access 2002 und höher

Beispieldateien

Datumsauswahl.mdb

Shortlink

www.access-im-unternehmen.de/729

Datumsbereiche auswählen

André Minhorst, Duisburg

Das aktuelle Datum ist unter Access schnell eingegeben - es reicht die Tastenkombination Strg + Semikolon. Sonstige Daten wählt man ab Access 2007 schnell mit dem eingebauten Datepicker aus. Oder Sie verwenden die Lösung aus dem Beitrag »Flexible Datumsfelder« (www.access-im-unternehmen.de/690). Wenn Sie aber gleich einen Zeitraum, bestehend aus zwei Datumsangaben, eingeben müssen, brauchen Sie größere Kaliber - so eines wie wir im vorliegenden Beitrag beschreiben.

Viele Anwendungen erfordern die Eingabe nicht nur eines einzigen Datums, sondern gleich eines ganzen Bereichs. Das sieht im einfachsten Fall wie in Abb. 1 aus.

pic001.png

Abb. 1: Einfaches Beispiel für die Eingabe eines Datumsbereichs

Das dort dargestellte Formular enthält zwei Textfelder zur Eingabe des Start- und des Enddatums. Das Ziel dieses Beitrags ist, ein Formular zu erstellen, das entweder per Doppelklick in eines der betroffenen Datumsfelder oder über eine entsprechende Schaltfläche angezeigt werden kann. Es soll gegebenenfalls einen eventuell bereits in den Textfeldern vorhandenen Datumsbereich gleich beim Öffnen anzeigen und die Möglichkeit bieten, diesen anzupassen beziehungsweise neu zu setzen.

Am einfachsten wäre die Auswahl eines Datumsbereichs, wenn diese mit einer Mausgeste funktionieren könnte - Klick auf das erste Datum in einer Datumsübersicht, mit gedrückter Maus zum zweiten Datum fahren, loslassen, fertig. Aber wie lässt sich dies realisieren? Zunächst einmal benötigen wir ein Formular, das die infrage kommenden Datumsangaben zur Auswahl anzeigt. Und bevor dieses überhaupt irgendein Datum anzeigt, müssen wir uns erstmal überlegen, welche Zeiträume überhaupt erfassbar sein sollen. Zeiträume in der Vergangenheit? In der Zukunft? Oder einfach ein paar Monate vor und hinter dem aktuellen Datum? Nun: Wenn uns diese Frage am Erstellen einer schicken Lösung hindert, dann parametrisieren wir dies einfach und legen je nach Anwendung fest, wie der Zeitraum aussehen soll.

Wie aber soll die Datumsübersicht zur Auswahl eines Datumsbereichs genau aufgebaut sein? Angenommen, wir würden jeweils ein Jahr abdecken, wobei wir ein bestimmtes Intervall im Code festlegen und dem Benutzer die Möglichkeit geben, monatsweise vor- und zurückzublättern, wäre eine zeilenweise Anzeige der Monate mit ihren Tagen wohl am geeignetsten.

Bauen wir also zunächst ein Formular, das für jeden Tag eines Jahres ein Steuerelement enthält und das wie in Abb. 2 aussieht.

pic002.png

Abb. 2: So soll das Formular für die Datumsauswahl später aussehen.

Das Formular soll nach folgenden Regeln arbeiten:

  • Wenn keines der beiden Datumsfelder des aufrufenden Formulars gefüllt ist, wird das aktuelle Datum als Start- und Enddatum verwendet - es wird also nur der aktuelle Tag markiert.
  • Wenn das Startdatum angegeben ist und kein Enddatum, wird das Enddatum gleich dem Startdatum gesetzt und dieses im Formular zur Datumsauswahl eingestellt.
  • Gleiches gilt umgekehrt, wenn nur das Enddatum angegeben ist.
  • Wenn beide Daten angegeben sind, aber das Enddatum vor dem Startdatum liegt, werden die Daten einfach vertauscht und der entsprechende Zeitraum angezeigt.

Einsatz des Datumsauswahlformulars

Möglicherweise möchten Sie gar nicht so genau wissen, wie dieses Formular funktioniert, sondern es einfach nur in Ihren eigenen Anwendungen einsetzen. Für diesen Fall erfahren Sie nun, wie Sie diese Lösung in eine eigene Anwendung integrieren und verwenden. Zuerst importieren Sie die folgenden Elemente der Beispieldatenbank in die Zielanwendung:

  • Formular frmDatumsauswahl
  • Klassenmodul clsDatumsauswahl
  • Klassenmodul clsLabel
  • Standardmodul mdlDatumsauswahl

Anschließend benötigen Sie nur noch ein paar Zeilen Code, die Sie für die Ereignisprozedur Beim Laden des betroffenen Formulars hinterlegen.

Hierzu gehen Sie folgendermaßen vor:

  • Öffnen Sie das Formular mit den beiden Datumsfeldern in der Entwurfsansicht.
  • Wählen Sie auf der Registerseite Ereignis für die Eigenschaft Beim Laden den Wert [Ereignisprozedur] aus und klicken Sie auf die Schaltfläche mit den drei Punkten (s. Abb. 3).
  • Fügen Sie den Code aus Listing 1 hinzu.
pic003.png

Abb. 3: Anlegen des Ereignisses, das unser Formular um die Funktion zum Auswählen von Datumsbereichen erweitern soll

Listing 1: Füllen der Tabelle tblSuchfelder mit allen möglichen Suchfeldern

Dim objDatumsauswahl As clsDatumsauswahl

Private Sub Form_Load()

  Set objDatumsauswahl = New clsDatumsauswahl

  With objDatumsauswahl

    Set .Form = Me

    Set .StartdateTextbox = Me!txtStartdatum

    Set .EnddateTextbox = Me!txtEnddatum

  End With

End Sub

Fertig! Sie brauchen nun nur noch in die Formularansicht zu wechseln und einen Doppelklick auf einem der Textfelder auszuführen.

Erstellung und individuelle Anpassung

Nach der Einführung geht es an die technischen Hintergründe. Die erste Frage ist: Wie stellen wir die ganzen Tage der Jahresübersicht dar? Die Antwort lautet: Mit Bezeichnungsfeldern. Diese bieten, wie wir gleich sehen werden, alle notwendigen Ereignisprozeduren, sie können Texte anzeigen und wir können verschiedene Hintergrundfarben für sie einstellen.

Welche Elemente brauchen wir für das Formular?

  • Ein Bezeichnungsfeld als Beschriftung der Zeilen- und Spaltenüberschriften (Monat/Tag),
  • 12 Bezeichnungsfelder für die Monate (Zeilenüberschriften),
  • 37 Bezeichnungsfelder für die Spaltenüberschriften, die durchlaufend mit den Anfangsbuchstaben der Wochentage belegt werden - die Samstage und Sonntage werden zusätzlich fett gedruckt, um eine einfachere Orientierung zu ermöglichen, und
  • 366 Bezeichnungsfelder für die eigentlichen Tage. Das letzte davon brauchen wir allerdings nur alle vier Jahre.

Die ersten drei Kategorien von Bezeichnungsfeldern erhalten immer die gleiche Position - egal, welche Monate welchen Jahres angezeigt werden. Es ändern sich lediglich die Beschriftungen der Zeilenüberschriften, also die Monate.

Die 366 Bezeichnungsfelder für die Tage werden je nach Startmonat unterschiedlich in der Matrix zwischen Monaten und Tagen aufgeteilt. Das liegt daran, dass wir in den Spaltenüberschriften feste Wochentage festlegen und die Datumsangaben eines jeden Monats daran ausrichten müssen. Der 1. Januar 2010 ist beispielsweise ein Freitag, der 1. Februar 2010 ein Montag. Dementsprechend besitzt der erste Tag eines jeden Monats einen unterschiedlichen Abstand zum linken Rand, die übrigen Tage reihen sich dahinter ein.

Und auch die Beschriftungen müssen je nach dem in der ersten Zeile angezeigten Monat dynamisch angepasst werden. Für diese Lösung schien es am sinnvollsten, die Bezeichnungsfelder für die Tage schlicht von 001 bis 366 durchzunummerieren und den Rest zur Laufzeit einzustellen. Beim Erstmaligen Anlegen werden diese Steuerelemente also einfach links oben im Formularentwurf abgelegt.

Erstellen des Formulars zur Anzeige des Jahreskalenders

Zu Beginn bekommen wir es gleich mal mit einer richtigen Fleißaufgabe zu tun: Das Anlegen der Bezeichnungsfelder. Wenn wir richtig gezählt haben, kommen wir immerhin auf 416 Felder, die wir anlegen und mit Namen versehen müssen. Einige davon, die als Spalten- und Zeilenüberschriften dienen, müssen wir gar noch genau ausrichten. Das Ausrichten müssen wir anschließend wahrscheinlich noch mehrfach wiederholen, da wir ja die Breite und Höhe der Felder mit denen der 366 Bezeichnungsfelder abstimmen müssen, welche die Tage anzeigen.

Na, klingelt's? Das ist natürlich keine Aufgabe für Access im Unternehmen-Leser. Dafür stellen wir entweder einen Hilfsprogrammierer ein oder - noch besser - Sie automatisieren das Ganze.

Immerhin stellt Access-VBA einige Methoden zur Verfügung, um nicht nur Formulare, sondern auch die enthaltenen Steuerelemente anzulegen und mit den gewünschten Eigenschaften zu versehen.

Bevor Sie beginnen, legen Sie ein Formular namens frmDatumsauswahl an und stellen seine Eigenschaften Navigationsschaltflächen, Bildlaufleiste, Datensatzmarkierer und Trennlinie auf Nein und Automatisch zentrieren auf Ja ein.

Anschließend rufen Sie einfach die Prozedur SteuerelementeErstellen auf. Das Ergebnis sieht wie in Abb. 4 aus, die übrigen dort sichtbaren Steuerelemente legen wir später an.

pic004.png

Abb. 4: Das Formular zur Datumsauswahl mit allen Steuerelementen in der Entwurfsansicht

Listing 2 zeigt den Code, der für das Anlegen der Bezeichnungsfelder nötig ist. Zu Beginn schließt die Prozedur das Formular, falls dieses noch geöffnet ist. Dann öffnet sie das Formular in der Entwurfsansicht und füllt die Objektvariable frm mit einem Verweis auf das Formular, um später einfacher darauf verweisen zu können.

Listing 2: Füllen des Formulars mit den nötigen Bezeichnungsfeldern

Public Sub SteuerelementeErstellen()

  Dim frm As Form

  Dim ctl As Control

  Dim strForm As String

  Dim i As Integer

  DoCmd.Close acForm, "frmDatumsauswahl"

  DoCmd.OpenForm "frmDatumsauswahl", acDesign

  Set frm = Forms!frmDatumsauswahl

  For i = frm.Controls.Count To 1 Step -1

    Application.DeleteControl "frmDatumsauswahl", frm.Controls(i - 1).Name

  Next i

  Set ctl = Application.CreateControl(strForm, acLabel, acDetail, , , cBorder, cBorder, 6 * cMass, cMass)

  ctl.Name = "lblTopLabel"

  ctl.Caption = "Monat/Tag"

  ctl.FontWeight = 700

  For i = 1 To 12

    Set ctl = Application.CreateControl(strForm, acLabel, acDetail, , , cBorder, _

      i * cMass + cBorder, 6 * cMass, cMass)

    ctl.Name = "lblLabel" & Format(i, "000")

    ctl.FontWeight = 700

  Next i

  For i = 0 To 36

    Set ctl = Application.CreateControl(strForm, acLabel, acDetail, , , _

      cBorder + (i + 6) * cMass, cBorder, cMass, cMass)

    ctl.Name = "lblTop" & Format(i, "000")

    ctl.Caption = Choose(i Mod 7 + 1, "M", "D", "M", "D", "F", "S", "S")

    ctl.FontWeight = CBool(i Mod 7 > 4) * -700

  Next i

  For i = 1 To 366

    Set ctl = Application.CreateControl(strForm, acLabel, acDetail, , , 0, 0, cMass, cMass)

    ctl.Name = Format(i, "000")

  Next i

  DoCmd.Close acForm, strForm, acSaveYes

End Sub

Da wir diese Prozedur wie oben angekündigt wohl öfter durchlaufen müssen, löschen wir zu Beginn jeweils die bereits vorhandenen Bezeichnungsfelder, deren Name entweder mit lbl beginnt oder nur aus Zahlen besteht (IsNumeric).

Auf diese Weise verhindern wir, dass bereits bestehende Steuerelemente, wie die in Abb. 4 bereits sichtbaren Schaltflächen, jedesmal neu anlegen müssen.

Die For...Next-Schleife zum Löschen der Bezeichnungsfelder ermittelt zunächst die Anzahl der Bezeichnungsfelder und löscht diese dann, wobei sie beim letzten Bezeichnungsfeld beginnt (anderenfalls würde die For...Next-Schleife durch das Löschen von Elementen mit dem Index durcheinanderkommen).

Beim Löschen kommt die Methode DeleteControl zum Einsatz, die schlicht den Formular- und den Steuerelementnamen als Parameter erwartet.

Die folgenden vier Anweisungen erstellen das Bezeichnungsfeld mit der Beschriftung Monat/Tag, das ganz links oben positioniert wird. Das Erstellen übernimmt die Methode CreateControl, der wir den Namen des Zielformulars, die Steuerelementart (acLabel), den Detailbereich als Zielbereich (acDetail) sowie die linke und obere Position und die Höhe und Breite mitgeben.

Die hier verwendeten Konstanten werden im Modul mdlDatumsauswahl deklariert:

Public Const cMass As Integer = 300

Public Const cBorder As Integer = 80

cBorder gibt dabei den Standardabstand zum Formularrahmen an und cMass liefert die Standardbreite und -höhe eines der 366 Tag-Bezeichnungsfelder.

Die Breite der Zeilenüberschriften muss bei der Schriftart und -größe aus Abb. 2 sechs Mal so breit sein wie die der Tag-Bezeichnungsfelder, deshalb taucht in der Anweisung der Ausdruck 6 x cMass auf. Die folgenden drei Anweisungen legen Name, Beschriftung und Schriftbreite des frisch angelegten Steuerelements fest.

Nachdem wir nun vier Zeilen zum Anlegen eines einzigen Steuerelements benötigt haben, geht es ab jetzt etwas effizienter zu: Die Anweisungen der folgenden For...Next-Schleife zeichnen immerhin für das Anlegen von zwölf Steuerelementen verantwortlich, nämlich der Zeilenüberschriften mit den Monatsnamen.

Auch hier erstellt die CreateControl-Methode die Bezeichnungsfelder, wobei hier bei der Angabe des Abstands vom oberen Rand eine Variable ins Spiel kommt: i * cMass + cBorder. Dadurch werden die Steuerelemente jeweils um cMass nach unten versetzt.

Auch der Name des Steuerelements wird in Abhängigkeit von der Laufvariablen i vergeben (lblLabel001, lblLabel002...).

Für die Zeilenüberschriften benötigen wir genau 37 Steuerelemente. Warum gerade 37? Ein Monat kann an jedem Tag von Montag bis Sonntag beginnen und hat maximal 31 Tage. Der erste Tag liegt also im Extremfall auf der siebten Position von links, plus die fehlenden maximal 30 Tage ergibt 37 Tage. Die For...Next-Schleife mit den Anweisungen zum Anlegen der Spaltenüberschriften läuft von 0 bis 36. Die Steuerelemente werden mit dem Abstand cBorder + (i + 6) * cMass vom linken Rand angelegt.

Beim ersten Element ist i = 0, es beginnt also genau am rechten Rand des ganz links oben positionierten Bezeichnungsfeldes Monat/Tag. Die übrigen Elemente werden dann jeweils um die Breite eines Elements nach rechts verschoben, damit alle genau nebeneinanderliegen. Der Name wird auf lblTop001, lblTop002... festgelegt. Der Ausdruck für die Bezeichnung ist erklärungsbedürftig:

Choose(i Mod 7 + 1, "M", "D", "M", "D", "F", "S", "S")

Die Choose-Methode erwartet im ersten Parameter einen Index für die Auswahl der in der folgenden Parameterliste enthaltenen Elemente. Ist der erste Wert 1, dann liefert sie "M" zurück, ist der Wert 7, heißt der Rückgabewert "S".

Interessant ist die Ermittlung des Indexes: Dieser basiert wiederum auf der Laufvariablen i der For...Next-Schleife. i wird durch 7 geteilt und mit Mod der Rest ermittelt, zu dem noch der Wert 1 hinzuaddiert wird. Ist i also beispielsweise 0, lautet der Index 1. Die ganz linke Spaltenüberschrift soll also die Beschriftung "M" für Montag erhalten.

Für die elfte Spalte hat i den Wert 10. 10 Mod 7 liefert den Rest 3, plus 1 ergibt 4. Die zehnte Spaltenüberschrift lautet "D" für Donnerstag. Sie sehen: Man kann in einer Zeile Funktionalität unterbringen, die zwar auch ohne Verwendung spezieller VBA-Funktionen möglich ist, aber wesentlich mehr Zeilen benötigen würde.

Fehlen noch die 366 Bezeichnungsfelder für die eigentlichen Tage. Die For...Next-Schleife durchläuft folgerichtig 366 Elemente, wobei einfach nur Bezeichnungsfelder mit dem Namen 001, 002... und der Höhe und Breite cMass angelegt werden.

Den Rest erledigen wir zur Laufzeit, denn die Position und Beschriftung der Steueuerelemente ist ohnehin von den jeweils anzuzeigenden Monaten abhängig. Sie könnten maximal die ersten 28 Elemente mit den Zahlen 1 bis 28 beschriften, aber bereits die Position dieser Elemente kann erst festgelegt werden, wenn der Monat bekannt ist, der in der ersten Zeile angezeigt werden soll: Sie wissen einfach vorher nicht, auf welchen Wochentag der erste Tag des jeweiligen Monats fällt.

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Verwandte Beiträge:

Flexible Datumstextfelder

Formularposition speichern und wiederherstellen

Modale Dialoge mal anders

Transparenz und andere Effekte in Formularen

Formulare für die Dateneingabe

Mit Zeiten rechnen

Validieren mit Klasse

© 2003-2015 André Minhorst Alle Rechte vorbehalten.