Create an auxiliary calendar table, which is simply a table of all dates.
There are various ways you can do this:
1. Serially fill down a column in Excel and import it into Access as a table.
2. Call a function which builds the table on the basis of start and end
dates passed into the function as arguments. I'll give an example at the end
of this reply.
You can then LEFT JOIN the calendar table to the sales table e.g. for the 30
days up to and including today:
SELECT calDate, NZ(sales,0)
FROM Calendar LEFT JOIN SalesTable
ON Calendar.calDate = SalesTable.saleDate
WHERE caldate BETWEEN DATE()-29 AND DATE();
BTW don't name a column Date. As you see from the above it’s the name of a
built in function so should be avoided.
Here's the procedure for creating a calendar table:
Public Function MakeCalendar_DAO(strTable As String, _
dtmStart As Date, _
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 lngDayNum As Long
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
Else
Exit Function
End If
End If
On Error GoTo 0
' create new table
strSQL = "CREATE TABLE " & strTable & _
"(calDate DATETIME, " & _
"CONSTRAINT PrimaryKey PRIMARY KEY (calDate))"
dbs.Execute strSQL
' refresh database window
Application.RefreshDatabaseWindow
If varDays(0) = 0 Then
' fill table with all dates
For dtmDate = dtmStart To dtmEnd
lngDayNum = lngDayNum + 1
strSQL = "INSERT INTO " & strTable & "(calDate) " & _
"VALUES(#" & Format(dtmDate, "mm/dd/yyyy") & "#)"
dbs.Execute strSQL
Next dtmDate
Else
' fill table with dates of selected days of week only
For dtmDate = dtmStart To dtmEnd
For Each varDay In varDays()
If Weekday(dtmDate) = varDay Then
lngDayNum = lngDayNum + 1
strSQL = "INSERT INTO " & strTable & "(calDate) " & _
"VALUES(#" & Format(dtmDate, "mm/dd/yyyy") & "#)"
dbs.Execute strSQL
End If
Next varDay
Next dtmDate
End If
End Function
As you see you can restrict it to certain days of the week if you wish, but
to include all days you'd call it like this to create a table covering 2005
to 2015 for instance:
MakeCalendar_DAO "Calendar", "01/01/2005#, #12/31/2015#, 0
Once you have the basic calendar table there are many other uses you can out
it to, e.g. you can add a Boolean (Yes/No) isHoliday column for public
holidays. This enables you to calculate working days between two dates for
instance:
PARAMETERS
[Start date:] DATETIME,
[End date:] DATETIME;
SELECT COUNT(*)
FROM Calendar
WHERE NOT isHoliday
AND WEEKDAY(calDate, 2) < 6
AND caldate BETWEEN
[Start date:] AND [End date:];
Ken Sheridan
Stafford, England