Working days between two dates

N

NevilleT

I need to provide two dates and calculate the working dates from the project
calendar. I had a look at the object module and thought the period value
would provide the answer. Unfortunately it does not work. The code I am
using is:

Dim objMSProject As MSProject.Application
Dim objMSProjectDoc As MSProject.Project
Dim objMSProjectCal As Calendar
Dim objMSProjectPeriod As Period
Dim strProjectName As String
Dim intWorkingDays As Integer
Dim dteStart As Date
Dim dteEnd As Date

dteStart = #1/1/2005#
dteEnd = #5/14/2005#

strProjectName = Me.Path ' Am running
this from a form
Set objMSProjectDoc = GetObject(strProjectName)
Set objMSProjectCal = objMSProjectDoc.Calendar
intWorkingDays = 0

For Each objMSProjectPeriod In objMSProjectCal
If IsNumeric(objMSProjectCal.Period(dteStart, dteEnd)) Then
With objMSProjectCal
If .Period(1 / 1 / 2005, 2 / 1 / 2005) Then
If .Period.Working = True Then
intWorkingDays = intWorkingDays + 1
end If
End If
End With
End If
Next
 
J

John

NevilleT said:
I need to provide two dates and calculate the working dates from the project
calendar. I had a look at the object module and thought the period value
would provide the answer. Unfortunately it does not work. The code I am
using is:

Dim objMSProject As MSProject.Application
Dim objMSProjectDoc As MSProject.Project
Dim objMSProjectCal As Calendar
Dim objMSProjectPeriod As Period
Dim strProjectName As String
Dim intWorkingDays As Integer
Dim dteStart As Date
Dim dteEnd As Date

dteStart = #1/1/2005#
dteEnd = #5/14/2005#

strProjectName = Me.Path ' Am running
this from a form
Set objMSProjectDoc = GetObject(strProjectName)
Set objMSProjectCal = objMSProjectDoc.Calendar
intWorkingDays = 0

For Each objMSProjectPeriod In objMSProjectCal
If IsNumeric(objMSProjectCal.Period(dteStart, dteEnd)) Then
With objMSProjectCal
If .Period(1 / 1 / 2005, 2 / 1 / 2005) Then
If .Period.Working = True Then
intWorkingDays = intWorkingDays + 1
end If
End If
End With
End If
Next

Neville,
I think you are making this much more difficult than it needs to be.
There is a method for doing exactly what you want. Go to the VBA help
file and look at the syntax for the DateDifference Method.

Hope this helps.
John
Project MVP
 
N

NevilleT

Thanks John but the issue is to determine from the calendar (in this case the
standard calendar) which days are working days. It is not just a case of the
difference between two dates. I need to check each date to see if it is
classified as a working day.

I am not trying to look at the working hours available as this project does
not have half days or reduced days. Just need to know if work is occuring on
that day. I am a little confused by the database structure as the calendar
data seems to be a mix of recurring work records (Sunday is always a
non-working day is stored in one record) and exceptions (Dec 25 2005 is a
non-working day)
 
R

Rod Gill

I think John's idea works:
Enter the following into Project VBA's immediate window

