Calculating Length of Service where one field has a Null Value (1 Viewer)

Pauline123

Registered User.
Local time
Today, 22:29
Joined
Apr 1, 2013
Messages
69
Hi hoping someone can help. I am creating a personnel database and need to show the length of service as years months days from StartDate to EndDate.
Where EndDate contains a null value then the Today () or Now() needs to be used.
There is alot of info on the subject but none that I can find that takes into account a Null Value in EndDate.
Many thanks
Pauline
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 22:29
Joined
Jul 9, 2003
Messages
16,282
IIf (IsNull(EndDate), Today (), EndDate)
 

Pauline123

Registered User.
Local time
Today, 22:29
Joined
Apr 1, 2013
Messages
69
Hi thanks for getting back to me but this does not really address my problem..
I have a StartDate field and a LeavingDate field.
I need to calculate the length of service from the StartDate to the LeavingDate in years, months and days taking into account that the LeavingDate may contain a Null value so therefore you would refer to Now () or Today().
This would display on my form the number of years, months and days employed.:)
 

plog

Banishment Pending
Local time
Today, 16:29
Joined
May 11, 2011
Messages
11,646
Whenever you want to express something in multiple units (ounces/pounds/tons, feet/yards/miles) you determine the amount of the lowest unit and then work your way up. That's assuming your units are evenly divisible. You can't really do that with days/months/years.

Months have between 28-31 days. While years always have 12 months, they can have either 365 or 366 days. So you need to better express what it is you want. The way to do this is with example data. Give me what you expect as results from these examples:

Start, Leave
1/1/2015, 12/30/2015
1/1/2015, 3/1/2015
1/1/2016, 3/1/2016
2/1/2015, 2/28/2015
2/1/2016, 2/29/2016
3/2/2015, 2/29/2016
 

sneuberg

AWF VIP
Local time
Today, 14:29
Joined
Oct 17, 2014
Messages
3,506
I think it does address the null issue which is what I thought you were talking about. For example to calculate the number of years it would be something like

DateDiff("yyyy", [StartDate], IIf(IsNull([LeavingDate]), Now(), [LeavingDate]))
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 22:29
Joined
Jul 9, 2003
Messages
16,282
Hi hoping someone can help. I am creating a personnel database and need to show the length of service as years months days from StartDate to EndDate.
Where EndDate contains a null value then the Today () or Now() needs to be used.
There is alot of info on the subject but none that I can find that takes into account a Null Value in EndDate.
Many thanks
Pauline

The way your question reads is that you have got your solution, however you have a small problem with a null value. To which you received two practically identical answers.
 

Pauline123

Registered User.
Local time
Today, 22:29
Joined
Apr 1, 2013
Messages
69
Hi Plog - it would be #StartDate# less #LeavingDate# or #Date() to give years, months, days employed by company et 3 years, 4 months 2 days
 

plog

Banishment Pending
Local time
Today, 16:29
Joined
May 11, 2011
Messages
11,646
It?

I didn't give you a singular example. I provided multiple fringe examples to demonstrate its not as easy as you think. Further, in none of my examples were the differences between Start and End greater than 2 years, so I don't see that your answer is specific to any of them.
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Tomorrow, 05:29
Joined
May 7, 2009
Messages
19,245
from: http://www.vbaexpress.com/kb/getarticle.php?kb_id=866
Code:
Option Compare Database
Option Explicit

