DatePicker selbstgemacht

By , 6. September 2008

Zur Auswahl eines Datums ist das DateTime Picker Control sehr gut geeignet – will man jedoch die Datenbank an den Kunden weitergeben hakt es meistens an dem ActiveX Control. Daher sollte man mit ActiveX Steuerelementen sparsam umgehen, und wenn möglich ganz darauf verzichten. Dieser Beitrag beschreibt wie man ein professionelles DatePicker Steuerelement selbst mit Access-Bordmitteln erstellt.

Zuerst benötigen wir ein Formular, das als DatePicker dient. Wir wollen ja uns streng am Orginal Orientieren, also benötigen wer zuerst ein Bezeichnungsfeld 0,8 x 4,2 cm, und Hintergrundfarbe 14215660, Rahmen Flach und Transparent. In diesem „Kopfbereich“ plazieren wird links und rechts 2 kleine Buttons, namens „Vor“ und „Zurueck“, und wählen als Bild „gehe zum nächsten2“ sowie „gehe zum vorherigen2“ aus. Dazwischen plazieren wir ein Bezeichnisfeld mit Namen „MonatJahr“, das Monat und Jahr anzeigen soll.
Hier mal eine kleine Vorschau auf den fertigen DatePicker:

DatePicker

Darunter beginnen wir mit den Wochentagen, also 7 Bez.Felder plaziert und mit Mo, Di, … bis So beschriftet.
Darunter beginnt dann unser Kalender. Dazu benötigen wird 6 x 7 Bez.Felder, benennt diese z.B. k1 bis k42. Ihr müsst eine Beschriftung angeben damit diese überhaupt erstellt werden, wählt einfach eine beliebige Zahl aus, z.B. die 1.
Bei dem Ereignis „Beim Klicken“ gebt ihr direkt =kclick(1 bis 42) ein, analog der Eigenschaft Name (k1 bis k42).

Eigenschaften (auch für Wochentage):

  • Breite x Höhe: 0,6 x 0,4cm
  • Hintergrund: normal, Farbe 16777215
  • Rahmen: Flach, Transparent
  • Schrift: Normal, MS Sans Serif, 8px, Zentriert

Als Letztes darunter noch ein Bez.Feld mit Namen „Heute“, das den aktuellen Tag anzeigen soll.
Damit alles schön untereinander passt, markiert ihr die Felder und klickt rechts auf Ausrichten und richtet oben und links aus.

Jetzt wird um alle Felder herum ein Rechteck gezogen, das die Eigenschaft Hintergrund Transparent und Rahmen Graviert und Durchgezogen besitzt. Unter dem Rahmen mit etwas Abstand ein Button „close“ mit Beschriftung „schließen“

Jetzt erstellen wir noch 3 Textfelder (ohne Bez.Feld), machen diese ganz klein und stellen die Eigenschaft Sichtbar auf nein. Die Namen sind: kday, kmonth und kyear, darin wird das aktuelle Datum gespeichert. Nachfolgend ein Blick auf die Entwurfsansicht:

Kommen wird nun zum Code:
Der Modulcode des Formulars sieht wie folgt aus:

Option Compare Database
Option Explicit
Dim ende As Boolean

Public Sub kclick(kd As Integer)
    If Not ende Then
        Call klickauswertung(kd)
    End If
    ende = True
End Sub

Private Sub Heute_Click()
    Dim d As Date
    d = Date
    Me!kyear = year(d)
    Me!kmonth = Month(d)
    KalenderFuellen Me!kmonth, Me!kyear
End Sub

Private Sub Form_Open(Cancel As Integer)
    Dim d As Date
    d = Date
    Me!kyear = year(d)
    Me!kmonth = Month(d)
    KalenderFuellen Me!kmonth, Me!kyear
End Sub

Private Sub Vor_Click()
    Vor_Zurueck 1
End Sub

Private Sub Zurueck_Click()
    Vor_Zurueck -1
End Sub

Private Sub Vor_Zurueck(Incr As Long)
    Dim d As Date
    d = DateSerial(Me!kyear, Me!kmonth + Incr, 1)
    Me!kmonth = Month(d)
    Me!kyear = year(d)
    KalenderFuellen Me!kmonth, Me!kyear
End Sub

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

Zusätzlich wird ein Modul benötigt, für das Füllen des Kalenders und der Auswertung des Klick-Ereignisses:
Erstellt ein Modul und fügt folgenden Code ein.
Der Code für die Anzeige der Kalendertage stammt größtenteils aus dem Beispiel „ACSampleKalender97.mdb“ von www.dbWiki.de, den Autoren sei an dieser Stelle gedankt.
Code:

Option Compare Database
Option Explicit

Private datMonatsanfang As Date
Private datMonatsende As Date
Private Offset As Long
Public dpfieldname As String
Global dpfrm As Form

Public Sub DatePicker(Formname As String, Buttonname As String, textfieldname As String)
    Dim btn As CommandButton, frm As Form
    Set dpfrm = Forms(Formname)
    Set btn = dpfrm.Controls(Buttonname)
    dpfieldname = textfieldname
    DoCmd.OpenForm "DatePicker"
    Forms!DatePicker.Move btn.Left, btn.Top + btn.Height
    Set btn = Nothing
End Sub

Public Sub klickauswertung(kd As Integer)
    Dim d As Date, frm As Form, ctl As Control
    On Error GoTo klickauswertung_Error

    Set frm = Forms("DatePicker")
    If frm("k" & kd).Tag = "premonth" Then
        If frm!kmonth - 1 = 0 Then
            frm!kmonth = 12
            frm!kyear = frm!kyear - 1
        Else
            frm!kmonth = frm!kmonth - 1
        End If
        d = DateSerial(frm!kyear, frm!kmonth, frm("k" & kd).Caption)
    ElseIf frm("k" & kd).Tag = "nextmonth" Then
        If frm!kmonth + 1 = 13 Then
            frm!kmonth = 1
            frm!kyear = frm!kyear + 1
        Else
            frm!kmonth = frm!kmonth + 1
        End If
        d = DateSerial(frm!kyear, frm!kmonth, frm("k" & kd).Caption)
    Else
        d = DateSerial(frm!kyear, frm!kmonth, frm("k" & kd).Caption)
    End If
    Call KalenderFuellen(frm!kmonth, frm!kyear)

    Set ctl = dpfrm.Controls(dpfieldname)
    ctl.Value = d
    Set ctl = Nothing
    
    DoCmd.Close acForm, frm.Name

Exit_klickauswertung:
    Exit Sub

klickauswertung_Error:
    MsgBox Err.Description
    Resume Exit_klickauswertung
End Sub

Public Sub KalenderFuellen(Monat As Long, Jahr As Long)
    Dim I As Long, J As Long, d As Date, frm As Form
    Set frm = Forms("DatePicker")

    'Monatsanfang & -ende bestimmen
    datMonatsanfang = CDate("1." & Monat & "." & Jahr)
    datMonatsende = DateAdd("m", 1, datMonatsanfang)    ‘l;+ 1 Monat
    datMonatsende = DateAdd("d", -1, datMonatsende)    ‘l;- 1 Tag

    'Offset setzen
    Offset = Weekday(datMonatsanfang, vbMonday)    ‘l;vbMonday um die Woche mit Montag zu beginnen
    If Offset < 2 Then Offset = 8

    'Alle Labels zurücksetzen
    For I = 1 To 42
        frm("k" & I).BackColor = 16777215
        frm("k" & I).BorderStyle = 0
        frm("k" & I).Tag = ""
    Next I

    'Labels des vorherigen Monats setzen
    If Offset > 1 Then
        For I = Offset - 1 To 1 Step -1
            d = DateAdd("d", I - Offset, datMonatsanfang)
            frm("k" & I).Caption = Day(d)
            frm("k" & I).ForeColor = RGB(128, 128, 128)
            frm("k" & I).Tag = "premonth"
        Next I
    End If

    'Labels des aktuellen Monats setzen
    For I = 0 To Day(datMonatsende) - 1
        d = DateSerial(Jahr, Monat, I + 1)
        frm("k" & I + Offset).Caption = I + 1
        frm("k" & I + Offset).ForeColor = &H80000012

        If CStr(d) = Format(Now, "dd.mm.yyyy") Then
            frm("k" & I + Offset).BackColor = 65535
            frm("k" & I + Offset).BorderStyle = 1
        End If
    Next I

    'Labels des Folgemonats setzen
    For J = 1 To 42 - I - Offset + 1
        d = DateSerial(Jahr, Monat + 1, J)
        frm("k" & I + J + Offset - 1).Caption = J
        frm("k" & I + J + Offset - 1).ForeColor = RGB(128, 128, 128)
        frm("k" & I + J + Offset - 1).Tag = "nextmonth"
    Next J

    frm!MonatJahr.Caption = Format(DateSerial(frm!kyear, frm!kmonth, 1), "mmmm") & " " & frm!kyear
    frm!Heute.Caption = " Heute: " & Format(Now(), "dd.mm.yyyy")
End Sub

