Я создал таблицу календаря, чтобы было легче с ней справляться.Я включил код для двух процедур, которые я использовал (CreateTable_calendar и LoadCalendar) ниже.Я добавил поле «рабочий день» в таблицу календаря, если вы хотите ограничить количество дней только рабочими днями вашей организации в каждом месяце.Если это так, вам необходимо соответствующим образом изменить предложение WHERE.А также сбросьте значения рабочего дня для каждой календарной даты, если мой выбор не совпадает с вашим.
В любом случае, я оставлю эти детали для вас, чтобы разобраться.Без корректировки рабочих и нерабочих дней этот запрос возвращает набор результатов, который, я думаю, вам нужен.
TRANSFORM Count(sub.the_date) AS CountOfProjectDays
SELECT sub.Project_name
FROM
(
SELECT
p.Project_name,
MonthName(Month(c.the_date),-1) AS month_name,
c.the_date
FROM Projects AS p, tblCalendar AS c
WHERE
c.the_date >= [p].[start_date]
And c.the_date <= [p].[end_date]
ORDER BY p.Project_name
) AS sub
GROUP BY sub.Project_name
PIVOT sub.month_name
In ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec");
Примечания :
- Я использовал список названий месяцев после PIVOT, чтобы изменить порядок столбцов.Без этого списка столбцы будут представлены в алфавитном порядке по названию месяца.Сократите этот список, если вы не хотите / не нуждаетесь в столбцах для всех 12 месяцев.
- Этот подход должен работать, когда все даты взяты из одного календарного года.Если вы хотите иметь дело с диапазоном дат, который охватывает более одного года ... у вас есть больше работы.: -)
Сделать таблицу календаря:
Public Sub CreateTable_calendar()
Const cstrTable As String = "tblCalendar"
Dim cn As Object
Dim strSql As String
Set cn = CurrentProject.Connection
On Error Resume Next
cn.Execute "DROP TABLE " & cstrTable & ";"
If Err.Number <> 0 Then
Debug.Print Err.Description
End If
On Error GoTo 0
strSql = "CREATE TABLE " & cstrTable & " (" & vbCrLf & _
"the_date DATETIME CONSTRAINT pkey PRIMARY KEY," & vbCrLf & _
"work_day YESNO," & vbCrLf & _
"CONSTRAINT midnite_only CHECK " & _
"(the_date = DateValue(the_date))" & vbCrLf & _
");"
Debug.Print strSql
cn.Execute strSql
Set cn = Nothing
End Sub
Загрузить таблицу календаря.Без указания аргумента для года будут загружены все даты текущего года.В противном случае он загружает даты за год, который вы указали в качестве аргумента.
Public Sub LoadCalendar(Optional ByVal pYear As Integer)
Const cstrTable As String = "tblCalendar"
Dim db As DAO.Database
Dim dte As Date
Dim intYear As Integer
Dim rs As DAO.Recordset
Dim strMsg As String
On Error GoTo ErrorHandler
intYear = IIf(pYear = 0, Year(Date), pYear)
dte = DateSerial(intYear, 1, 1)
Set db = CurrentDb
Set rs = db.OpenRecordset(cstrTable, dbOpenTable, dbAppendOnly)
Do While Year(dte) = intYear
rs.AddNew
rs!the_date = dte
rs!work_day = Not (Weekday(dte) = vbSunday Or _
Weekday(dte) = vbSaturday)
rs.Update
dte = dte + 1
Loop
rs.Close
ExitHere:
On Error GoTo 0
Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
strMsg = "Error " & Err.Number & " (" & Err.Description _
& ") in procedure LoadCalendar"
MsgBox strMsg
GoTo ExitHere
End Sub
Редактировать : Календарь является зарезервированным словом.См. Имена проблем и зарезервированные слова в Access .Я не замечал этого, пока не проверил свою базу данных с помощью утилиты проверки проблем с базой данных мистера Брауна *1027*.Поэтому я изменил название календаря на tblCalendar в этом ответе.И я настоятельно рекомендую эту утилиту.Помимо выявления проблем с зарезервированными словами, он может информировать вас о многих других потенциальных проблемных проблемах.