Function YearsMonthsDays(Date1 As Date, Optional Date2 As Date = 0, Optional ShowAll As _
    Boolean = False, Optional Grammar As Boolean = True)
     
     ' This function returns a string "X years, Y months, Z days" showing the time
     ' between two dates.  This function may be used in any VBA or VB project
     
     ' Date1 and Date2 must either be dates, or strings that can be implicitly
     ' converted to dates.  If these arguments have time portions, the time portions
     ' are ignored. If Date1 > Date2 (after ignoring time portions), the function
     ' returns an empty string
     
     ' ShowAll indicates whether all portions of the string "X years, Y months, Z days"
     ' are included in the output.  If ShowAll = True, all portions of the string are
     ' always included.  If ShowAll = False, then if the year portion is zero the year
     ' part of the string is omitted, and if the year portion and month portion are both
     ' zero, than both year and month portions are omitted.  The day portion is always
     ' included, and if at least one year has passed then the month portion is always
     ' included
     
     ' Grammar indicates whether to test years/months/days for singular or plural
     
     ' By definition, a "full month" means that the day number in Date2 is >= the day
     ' number in Date1, or Date1 and Date2 occur on the last days of their respective
     ' months. A "full year" means that 12 "full months" have passed.
     
     ' In Excel, this function is an alternative to the little-known DATEDIF.  DATEDIF
     ' usually works well, but can create strange results when a date is at month end.
     ' Thus, this formula:
     
     '       =DATEDIF(A1,B1,"y") & " years, " & DATEDIF(A1,B1,"ym") & " months, " &
     '       DATEDIF(A1,B1,"md") & " days"
     
     ' will return "0 years, 1 months, -2 days" for 31-Jan-2006 and 1-Mar-2006.
     ' This function will return "0 years, 1 month, 1 day"
     
     ' Chip Pearson gives a VBA equivalent in his Age() function at
     ' http://www.cpearson.com/excel/datedif.htm
     ' Unfortunately, it gives the same result in the test case above
     
    Dim TestYear As Long, TestMonth As Long, TestDay As Long
    Dim TargetDate As Date, Last1 As Date, Last2 As Date
     
     ' Strip time portions
    
    Date1 = Int(Date1)
    If Date2 = 0 Then Date2 = Date
    Date2 = Int(Date2)
     
     ' Test for invalid dates
    If Date1 > Date2 Then
        YearsMonthsDays = ""
        Exit Function
    End If
     
     ' Test for whether the calendar year is the same
    If Year(Date2) > Year(Date1) Then
         
         ' Different calendar year.
         
         ' Test to see if calendar month is the same.  If it is, we have to look at the
         ' day to see if a full year has passed
        If Month(Date2) = Month(Date1) Then
            If Day(Date2) >= Day(Date1) Then
                TestYear = DateDiff("yyyy", Date1, Date2)
            Else
                TestYear = DateDiff("yyyy", Date1, Date2) - 1
            End If
             
             ' In this case, a full year has definitely passed
        ElseIf Month(Date2) > Month(Date1) Then
            TestYear = DateDiff("yyyy", Date1, Date2)
             
             ' A full year has not passed
        Else
            TestYear = DateDiff("yyyy", Date1, Date2) - 1
        End If
         
         ' Calendar year is the same, so a full year has not passed
    Else
        TestYear = 0
    End If
     
     ' Test to see how many full months have passed, in excess of the number of full
     ' years
    TestMonth = (DateDiff("m", DateSerial(Year(Date1), Month(Date1), 1), _
    DateSerial(Year(Date2), Month(Date2), 1)) + IIf(Day(Date2) >= _
    Day(Date1), 0, -1)) Mod 12
     
     ' See how many days have passed, in excess of the number of full months.  If the day
     ' number for Date2 is >= that for Date1, it's simple
    If Day(Date2) >= Day(Date1) Then
        TestDay = Day(Date2) - Day(Date1)
         
         ' If not, we have to test for end of the month
    Else
        Last1 = DateSerial(Year(Date2), Month(Date2), 0)
        Last2 = DateSerial(Year(Date2), Month(Date2) + 1, 0)
        TargetDate = DateSerial(Year(Date2), Month(Date2) - 1, Day(Date1))
        If Last2 = Date2 Then
            If TestMonth = 11 Then
                TestMonth = 0
                TestYear = TestYear + 1
            Else
                TestMonth = TestMonth + 1
            End If
        Else
            TestDay = DateDiff("d", IIf(TargetDate > Last1, Last1, TargetDate), Date2)
        End If
    End If
     
    If ShowAll Or TestYear >= 1 Then
        YearsMonthsDays = TestYear & IIf(TestYear = 1 And Grammar, " year, ", _
        " years, ") & TestMonth & IIf(TestMonth = 1 And Grammar, " month, ", _
        " months, ") & TestDay & IIf(TestDay = 1 And Grammar, " day", " days")
    Else
        If TestMonth >= 1 Then
            YearsMonthsDays = TestMonth & IIf(TestMonth = 1 And Grammar, " month, ", _
            " months, ") & TestDay & IIf(TestDay = 1 And Grammar, " day", " days")
        Else
            YearsMonthsDays = TestDay & IIf(TestDay = 1 And Grammar, " day", " days")
        End If
    End If
     
End Function

