Find number of weekdays/weekends in a given date range - ms-access

I'm trying to find some VBA code to determine the number of week days and weekend days in a given date range using Access VBA.
For example:
Begin Date - 1/1/2012
End Date - 1/31/2012
Result should be:
Week days - 22
Weekend days - 9
Can anyone help out with this?

These two functions will calculate the number of weekdays and weekend days:
Function NumWeekendDays(dBegin As Date, dEnd As Date) As Long
Dim iPartial As Integer
Dim lBeginDay As Long
Dim lNumWeekendDays As Long
iPartial = DateDiff("d", dBegin, dEnd + 1) Mod 7
lBeginDay = 6 - DatePart("w", dBegin, vbMonday)
lNumWeekendDays = (DateDiff("d", dBegin, dEnd + 1) \ 7) * 2
If iPartial > 0 And lBeginDay - iPartial < 0 Then
If lBeginDay = -1 Then
lNumWeekendDays = lNumWeekendDays + 1
ElseIf iPartial - lBeginDay = 1 Then
lNumWeekendDays = lNumWeekendDays + 1
Else
lNumWeekendDays = lNumWeekendDays + 2
End If
End If
NumWeekendDays = lNumWeekendDays
End Function
Function NumWeekDays(dBegin As Date, dEnd As Date) As Long
NumWeekDays = DateDiff("d", dBegin, dEnd + 1) - NumWeekendDays(dBegin, dEnd)
End Function
Note: I found it simplest to calculate the partial-week weekend days by calculating the lBeginDay variable so that if the start date was Monday, lBeginDay == 5... if the start date was Friday, lBeginDay == 1, etc. Other variations should also work.

Related

VB.NET Do Until Loop to get the Month Name

I want to get the month name from a Do Until......Loop and display in a CheckedListBox.
I have two tables.
1. Month_Count
2. Fees_Ledger
My month name function...
Function mnthName(ByVal mnth As Integer)
Dim name As String = String.Empty
name = MonthName(mnth, False)
Return name
End Function
To get the Month Details
"SELECT FromMonth,ToMonth,MonthCount FROM Month_Count WHERE SemesterNumber='1'"
And to get the Paid Count
"SELECT COUNT(*) AS TotMonthPaidCount FROM Fees_Ledger WHERE SemYear='1' AND FeeId='1'"
So...
' Got the values from queries
FromMonth = 7 '(July)
ToMonth = 6 '(June)
MonthCount = 12 '(Loop will rotate 12 times)
TotMonthPaidCount = 1 '(FeeId 1 paid one time)
'Declaring an integer variable
Dim StartM As Integer = 1
FromMonth = FromMonth + TotMonthPaidCount
' For the first month
CheckedListBoxMonth.Items.Clear()
CheckedListBoxMonth.Items.Add(mnthName(FromMonth))
' Now the loop to achieve the goal
Do Until StartM = (MonthCount - TotMonthPaidCount)
If FromMonth >= 12 Then
FromMonth = 1
CheckedListBoxMonth.Items.Add(mnthName(FromMonth))
Else
FromMonth += 1
CheckedListBoxMonth.Items.Add(mnthName(FromMonth))
End If
StartM += 1
Loop
This Subroutine results exactly what I want.
But the problem occurs when the StartMonth = FromMonth (6) + TotMonthPaidCount (7) value >12. As 13 or 14 or 15 has no Month Name, it is showing error.
Argument 'Month' is not a valid value.
I want it like below.
What should I do ?

Calculate no. of working hours between two given dates(exclude the weekends)

