Often it is useful to return the date of a holiday for a given year, perhaps for a schedule application. Neither Excel nor VBA have any built in functions for working with holidays -- you have to create your own. Holidays can be thought of as being either Fixed or Floating. Fixed holidays are those that occur on the same day each year, such as Christmas. Floating holidays are those which occur on different days in different years. For example, Thanksgiving (in the US) occurs on the fourth Thursday of November. Therefore, we need a function that will calculate the fourth Thursday. We'll generalize that function, in both VBA and worksheet function form, to return the Nth day-of-week for any month and year.
Other floating holidays are a bit harder to calculate. For example, in the US, Memorial Day occurs on the last Monday of May. Depending on the year, this may be either the 4th or 5th Monday. So we need a function to calculate the number of Mondays in May. We'll generalize this to compute the number of any day-of-week in any month and year.
Finally, there is Easter, whose actual date is some bizarre result of the phases of the moon. I don't claim credit for the formulas for calculating Easter shown below, nor do I claim to understand why the work, but they do.
For fixed holidays, such as Christmas, this is simple since the date of the holiday
does not change from year to year. For example, use the following to return the date
of Christmas in the current year:
Other holidays, however, are not assigned to a specific date. For example, Thanksgiving Day is defined to be the 4th Thursday of November. Therefore its exact date will change from year to year. For Thanksgiving, we have an explicit VBA function:
Public Function ThanksgivingDate(Yr As Integer) As Date
We can generalize this to holidays that are defined as the Nth Day of some month, such as Martin Luther King's birthday, celebrated on the 3rd Monday of January. The following function will return the Nth DayOfWeek for a given month and year:
Public Function NDow(Y As Integer, M As Integer,
To return the date of the 3rd Monday in January of 1998, use
The NDow function can also be written as a worksheet formula:
Where Yr,Mon, and DoW are cell references or values indicating Year, Month, Nth, and Day-Of-Week.
Public Function DOWsInMonth(Yr As Integer, M As Integer,
where B3 is the year,
C3 is the month, and
D3 is the day
of week (1=Sunday, 2=Monday, ..., 7=Saturday)
Many organizations recognize holiday dates on dates different than those of the actual date. Typically, this is done when the day of week of the holiday falls on a weekend and holidays are observed to make a three-day weekend. The general rule is that if the holiday falls on a Saturday, it is observed on the Friday before the holiday. If the holiday falls on a Sunday, it is observed on the following Monday. The following formula will return a Friday if the holiday falls on a Saturday, a Monday if the holiday falls on a Sunday, or the date itself if it falls on a weekday.=IF(WEEKDAY(A2, 1)=1,A2+1,IF(WEEKDAY(A2,1)=7,A2-1,A2)) where A2 is the date of the holiday. In VBA, you can use the following function:
Function Observed(TheDate As Date) As Date If Weekday(TheDate, vbSunday) = 1 Then Observed = TheDate + 1 ElseIf Weekday(TheDate, vbSunday) = 7 Then Observed = TheDate - 1 Else Observed = TheDate End If End Function
where TheDate is the date if the holiday.
The Easter calculations are now at Easter Calculations.