Calculate Working Days Minus Holidays in VBA


June 17, 2008 – 9:50 am by JP

I was looking for a function that calculates working days, minus holidays, for a small project I've been working on. I decided to write one myself, but below I've also demonstrated an alternate way that uses the ATP (Analysis ToolPak) functions for VBA.
 

VBA:
  1. Function WorkDays(StartDate As Variant, EndDate As Variant) As Long
  2. ' adapted from:
  3. ' http://www.exceltip.com/st/Calculate_the_count_of_workdays_between_two_dates_using_VBA_in_Microsoft_Excel/523.html
  4. ' and http://support.microsoft.com/kb/97757
  5. '
  6. ' returns the count of days between StartDate - EndDate minus Saturdays and Sundays
  7. ' also checks for holidays (added by Jimmy Pena 6/17/2008)
  8.  
  9. Dim lCounter As Long
  10. Dim DaysCount As Long
  11. Dim HolidaysList()
  12. Dim ArrMember
  13. Dim bWasFound As Boolean
  14.  
  15. bWasFound = False
  16.  
  17. StartDate = DateValue(StartDate)
  18. EndDate = DateValue(EndDate)
  19.  
  20. ' define holiday list as an array which we will check against
  21. ' each day; if match is found, do not increase workday count
  22. '
  23. ' edit/add/delete as needed
  24. ' these are US Federal Holidays
  25. HolidaysList = Array("1/1/2007", "1/15/2007", "2/19/2007", "5/28/2007", "7/4/2007", "9/3/2007", "10/8/2007", "11/12/2007", _
  26. "11/22/2007", "12/25/2007", "1/1/2008", "1/21/2008", "2/18/2008", "5/26/2008", "7/4/2008", "9/1/2008", "10/13/2008", _
  27. "11/11/2008", "11/27/2008", "12/25/2008")
  28.  
  29. For lCounter = StartDate To EndDate
  30.     If Weekday(lCounter, vbMonday) <6 Then
  31.         For Each ArrMember In HolidaysList
  32.             If Format(ArrMember, "mm/dd/yyyy") = Format(lCounter, "mm/dd/yyyy") Then
  33.                 bWasFound = True
  34.                 Exit For
  35.             Else
  36.                 bWasFound = False
  37.             End If
  38.         Next ArrMember
  39.        
  40.         If bWasFound = False Then
  41.             DaysCount = DaysCount + 1
  42.         End If
  43.     End If
  44. Next lCounter
  45. WorkDays = DaysCount
  46. End Function

Here we create an array of holidays, then loop through the dates passed as arguments to the function to see if they are not weekend days. The inner loop checks to see if the date matches one of the holidays in the array variable. If both conditions are met (i.e. a weekday and not a holiday) we add to the count (DaysCount variable).

The Boolean variable is used as a flag inside the loop -- if the date matches a holiday date, the flag is raised and the loop immediately exits. We check the flag after the loop is complete and add to the count if it was left False.

To use:

VBA:
  1. MsgBox WorkDays("1/1/2008", "1/31/2008")

Or since the function returns a Long value, assign the result to a variable

VBA:
  1. Dim lCountOfDays As Long
  2. lCountOfDays = WorkDays("1/1/2008", "1/31/2008")

Here's another way, using the ATP library for VBA. To set a reference, open the VBE and go to Tools > References and set a reference to "atpvbaen.xls".

ATP VBA Functions Library

You may also need to go back to Excel and go to Tools > Add-Ins and select "Analysis ToolPak - VBA".

ATP VBA In Excel

Now you can use the NETWORKDAYS function directly in VBA like this:

VBA:
  1. Dim HolidaysList()
  2.  
  3. HolidaysList = Array("1/1/2007", "1/15/2007", "2/19/2007", "5/28/2007", "7/4/2007", "9/3/2007", "10/8/2007", "11/12/2007", _
  4. "11/22/2007", "12/25/2007", "1/1/2008", "1/21/2008", "2/18/2008", "5/26/2008", "7/4/2008", "9/1/2008", "10/13/2008", _
  5. "11/11/2008", "11/27/2008", "12/25/2008")
  6.  
  7. MsgBox networkdays("1/1/2008", "1/31/2008", HolidaysList)

Which should give you the same answer, and in my tests, at approximately the same speed.

Personally I like my way better, but that's only because I worked on it and I hate throwing away old code. Plus it uses built-in functions in case you don't want to add additional object libraries to your VBE. As you can see above, I already have a lot, so anything already built-in to VBA I can use is something I will prefer.

Enjoy,
JP


If you enjoyed this page:
  • StumbleUpon
  • Technorati
  • Digg
  • Google
  • del.icio.us
  • MisterWong

Print This Post Print This Post  |  Email This Post Email This Post  |  Permalink  |  Subscribe to this feed Subscribe now!

Filed Under: Excel, UDF, VBA
Tags: , , , ,

This post has 2,300 views since June 17, 2008 – 9:50 am.
  1. 3 Responses to “Calculate Working Days Minus Holidays in VBA”

  2. Hi - down here in the southern hemisphere we run with different date formats ie day/month/year and I can not get this macro to calculate correctly.
    I am trying to calculate the number of hours between when a quote was requested and when it was submitted - using 24 hours per day x total days - weekends - holidays.

    I have been playing with both Workdays function and TimeDiff function VBA code but to no avail as yet. I have tried holiday dates in different formats in Sub.

    eg Input data:
    Date/time quote requested 5/02/2008 8:00 (i.e. in one field with format d/mm/yyyy h:mm)
    Date/Time quote submitted 30/04/2008 17:00

    NZ HolidaysList = Array("1/01/2007", "6/02/2007", "6/04/2007", "9/04/2007", "25/04/2007", "4/06/2007", "22/10/2007", "25/12/2007", "26/12/2007")

    = 85.38 days - 24 days weekends - 4days holidays = 57.38 days, x24 = 1377 hours

    Networkdays = 58 days, x 24 = 1392hours

    With
    Const ComeIn As Date = "0:00"
    Const Leave As Date = "23:59"
    TimeDiff = 1448 hours which has added more hours not subtracted for holidays or failed to find any holidays (which is what I thought it would do if could not match holidays with dates)?

    I have also played with modified code from "Visual Basic Language Developer's Handbook" by Ken Getz and Mike Gilbert and once again can not get calculating correctly. I do not want to use american date formats for my quote data as it has NZ users.
    Please can you help.

    By M White on Jul 26, 2008

  3. I'll check it out and let you know. It would probably help if you send me the full code you are using. Just use the contact form and paste in the code:

    http://www.codeforexcelandoutlook.com/Contact.html

    --JP

    By JP on Jul 27, 2008

  4. I just noticed that your work date range is in 2008, but the holidays list is in 2007. If that is the case, the NETWORKDAYS function won't subtract the holidays from the total workdays.

    If you can fix that, it should work. Let me know!

    --JP

    By JP on Jul 28, 2008

Post a Comment

To post VBA code in your comment, use [VBA] tags, like this: [VBA]Code goes here[/VBA].





Subscribe without commenting

Keep Reading:

Browse Posts:


« Wordpress move almost complete! || Calculate Working Hours in VBA »