Eine wichtige Sache habe ich vergessen:
Stellt die Hintergrundfarbe des Detailbereiches auf weiss, und passt die Größe so an dass sie minimal ist. Dann stellt ihr folgende Eigenschaften auf nein: Bildlaufleisten, Datensatzmarkierer, Navigationsschaltflächen, Trennlinien, automatisch Zentrieren. Die Eigenschaften Popup, Gebunden und Größe anpassen auf ja stellen, Rahmenart auf „keine“ stellen. Wichtig ist auch dass der Name des Formulars „DatePicker“ lauten muss.
Gebunden bedeutet, dass der Datepicker den Fokus behält bis er geschlossen wird.

Nun aber ist unser DatePicker fertig. Wie man ihn einsetzt zeige ich euch im folgenden:

Ihr benötigt ein Textfeld, und dahinter ein Button. Ich verwende als Einstellung Breite x Höhe: 0,5 x 0,5cm. Außerdem als Bild „Kalender“. Im Ereignis „Beim Klicken“ fügt ihr folgenden Code ein:

Call DatePicker(Me.Name, "cmdDatum", "txtDatum")

cmdDatum ist der Name des Buttons, txtDatum ist der Name des Textfeldes. Der DatePicker wird dann automatisch unterhalb des Buttons plaziert. Durch Klick auf ein Datum wird er geschlossen und das Datum eingetragen.

Wenn ihr nicht mit der Anleitung zurecht kommt, dann schickt einfach eine Email, ich schicke ihn dann euch kostenlos zu.

AV 2008

9 Responses to “DatePicker selbstgemacht”

  1. Nils Körber sagt:

    Hallo Andreas,
    ich erstelle im Zweitberuf Access-Applikationen, die bei Ärzten eingesetzt werden. Diese Applikationen werden im Auftrag eines Sponsors erstellt und dann (kostenlos) an die Ärzte verteilt. Beispiel: RheumaDok, siehe meine Website.
    Ich möchte die Datumseingabe gerne etwas schöner gestalten und bin auf Ihren DatePicker gestoßen, der mir gut gefallen hat.
    Frage: Würden Sie mir erlauben, Ihren DatePicker in meinen Applikationen zu verwenden?
    Eine Erwähnung in der Bedienungsanleitung wäre Ihnen sicher, wenn gewünscht.
    Grüße aus Erlangen!
    Nils Körber

  2. Matthias sagt:

    Hallo Andreas,

    vielen Dank für deine Mithilfe. Ist ja super, dass das so schnell klappt. Allerdings erscheint bei mir eine Fehlermeldung, wenn ich aus dem Datepicker (im Unterformular) ein Datum anklicke.
    Ich versuche es morgen aber mal trotzdem nach der Text-Anleitung.

    Vielen Dank und schöne Grüße aus NRW

    Matthias

  3. Andreas Vogt sagt:

    Hallo Matthias,
    für die Verwendung im Unterformular muss man den Code anpassen und beim Aufruf ein paar Parameter mehr mitgeben.

    Ich habe mal eine neue Beispieldatenbank (Acc 2002) erstellt und die Erklärung aktualisiert.

    Zum Testen das Formular UnterformularStart öffnen.

    Gruß Andreas

    zum Downloadbereich: http://www.accessblog.de/downloads

  4. Matthias sagt:

    Hallo,

    vielen Dank für deine Anleitung. Der Datepicker funktioniert bei mir reibungslos. Allerdings habe ich ein Problem bzw. eine Frag:

    Wie muss ich den Code abändern, dass diese Funktion auch in einem Unterformular funktioniert? Dort sagt er mir nämlich immer, dass mein Formular, in dem der Button eingesetzt wird, nicht gefunden wird.

    Vielen Dank und liebe Grüße
    Matthias

  5. Andreas Vogt sagt:

    Überarbeitete Version für Access 97 steht nun auch als Download zur Verfügung:
    http://www.accessblog.de/?dl_id=4

  6. Andreas Vogt sagt:

    Hinweis: Obiger Code funktioniert nicht mit Access 97 oder früher.

  7. Andreas Vogt sagt:

    Achtung!
    Funktion Vor_Zurueck geändert!
    Sie lautet nun wie folgt:

    Private Sub Vor_Zurueck(Incr As Long)
    Dim d As Date
    d = DateSerial(Me!kyear, Me!kmonth + Incr, 1)
    Me!kmonth = Month(d)
    Me!kyear = year(d)
    KalenderFuellen Me!kmonth, Me!kyear
    End Sub

    Geändert wurde die Zeile d = DateSerial(…
    Gruß Andreas Vogt

  8. Italiak1 sagt:

    Thank you for valuable information.

OfficeFolders theme by Themocracy