?Application.datedifference("5/23/2005","5/5/2005
17:00")/60/activeproject.HoursPerDay

It calculates the duration in minutes between two dates and times. Divide by
60 and hours per day and you get the number of working days between two
dates.
Note I've added the finish time of the second date otherwise the default
time of 08:00 is used so the dates wouldn't be inclusive.
 
N

NevilleT

Thanks again Rod but it was a bit more complicated as some days have
different working hours. I eventually got a function to work. It is listed
below. You pass it two dates and it calculates the working days between and
returns the number. So far it is testing without a problem.

'::::::::::::::::::: FUNCTION TO FIND THE NUMBER OF WORKING DAYS BETWEEN TWO
DATES :::::::::::::::::

Function funCalcWorkingDays(StartDate As Date, EndDate As Date)

Dim objMSProject As MSProject.Application '
Application Object
Dim objMSProjectDoc As MSProject.Project ' Project
Object
Dim objMSProjectCal As Calendar ' Calendar
Object
Dim strProjectName As String ' Path to
the project (from the form)
Dim WorkingDays As Integer ' Number of
working days

Dim dteCurrentlyChecking As Date ' The date
currently being checked
Dim intCheckYear As Integer ' The year
currently being checked
Dim intCheckMonth As Integer ' The month
currently being checked
Dim intCheckDay As Integer ' The day
currently being checked

Dim dteStart As Date ' The start
date of the period to check
Dim intStartYear As Integer ' The year
of the start date
Dim intStartMonth As Integer ' The month
of the start date
Dim intStartDay As Integer ' The day of
the start date

Dim dteEnd As Date ' The end
date of the period to check
Dim intEndYear As Integer ' The year
of the end date
Dim intEndMonth As Integer ' The month
of the end date
Dim intEndDay As Integer ' The day of
the end date

Dim intCounter As Integer ' Counter
for the for/next loop

WorkingDays = 0 ' Initialise
the days

dteStart = StartDate ' The start
date parameter passed to the function
dteEnd = EndDate ' The end
date parameter passed to the function

intStartYear = Year(dteStart) ' The year
of the start date
intStartMonth = Month(dteStart) ' The month
of the start date
intStartDay = Day(dteStart) ' The day of
the start date

intEndYear = Year(dteEnd) ' The year
of the end date
intEndMonth = Month(dteEnd) ' The month
of the end date
intEndDay = Day(dteEnd) ' The day of
the end date

' Set up the
criteria to start counting working days
intCheckMonth = intStartMonth ' Start
checking from the start date - month
intCheckYear = intStartYear ' Start
checking from the start date - year
intCheckDay = intStartDay ' Start
checking from the start date - day

strProjectName = Me.Path ' The
location of the project file

Set objMSProjectDoc = GetObject(strProjectName) ' Create the
project object
Set objMSProjectCal = objMSProjectDoc.BaseCalendars(1) ' Create the
base calendar object

' Read each day record and decide if it is a working day. If it is
increment the integer WorkingDays by one.
CalcWorkingDays:
With objMSProjectCal.Years(intCheckYear).Months(intCheckMonth) ' The
year and month to check
For intCounter = intCheckDay To .Days.Count ' Start
at the start day, or if not the first month
' start
at 1
If .Days(intCounter).Working = True Then ' Is a
working day
' Create
the date
dteCurrentlyChecking = DateSerial(intCheckYear,
intCheckMonth, intCounter)

If dteCurrentlyChecking > dteEnd Then ' Check
it is not past the end date
funCalcWorkingDays = WorkingDays ' End
of checking
GoTo funCalcWorkingDays_Exit ' Clean
up before exiting
Else
WorkingDays = WorkingDays + 1 '
Increment the counter by 1
End If

End If
Next intCounter ' Loop back
and read the next record
End With

NextMonth: ' Check if
there is another month to check
intCounter = 0 ' Initialise
the counter
intCheckDay = 1 ' First day of next
month
intCheckMonth = intCheckMonth + 1 ' Increment the
month by one
If intCheckMonth = 13 Then ' Last month checked
was December
intCheckMonth = 1 ' Next month to
check is January
intCheckYear = intCheckYear + 1 ' Increase the year
by one
End If

If intEndYear > intCheckYear Then ' Date range spans
two years
GoTo funCalcWorkingDays_Exit ' Clean up and exit
End If
GoTo CalcWorkingDays ' Check the next month

funCalcWorkingDays_Exit: ' Close Project and
initialize fields
On Error Resume Next
objMSProject.DocClose ' Close the project
file
objMSProject.Quit ' Quit MSP
Exit Function ' End the function

funCalcWorkingDays_Error: ' Error Handling
MsgBox Err.Description
Resume Next

End Function
 
B

Brian K - Project MVP

NevilleT said:
Thanks again Rod but it was a bit more complicated as some days have
different working hours.

But this does not make a difference in what you were asking for. You
asked for the number of days between two dates where work was
occurring. The datedifference function does this if you perform the
other calcs on it's output as Rod described.
 
J

JackD

Actually Brian if you want a COUNT of the days then it does make a
difference. One can imagine a situation where there is only an hour of work
on some days and 8 on others. Now why anyone needs to count those days is
beyond me, but there could be a reason.
 
B

Brian K - Project MVP

JackD said:
Actually Brian if you want a COUNT of the days then it does make a
difference. One can imagine a situation where there is only an hour
of work on some days and 8 on others. Now why anyone needs to count
those days is beyond me, but there could be a reason.

That is the confusing part. Knowing how many days on which some work
can be done does not seem very useful particularly if some of those
days might only have 2 hours of working time. It would seem to me that
the number of hours of working time would be the key.
 
J

JackD

Maybe they need to know how many times the coffee maker is turned on and
off. Seriously, there are some things which might need tracking which are on
a per day and not a per hour basis.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top