For this sort of thing I would use an auxiliary calendar table, which can be created with the following function:
Code:
Public Function MakeCalendar_DAO(ByVal strTable As String, _
ByVal dtmStart As Date, _
ByVal dtmEnd As Date, _
ParamArray varDays() As Variant)
' Accepts: Name of calendar table to be created: String.
' Start date for calendar: DateTime.
' End date for calendar: DateTime.
' Days of week to be included in calendar
' as value list, e,g 2,3,4,5,6 for Mon-Fri
' (use 0 to include all days of week)
Dim dbs As DAO.Database, tdf As DAO.TableDef
Dim strSQL As String
Dim dtmDate As Date
Dim varDay As Variant
Dim intDayIndex As Integer
Set dbs = CurrentDb
' does table exist? If so get user confirmation to delete it
On Error Resume Next
Set tdf = dbs.TableDefs(strTable)
If Err = 0 Then
If MsgBox("Replace existing table: " & _
strTable & "?", vbYesNo + vbQuestion, _
"Delete Table?") = vbYes Then
strSQL = "DROP TABLE " & strTable
dbs.Execute strSQL, dbFailOnError
ElseIf MsgBox("Append rows to existing table: " & _
strTable & "?", vbYesNo + vbQuestion, _
"Append to Table?") = vbYes Then
GoTo AppendRows
Else
Exit Function
End If
End If
On Error GoTo 0
' create new table
strSQL = "CREATE TABLE " & strTable & _
"(calDate DATETIME, DayIndex SMALLINT, " & _
"CONSTRAINT PrimaryKey PRIMARY KEY (calDate))"
dbs.Execute strSQL, dbFailOnError
' refresh database window
Application.RefreshDatabaseWindow
AppendRows:
If varDays(0) = 0 Then
' fill table with all dates
For dtmDate = dtmStart To dtmEnd
intDayIndex = intDayIndex + 11
strSQL = "INSERT INTO " & strTable & "(calDate,dayIndex) " & _
"VALUES(#" & Format(dtmDate, "mm/dd/yyyy") & "#," & intDayIndex & ")"
dbs.Execute strSQL, dbFailOnError
Next dtmDate
Else
' fill table with dates of selected days of week and non holiday dates only
For dtmDate = dtmStart To dtmEnd
' exclude public or discretionary holidays
If IsNull(DLookup("holDate", "PubHols", "holDate =#" & Format(dtmDate, "yyyy-mm-dd") & "#")) Then
For Each varDay In varDays()
If Not IsNull(varDay) Then
If Weekday(dtmDate) = varDay Then
intDayIndex = intDayIndex + 1
strSQL = "INSERT INTO " & strTable & "(calDate,dayIndex) " & _
"VALUES(#" & Format(dtmDate, "mm/dd/yyyy") & "#," & intDayIndex & ")"
dbs.Execute strSQL
End If
End If
Next varDay
End If
Next dtmDate
End If
End Function
The code references a PubHols table with column holDate to exclude public holidays from the count. As public holidays are added to this table in the future the calendar table can be re-indexed with the following function:
Code:
Public Function ReindexCalendar(strCalendar As String)
Dim rst As DAO.Recordset
Dim strSQL As String
Dim intDayIndex As Integer
strSQL = "SELECT * FROM " & strCalendar & " ORDER By calDate"
Set rst = CurrentDb.OpenRecordset(strSQL)
With rst
.MoveFirst
Do While Not .EOF
intDayIndex = intDayIndex + 1
.Edit
.Fields("dayIndex") = intDayIndex
.Update
.MoveNext
Loop
End With
End Function
To add working days to any date the following function can be called:
Code:
Public Function CalDateAdd(strCalendar As String, AddDays As Integer, Optional DateFrom) As Date
' Accepts: Name of calendar table to be used: String.
' Number of days to add: Integer.
' Date to which days are to be added (Optional). Default = current date.
Dim intDayIndexFrom As Integer
If IsMissing(DateFrom) Then DateFrom = VBA.Date
intDayIndexFrom = DMin("DayIndex", strCalendar, "calDate > #" & Format(DateFrom, "yyyy-mm-dd") & "#") - 1
CalDateAdd = DLookup("CalDate", strCalendar, "dayIndex = " & intDayIndexFrom + AddDays)
End Function