another function:
to call it:
Diff2Dates("dmy",#10/29/1963#,now()), will show difference in years, month and days.
Code:
Option Compare Database
Option Explicit

'***************** Code Start **************
Public Function Diff2Dates(Interval As String, Date1 As Variant, Date2 As Variant, _
Optional ShowZero As Boolean = False) As Variant
'Author:    ? Copyright 2001 Pacific Database Pty Limited
'           Graham R Seach MCP MVP gseach@pacificdb.com.au
'           Phone: +61 2 9872 9594  Fax: +61 2 9872 9593
'           This code is freeware. Enjoy...
'           (*) Amendments suggested by Douglas J. Steele MVP
'
'Description:   This function calculates the number of years,
'               months, days, hours, minutes and seconds between
'               two dates, as elapsed time.
'
'Inputs:    Interval:   Intervals to be displayed (a string)
'           Date1:      The lower date (see below)
'           Date2:      The higher date (see below)
'           ShowZero:   Boolean to select showing zero elements
'
'Outputs:   On error: Null
'           On no error: Variant containing the number of years,
'               months, days, hours, minutes & seconds between
'               the two dates, depending on the display interval
'               selected.
'           If Date1 is greater than Date2, the result will
'               be a negative value.
'           The function compensates for the lack of any intervals
'               not listed. For example, if Interval lists "m", but
'               not "y", the function adds the value of the year
'               component to the month component.
'           If ShowZero is True, and an output element is zero, it
'               is displayed. However, if ShowZero is False or
'               omitted, no zero-value elements are displayed.
'               For example, with ShowZero = False, Interval = "ym",
'               elements = 0 & 1 respectively, the output string
'               will be "1 month" - not "0 years 1 month".

On Error GoTo Err_Diff2Dates

   Dim booCalcYears As Boolean
   Dim booCalcMonths As Boolean
   Dim booCalcDays As Boolean
   Dim booCalcHours As Boolean
   Dim booCalcMinutes As Boolean
   Dim booCalcSeconds As Boolean
   Dim booCalcWeeks As Boolean
   Dim booSwapped As Boolean
   Dim dtTemp As Date
   Dim intCounter As Integer
   Dim lngDiffYears As Long
   Dim lngDiffMonths As Long
   Dim lngDiffDays As Long
   Dim lngDiffHours As Long
   Dim lngDiffMinutes As Long
   Dim lngDiffSeconds As Long
   Dim lngDiffWeeks As Long
   Dim varTemp As Variant

   Const INTERVALS As String = "dmyhnsw"

'Check that Interval contains only valid characters
   Interval = LCase$(Interval)
   For intCounter = 1 To Len(Interval)
      If InStr(1, INTERVALS, Mid$(Interval, intCounter, 1)) = 0 Then
         Exit Function
      End If
   Next intCounter

'Check that valid dates have been entered
   If IsNull(Date1) Then Exit Function
   If IsNull(Date2) Then Exit Function
   If Not (IsDate(Date1)) Then Exit Function
   If Not (IsDate(Date2)) Then Exit Function

'If necessary, swap the dates, to ensure that
'Date1 is lower than Date2
   If Date1 > Date2 Then
      dtTemp = Date1
      Date1 = Date2
      Date2 = dtTemp
      booSwapped = True
   End If

   Diff2Dates = Null
   varTemp = Null

'What intervals are supplied
   booCalcYears = (InStr(1, Interval, "y") > 0)
   booCalcMonths = (InStr(1, Interval, "m") > 0)
   booCalcDays = (InStr(1, Interval, "d") > 0)
   booCalcHours = (InStr(1, Interval, "h") > 0)
   booCalcMinutes = (InStr(1, Interval, "n") > 0)
   booCalcSeconds = (InStr(1, Interval, "s") > 0)
   booCalcWeeks = (InStr(1, Interval, "w") > 0)

'Get the cumulative differences
   If booCalcYears Then
      lngDiffYears = Abs(DateDiff("yyyy", Date1, Date2)) - _
              IIf(Format$(Date1, "mmddhhnnss") <= Format$(Date2, "mmddhhnnss"), 0, 1)
      Date1 = DateAdd("yyyy", lngDiffYears, Date1)
   End If

   If booCalcMonths Then
      lngDiffMonths = Abs(DateDiff("m", Date1, Date2)) - _
              IIf(Format$(Date1, "ddhhnnss") <= Format$(Date2, "ddhhnnss"), 0, 1)
      Date1 = DateAdd("m", lngDiffMonths, Date1)
   End If

   If booCalcWeeks Then
      lngDiffWeeks = Abs(DateDiff("w", Date1, Date2)) - _
              IIf(Format$(Date1, "hhnnss") <= Format$(Date2, "hhnnss"), 0, 1)
      Date1 = DateAdd("ww", lngDiffWeeks, Date1)
   End If

   If booCalcDays Then
      lngDiffDays = Abs(DateDiff("d", Date1, Date2)) - _
              IIf(Format$(Date1, "hhnnss") <= Format$(Date2, "hhnnss"), 0, 1)
      Date1 = DateAdd("d", lngDiffDays, Date1)
   End If

   If booCalcHours Then
      lngDiffHours = Abs(DateDiff("h", Date1, Date2)) - _
              IIf(Format$(Date1, "nnss") <= Format$(Date2, "nnss"), 0, 1)
      Date1 = DateAdd("h", lngDiffHours, Date1)
   End If

   If booCalcMinutes Then
      lngDiffMinutes = Abs(DateDiff("n", Date1, Date2)) - _
              IIf(Format$(Date1, "ss") <= Format$(Date2, "ss"), 0, 1)
      Date1 = DateAdd("n", lngDiffMinutes, Date1)
   End If

   If booCalcSeconds Then
      lngDiffSeconds = Abs(DateDiff("s", Date1, Date2))
      Date1 = DateAdd("s", lngDiffSeconds, Date1)
   End If

   If booCalcYears And (lngDiffYears > 0 Or ShowZero) Then
      varTemp = lngDiffYears & IIf(lngDiffYears <> 1, " years", " year")
   End If

   If booCalcMonths And (lngDiffMonths > 0 Or ShowZero) Then
      If booCalcMonths Then
         varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
                   lngDiffMonths & IIf(lngDiffMonths <> 1, " months", " month")
      End If
   End If

   If booCalcWeeks And (lngDiffWeeks > 0 Or ShowZero) Then
      If booCalcWeeks Then
         varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
                   lngDiffWeeks & IIf(lngDiffWeeks <> 1, " weeks", " week")
      End If
   End If

   If booCalcDays And (lngDiffDays > 0 Or ShowZero) Then
      If booCalcDays Then
         varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
                   lngDiffDays & IIf(lngDiffDays <> 1, " days", " day")
      End If
   End If

   If booCalcHours And (lngDiffHours > 0 Or ShowZero) Then
      If booCalcHours Then
         varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
                   lngDiffHours & IIf(lngDiffHours <> 1, " hours", " hour")
      End If
   End If

   If booCalcMinutes And (lngDiffMinutes > 0 Or ShowZero) Then
      If booCalcMinutes Then
         varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
                   lngDiffMinutes & IIf(lngDiffMinutes <> 1, " minutes", " minute")
      End If
   End If

   If booCalcSeconds And (lngDiffSeconds > 0 Or ShowZero) Then
      If booCalcSeconds Then
         varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
                   lngDiffSeconds & IIf(lngDiffSeconds <> 1, " seconds", " second")
      End If
   End If

   If booSwapped Then
      varTemp = "-" & varTemp
   End If

   Diff2Dates = Trim$(varTemp)

End_Diff2Dates:
   Exit Function

Err_Diff2Dates:
   Resume End_Diff2Dates

End Function
'************** Code End *****************
 
Last edited:

Pauline123

Registered User.
Local time
Today, 22:29
Joined
Apr 1, 2013
Messages
69
Hi Arnelgp this looks great but how do I use it - I currently have a text box I wish to use on a form and thought I could use the control source but I am having no luck :-(
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Tomorrow, 05:29
Joined
May 7, 2009
Messages
19,245
put the code in a Module and change this portions:
Code:
Function YearsMonthsDays(Date1 As Date, Optional Date2 As Date = 0, Optional ShowAll As _
    Boolean = False, Optional Grammar As Boolean = True)
with:
Code:
Function YearsMonthsDays(Date1 As Date, Optional Date2 As Variant = Null, Optional ShowAll As _
    Boolean = False, Optional Grammar As Boolean = True)
also this:
Code:
    Date1 = Int(Date1)
    If Date2 = 0 Then Date2 = Date
    Date2 = Int(Date2)
with:
Code:
    Date1 = Int(Date1)
    If IsNull(Date2) Then Date2 = Date
    Date2 = Int(Date2)
now on your query, use expression Length Of Service: YearsMonthsDays([StartDate], [LeavingDate])

or in a textbox control as its control source:
=YearsMonthsDays([StartDate], [LeavingDate])
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Tomorrow, 05:29
Joined
May 7, 2009
Messages
19,245
you're welcome maam!
 

Users who are viewing this thread

Top Bottom