Verjaardaglijst

Stel je hebt een database met persoonsgegevens, waaronder het veld geboortedatum. Je wilt op basis van die gegevens een lijstje maken van personen die de komende tijd jarig zijn. Daarbij wil je ook zien hoe oud de jarige wordt en op welke dag van de week hij verjaart.

Een probleem waar je dan tegenaan loopt is dat je een selectie wilt maken zonder naar de volledige geboortedatum te kijken. Alleen de dag en de maand zijn in dit geval interssant. De functie Format kan ons hierbij helpen. Als een geboortedatum bijvoorbeeld 24-06-1967 is, kunnen we die met Format(Geboortedatum,"mmdd") omzetten in de waarde 0624. Dit helpt ons zowel bij het selecteren van personen als bij het sorteren van de verjaardaglijst.

In mijn voorbeelddatabase heb ik een formulier gemaakt waarin je de periode waarover je de verjaardagen wilt weten op kunt geven. Je doet dat door twee datums in het formaat dd-mm op te geven. Als je bijvoorbeeld alle verjaardagen in juni wilt weten geef je 01-06 en 30-06 op. Om te zorgen altijd een geldige periode opgegeven wordt, moet we van beide formuliervelden de eigenschappen Notatie en Invoermasker correct instellen op dd-mm respectievelijk 00-00. Het streepje hoef je dan niet in te tikken; dat wordt automatisch geplaatst.

Een bijzonderheid waar we rekening mee moeten houden is het feit dat in de opgegeven periode een jaarovergang kan zitten. Als je in november wilt weten wie er in december en januari jarig zijn geef je 01-12 als Van op en 31-01 als T/M. In een selectiequery kan Van echter niet groter zijn dan T/M. Daarom moeten we onder water de periode in twee stukken knippen: 01-12 t/m 31-12 en 01-01 t/m 31-01.

Op het formulier waar je de datums ingeeft staat ook een opdrachtknop om het lijste af te drukken. Onder die knop staat:
Private Sub selectie_Click()

If IsNull(Me.Van) And IsNull(Me.TM) Then
   DoCmd.OpenReport "Verjaardagslijst", acViewPreview
   GoTo Klaar
End If

If Not IsNull(Me.Van) And IsNull(Me.TM) Then
   DoCmd.OpenReport "Verjaardagslijst", acViewPreview, , _
      "Format(Geboortedatum,'mmdd')>='" & Format(Me.Van, "mmdd") & "'"
   GoTo Klaar
End If

If IsNull(Me.Van) And Not IsNull(Me.TM) Then
   DoCmd.OpenReport "Verjaardagslijst", acViewPreview, , _
      " Format(Geboortedatum,'mmdd')>='" & Format(Date, "mmdd") & _
      "' AND" & " Format(Geboortedatum,'mmdd')<='" & Format(Me.TM, "mmdd") & "'"
   GoTo Klaar
End If

If Me.Van <= Me.TM Then
   DoCmd.OpenReport "Verjaardagslijst", acViewPreview, , _
      "Format(Geboortedatum,'mmdd')>='" & Format(Me.Van, "mmdd") & _
      "' AND Format(Geboortedatum,'mmdd')<='" & Format(Me.TM, "mmdd") & "'"
Else
   DoCmd.OpenReport "Verjaardagslijst", acViewPreview, , _
      "Format(Geboortedatum,'mmdd')>='" & Format(Me.Van, "mmdd") & "'" & _
      " OR Format(Geboortedatum,'mmdd')<='" & Format(Me.TM, "mmdd") & "'"
End If

Klaar:
End Sub

Als zowel Van als T/M leeg gelaten zijn, wordt de lijst met alle personen uit de tabel afgedrukt. Als een van beide of beide velden ingevuld zijn passen we bij het openen van het rapport een where-voorwaarde toe. In die voorwaarden zetten we alle data om naar het formaat MMDD, zodat ze vergelijkbaar zijn.

Om het rapport er op de gewenst manier uit te krijgen moet er ook in het rapportontwerp nog een en ander gebeuren.

Zo willen dat het lijstje gesorteerd wordt op oplopende verjaardatum. Dat betekent dat als we in november de verjaardagen van december en januari willen uitdraaien, eerst die van december getoond moeten worden en dan die van januari. Sorteren op MMDD werkt dan dus niet. In plaats daarvan gaan we sorteren op datum volgende verjaardag. Uitgaande van een actuele datum in november valt voor iemand die in december jarig is de volgende verjaardag in december van dit jaar en voor iemand die in januari verjaart in januari volgend jaar. Dat is dus wel een bruikbaar gegeven om op te sorteren. Met behulp van een zelf gemaakt functie rekenen we op basis van de geboortedatum en de actuele datum de volgende verjaardag van een persoon uit. De functie zie er zo uit:
Function VolgendeV(Geboortedatum As Date) As Date
Dim Jaar As Integer
Dim Maand As Byte
Dim Dag As Byte

Maand = DatePart("m", Geboortedatum)
Dag = DatePart("d", Geboortedatum)

If Maand = DatePart("m", Date) Then
   If Dag < DatePart("d", Date) Then
      Jaar = DatePart("yyyy", Date) + 1
   Else
      Jaar = DatePart("yyyy", Date)
   End If
Else
   If Maand < DatePart("m", Date) Then
      Jaar = DatePart("yyyy", Date) + 1
   Else
      Jaar = DatePart("yyyy", Date)
   End If
End If

VolgendeV = CDate(Dag & "-" & Maand & "-" & Jaar)
End Function

De clou van de functie is dat je op basis van de maand en dag uit de geboortedatum en de maand en dag uit de actuele datum (Date) afleidt of de verjaardag dit jaar al gepasseerd is of niet. Afhankelijk daarvan weet je het jaar van de volgende verjaardag. Samen met de uit de geboortedatum bekende dag en maand kunnen we dan een datum in elkaar draaien.

Op het rapport willen we ook zien hoe oud het feestvarken wordt. Ook daarvoor maken we een functie die op basis van de geboortedatum uitrekent hoe oud iemand is op een bepaalde peildatum. In het rapport gaan we de zojuist bepaalde datum volgende verjaardag als peildatum gebruiken. Dit is de functie:
Function LeeftijdOp(Geboortedatum As Date, Peildatum As Date) As Byte
If Format(Geboortedatum, "mmdd") > Format(Peildatum, "mmdd") Then
   LeeftijdOp = DateDiff("yyyy", Geboortedatum, Peildatum) - 1
Else
   LeeftijdOp = DateDiff("yyyy", Geboortedatum, Peildatum)
End If
End Function

Ook in deze functie passen we het principe toe dat we kijken of verjaardag in het jaar van de peildatum al dan niet gepasseerd is.

We hebben nu alle ingrediënten bij elkaar op het lijstje af te drukken. De recordbron van het rapport is:
SELECT Naam, Geboortedatum, Format([Geboortedatum],"dd mmmm (dddd)") AS Dag,
       VolgendeV([Geboortedatum]) AS Verjaardag,
       LeeftijdOp([Geboortedatum],VolgendeV([Geboortedatum])) AS Leeftijd
FROM Persoon ORDER BY VolgendeV([Geboortedatum]);

Klik hier om de voorbeelddatabase te downloaden.