I want to calculate no. of working hours between two given dates(excluding weekends) and it should be within business hours(8:00 AM - 5:00 PM).
I have 3 tables:
table 1 contains open dates and closed dates for different jobs.
table 2 contains the working hours(2 columns start time(8:00 AM) and end time(5:00 PM)).
Table 3 contains date and the day on that date.
For eg.
open date - 2015-10-16 06:00:00 & closed date - 2015-10-19
15:00:00 working_hours_start - 8:00 AM & working_hours_end - 5:00 PM
Answer - 16 hrs
I had this requirement and have written complete function that can calculate while avoiding hours of weekend and holidays for a given country (using a separate table). I have put the whole function and details on my blog (http://mgw.dumatics.com/mysql-function-to-calculate-elapsed-working-time/) along with explanation and flowchart and creation of holiday table etc...
Example of problem resolved:
Let's say an incident was logged on "Friday 10th June 2016 at 12:00" for a site in the "UK" which opens between 09:00 to 16:00. This incident was then closed on "Tuesday 14th June 2016 at 14:00".
For the above incident function should calculate the age as 960 minutes = 16 hours = [4 hours on Friday (12:00 to 16:00) + 7 hours on Monday (09:00 to 16:00) + 5 hours on Tuesday (09:00 to 14:00)]
CREATE FUNCTION WorkTime
(
reported_datetime DATETIME,
closed_datetime DATETIME
)
RETURNS DOUBLE
BEGIN
DECLARE FirstDay, LastDay, CurrentDate, LastDate DATE;
DECLARE StartTime, FinishTime, WorkStart, WorkFinish, DailyWorkTime TIME;
DECLARE Temp DOUBLE;
SET Temp = 0;
SET FirstDay = DATE(reported_datetime);
SET LastDay = DATE(closed_datetime);
SET StartTime = TIME(reported_datetime);
SET FinishTime = TIME(closed_datetime);
SET WorkStart = '08:00:00';
SET WorkFinish = '17:00:00';
SET DailyWorkTime = TIMEDIFF(WorkFinish,WorkStart);
IF (StartTime < WorkStart)
THEN
SET StartTime = WorkStart;
END IF;
IF (FinishTime > WorkFinish)
THEN
SET FinishTime = WorkFinish;
END IF;
SET CurrentDate = FirstDay;
SET LastDate = LastDay;
WHILE(CurrentDate <= LastDate)
DO
IF (DAYOFWEEK(CurrentDate)!=1 AND DAYOFWEEK(CurrentDate)!=7)
THEN
IF (CurrentDate != FirstDay) AND (CurrentDate != LastDay)
THEN
SET Temp = Temp + TIME_TO_SEC(DailyWorkTime)/3600;
ELSEIF (CurrentDate = FirstDay) AND (CurrentDate != LastDay)
THEN
SET Temp = Temp + GREATEST(TIME_TO_SEC(TIMEDIFF(WorkFinish,StartTime)),0)/3600;
ELSEIF (CurrentDate != FirstDay) AND (CurrentDate = LastDay)
THEN
SET Temp = Temp + GREATEST(TIME_TO_SEC(TIMEDIFF(FinishTime,WorkStart)),0)/3600;
ELSEIF (CurrentDate = FirstDay) AND (CurrentDate = LastDay)
THEN
SET Temp = TIME_TO_SEC(TIMEDIFF(FinishTime,StartTime))/3600;
END IF;
END IF;
SET CurrentDate = DATE_ADD(CurrentDate, INTERVAL 1 DAY);
END WHILE;
IF Temp < 0
THEN
SET Temp = 0;
END IF;
RETURN Temp;
END$$;
Try mysql timediff
time_to_sec(timediff('2015-10-16 06:00:00', '2015-10-19 15:00:00 ' )) / 3600
Day not saturday and sunday
where WEEKDAY(date) !=5 and WEEKDAY(date) !=6
and try query like this demo
select *,time_to_sec(timediff(date_note1, date_note2)) / 3600 from (SELECT CASE
WHEN DATE_FORMAT(date,'%H:%i:%s') < '8:00:00' THEN CONCAT(date, ' 8:00:00')
ELSE date
END AS date_note1 ,
CASE
WHEN DATE_FORMAT(date2,'%H:%i:%s') > '17:00:00' THEN CONCAT(date2, ' 17:00:00')
ELSE date2
END AS date_note2
FROM `test` where WEEKDAY(date) !=5 and WEEKDAY(date) !=6) as tbl

capture dates by quarters in access

To make my life much easier working with my data I set 3 columns of same date content. The first displays in the format mm/dd/yyyy, second in the format of yyyy-mm and the third in the format yyyy-q.
I did it purposely due to my reports. Sometimes I need to create monthly, quarterly, yearly etc. Usually I work with a form where I invite the user select start and end date and by a click of a button run a report. This report extracts a query where I specify on the date section to pull all information between start and end date. This time I want to do the same procedure but instead of start and end date - I want the user to select which quarter he wants so that the query will pull all information regarding this quarter. What do I specify in the criteria to archive this?
Filter on
DatePart("q", [YourDateField])
or
Format([YourDateField], "yyyyq")
To obtain the first and last date of a quarter, given the year and the quarter, you can use these expressions:
DateQuarterFirst = DateSerial(Y, 1 + 3 * (Q - 1), 1)
DateQuarterLast = DateSerial(Y, 1 + 3 * Q, 0)
If you have a date of the quarter, you can these functions to obtain the first and last date of the quarter of that date:
Public Function DateThisQuarterFirst( _
Optional ByVal datDateThisQuarter As Date) As Date
Const cintQuarterMonthCount As Integer = 3
Dim intThisMonth As Integer
If datDateThisQuarter = 0 Then
datDateThisQuarter = Date
End If
intThisMonth = (DatePart("q", datDateThisQuarter) - 1) * cintQuarterMonthCount
DateThisQuarterFirst = DateSerial(Year(datDateThisQuarter), intThisMonth + 1, 1)
End Function
Public Function DateThisQuarterLast( _
Optional ByVal datDateThisQuarter As Date) As Date
Const cintQuarterMonthCount As Integer = 3
Dim intThisMonth As Integer
If datDateThisQuarter = 0 Then
datDateThisQuarter = Date
End If
intThisMonth = DatePart("q", datDateThisQuarter) * cintQuarterMonthCount
DateThisQuarterLast = DateSerial(Year(datDateThisQuarter), intThisMonth + 1, 0)
End Function

Vacation Calculation based on Anniversary Date

The rule is after you first year of employment, based on your anniversary date, you get 40 hours. (ex. I was hired on 05/12/2011, I get 40 hours vacation on 05/12/2012.)
Then each subsequent year it rolls to calendar year. So using my above example I need to use my 40 hours between 05/12/2012 and 12/31/2012, because on 01/01/2013 my forty starts over.
At three years (01/01/2014), calendar date, I would get 80 hrs.
At 10 years, calendar date, it goes to 120. The code I am using is below but it doesn't come out right...
Function calcVacEarned(asOfDate As Date, HireDate As Date)
Dim anniversary As Boolean
Dim yos As Integer
anniversary = False
yos = Year(asOfDate) - Year(HireDate)
If Month(HireDate) = Month(asOfDate) And (yos = 1) Then
If Day(HireDate) <= Day(asOfDate) Then
anniversary = True
End If
ElseIf Month(HireDate) < Month(asOfDate) And (yos = 1) Then
anniversary = True
End If
If anniversary Then
calcVacEarned = 40
Else
Select Case yos
Case Is > 10
calcVacEarned = 120
Case Is > 3
calcVacEarned = 80
Case Is > 1
calcVacEarned = 40
Case Else
calcVacEarned = 0
End Select
End If
End Function
My company uses this on a daily basis to calculate hours across the board, could use some help. Thanks in advance!
Assuming you're returning the correct integer for yos :
If anniversary Then
Select Case yos
Case 1
MsgBox "You actually get vacation"
Case 2
MsgBox "OP said nothing regarding 2 years!"
Case 3
MsgBox "You get 80 hours!"
Case 10
MsgBox "You get 120 hours!"
End Select
End If

Calculate Vacation on Anniversary date then Calendar year

I have a form in my Access database that calculated Vacation based on my company policy. The rule is after you first year of employment based on your anniversary date you get 40 hours. (ex. I was hired on 09/06/2012, I get 40 hours vacation on 09/06/2013.)
Then each subsequent year it rolls to calendar year. So using my above example I need to use my 40 hours between 09/06/2013 and 12/31/2013 or I lose them because on January 1, 2014 I recieve 40.
At three years, calendar date, I would get 80 hrs. for on 01/01/2016 I get 80 hours.
At 10 years, calendar date, it goes to 120. The code I have been using which continues to pull from the anniversary date follows:
Function calcVacEarned(asOfDate As Date, HireDate As Date)
Dim yos As Single
Dim curryear As Integer
Dim hireYear As Integer
curryear = Year(asOfDate)
hireYear = Year(HireDate)
yos = (asOfDate - HireDate) / 365.25
If yos >= 1 Then
Select Case yos
Case Is > 10
calcVacEarned = 120
Case Is > 3
calcVacEarned = 80
Case Is > 1
calcVacEarned = 40
Case Else
calcVacEarned = 0
End Select
Else
If hireYear >= curryear Then
calcVacEarned = "0"
Else
If DateSerial(curryear, Month(HireDate), Day(HireDate)) = asOfDate Then
calcVacEarned = "40"
Else
calcVacEarned = "0"
End If
End If
End If
End Function
My company uses this on a daily basis to calculate hours across the board, could use some help. Thanks in advance!
I hope I have understood what you are asking. Here goes :
Function calcVacEarned(asOfDate As Date, HireDate As Date)
Dim anniversary As Boolean
Dim yos as Integer
anniversary = False
yos = Year(asOfDate) - Year(HireDate)
if Month(HireDate) = Month(asOfDate) And (yos = 1) then
if Day(HireDate) <= Day(asOfDate) then
anniversary = True
end if
elseif Month(HireDate) < Month(asOfDate) And (yos = 1) then
anniversary = True
end if
if anniversary then
calcVacEarned = 40
else
Select Case yos
Case Is > 10
calcVacEarned = 120
Case Is > 3
calcVacEarned = 80
Case Is > 1
calcVacEarned = 40
Case Else
calcVacEarned = 0
End Select
end if
End Function