I want to calculate some schedules on the basis of given dates. Like I have
Start Date
End Date
Weekdays, for example, Monday, Wednesday as a frequency
and I need to calculate
weekly
biweekly
triweekly
monthly
quarterly
dates from the start and end date and also by matching the given weekdays.
For an example
Date start = 05/07/2018
Date End = 15/07/2018
Frequency days = Saturday
and I need weekly Saturday dates and then biweekly Saturday dates until it reaches to the end date.
I have tried DAYOFWEEK in MS ACCESS VBA which is helping a bit but I need to know the complete solution so I can calculate schedules.
Your help is appreciated.
Thanks
The DateAdd Function can do all that.
Air code:
d = StartDate
Do While d <= EndDate
Debug.Print d ' <-- Output date
Select Case Interval
Case "biweekly": d = DateAdd("ww", 2, d)
Case "monthly" : d = DateAdd("m", 1, d)
' etc.
End Select
Loop
For months, you should always add to the original startdate as this could be one of the last days of a month, thus is would offset the dates for months following a month having fewer days. So:
Dim StartDate As Date
Dim EndDate As Date
Dim NextDate As Date
Dim Interval As Long
StartDate = #1/31/2018#
EndDate = #6/30/2018#
Do
NextDate = DateAdd("m", Interval, StartDate)
Interval = Interval + 1
Debug.Print NextDate
Loop Until NextDate >= EndDate
will return:
2018-01-31
2018-02-28
2018-03-31
2018-04-30
2018-05-31
2018-06-30
For starting on a specific weekday, find the first of this, then add intervals as above:
Public Function DateNextWeekday( _
ByVal datDate As Date, _
Optional ByVal bytWeekday As Byte = vbMonday) _
As Date
' Returns the date of the next weekday, as spelled in vbXxxxday, following datDate.
' 2000-09-06. Cactus Data ApS.
' No special error handling.
On Error Resume Next
DateNextWeekday = DateAdd("d", 7 - (Weekday(datDate, bytWeekday) - 1), datDate)
End Function
This should work too - I have included input boxes so you can enter start date, finish date, day of the week and frequency because I don't know how you want that input; also this will store the values in a Table2 Which has a field/column called Dates and then you can retrieve them (I don't know either how do you want to retrieve the dates, if you want to store them etc.)...I hope this helps!:
Sub test()
'clear the table2:
CurrentDb.Execute "DELETE * FROM Table2"
Dim DBTest As String
Dim RSTest As DAO.Recordset
Dim i As Long
Dim selectorInitDate, selectorEndDate, DBDate As Date
'Enter Start Date
selectorInitDate = Format(InputBox("Initial Date"), "mm/dd/yyyy")
'Enter Finish Date
selectorEndDate = Format(InputBox("End Date"), "mm/dd/yyyy")
'Enter Day of the Week (example: Saturday)
selectorWeekDay = InputBox("Week Day")
'Enter Frecuency (example: weekly, biweekly, etc)
selectorFreqDays = InputBox("Frecuency Days")
If selectorWeekDay = "Sunday" Then WeekDaySelected = 1
If selectorWeekDay = "Monday" Then WeekDaySelected = 2
If selectorWeekDay = "Tuesday" Then WeekDaySelected = 3
If selectorWeekDay = "Wednesday" Then WeekDaySelected = 4
If selectorWeekDay = "Thursday" Then WeekDaySelected = 5
If selectorWeekDay = "Friday" Then WeekDaySelected = 6
If selectorWeekDay = "Saturday" Then WeekDaySelected = 7
If selectorFreqDays = "weekly" Then Freq = 7
If selectorFreqDays = "biweekly" Then Freq = 14
If selectorFreqDays = "triweekly" Then Freq = 21
If selectorFreqDays = "monthly" Then Freq = 30
If selectorFreqDays = "quarterly" Then Freq = 90
DBDate = Format(selectorInitDate, "mm/dd/yyyy")
Count = 0
Do While DBDate <= selectorEndDate
If Weekday(DBDate) = WeekDaySelected Then
DBTest = "INSERT INTO Table2 ([Dates]) " & _
" VALUES (" & _
"'" & DBDate & "');"
CurrentDb.Execute DBTest
DBDate = DBDate + Freq - 1
Count = Count + 1
End If
DBDate = DBDate + 1
Loop
'this retrieves in a msgbox the saturdays found between the two dates you specify:
DBTest = "SELECT * FROM Table2"
Set RSTest = CurrentDb.OpenRecordset(DBTest)
If Not RSTest.BOF And Not RSTest.EOF Then
RSTest.MoveFirst
Do While (Not RSTest.EOF)
If Format(RSTest.Fields("Dates").Value, "mm/dd/yyyy") >= selectorInitDate And _
Format(RSTest.Fields("Dates").Value, "mm/dd/yyyy") <= selectorEndDate Then
mthString = mthString & RSTest.Fields("Dates") & ", "
End If
RSTest.MoveNext
Loop
End If
' (remove last comma)
mthString = Left(mthString, Len(mthString) - 2)
MsgBox Count & " " & selectorWeekDay & "(s) Added" & Chr(43) & mthString
'clear the table2:
CurrentDb.Execute "DELETE * FROM Table2"
End Sub
Following your example this should give you how many saturdays you have between two dates in a weekly basis, and which are those dates.
Note: you need to have selected on your reference the "Microsoft DAO 3.6 Object Library"
If you just wanted the bi-weekly dates grouped in 14 day increments beginning with some starting date (first week of the year for example) indate could be the current date or some date you choose or you could just you today().
Function biweeklyDate(indate as date) as Date
biweeklyDate = (DateSerial(2021,1,4)-indate) Mod 14 + inDate
End function
Related
I need help creating an array of dates between 2 dates. I am trying to export holidays from MS Project calendar using the Exceptions object. However, each Calendar.Exception isn't a single date. They can be defined as a range of dates (eg Christmas holidays).
Sub ArrayOfDates()
Dim StartDate As Date, EndDate As Date, aDates() As Date
StartDate = #1/1/2018#
EndDate = #1/31/2018#
'create array of dates inclusive of endpoints
If EndDate > StartDate Then
End If
End Sub
Thanks for all of the suggestions. I went with the approach that eliminated the array:
Sub ExportCalendarHolidays()
Dim calThisPrjCalendar As Calendar, excPeriod As Exception, OutputFileName As String, sOutputLine As String
Dim Period As Date
Set calThisPrjCalendar = ActiveProject.Calendar
OutputFileName = ActiveProject.Path & "\" & "Holidays_" & Format(Now(), "yyyy-mm-dd_hhmmss") & ".csv"
Open OutputFileName For Output As #1
For Each excPeriod In calThisPrjCalendar.Exceptions
For Period = excPeriod.Start To excPeriod.Finish
sOutputLine = Format(Period, "mm/dd/yyyy")
Print #1, sOutputLine
Next Period
Next
'Cleanup
Close #1
End Sub
The code below will create the Array including the start and end date. The lines marked as Debug can be deleted. The loop at the end is just to verify the dates.
Edit: Edited ending loop to look nicer.
Sub ArrayOfDates()
Dim StartDate As Date, EndDate As Date, aDates() As Date
Dim x As Long, y As Long, totalDates As Integer
StartDate = #1/1/2018#
EndDate = #1/31/2018#
DateLoop = StartDate
totalDates = DateDiff("d", StartDate, EndDate)
ReDim aDates(totalDates)
x = 0
Do While DateLoop <= EndDate
aDates(x) = DateLoop
Cells(x + 1, 1).Value = DateLoop ' Debug Line
DateLoop = DateAdd("d", 1, DateLoop)
x = x + 1
Loop
For y = 0 To UBound(aDates)
Cells(y + 1, 3).Value = aDates(y) ' Debug Line
Cells(y + 1, 4).Value = "Array Spot: " & y 'Debug Line
Next y
End Sub
To just get all the dates, you could do something like.
Dim dtDate as Date, dtStartDate as date, dtEndDate as Date
dtStartDate = #1/1/2018#
dtEndDate = #1/31/2018#
For dtDate = dtStartDate To dtEndDate
'code to do each date
Next dtDate
I managed to use the following formula to calculate the net working days between two dates.The problem is i would like to make it possible for the user to enter what days of the week the person works in another cell and automatically update the formula. Just to make it more user friendly, and prevent the user from messing with the formula. Is there anyway to enter the string(12345) in another cell and have the formula update automatically?
Thanks in advance
Option Explicit
'
' This function tells you how many working days are there between 2 given dates.
' You can use this to calculate working days in countries where saturday and sunday are
' not usually holidays.
'
Function NetWorkingDays(sDateRng As Range, eDateRng As Range, workingDays As String, _
Optional HolidayRng As Range) As Long
'
' e.g. use: =NetWorkingDays($A$1,$A$2,"12356")
' will tell you the count of mondays, tuesdays, wednesdays, fridays and saturdays
' between the dates in $A$1 and $A$2
'
' e.g. use: =NetWorkingDays($A$1,$A$2,"12356",$H$2:$H$50)
' will tell you the count of mondays, tuesdays, wednesdays, fridays and saturdays
' between the dates in $A$1 and $A$2, excluding any holidays (listed as dates) in
' the range $H$2:$H$50
'
' You can also count the number of individual days between dates:
' =NetWorkingDays($A$1,$A$2,"2")
' will tell you the number of tuesdays between those two dates
'
Dim sDate As Date, eDate As Date, Holidays() As Variant
Dim nHolidays As Long
Dim totalDays, startDay As Long, endDay As Long
Dim totWeeks As Long, extraDays As Long
Dim curWeekday As Long
Dim i, retVal As Long
'
If (Not IsDate(sDateRng.Value)) Then
sDate = 0#
Else
sDate = sDateRng.Value
End If
'
If (Not IsDate(eDateRng.Value)) Then
eDate = 0#
Else
eDate = eDateRng.Value
End If
'
If (Not HolidayRng Is Nothing) Then
nHolidays = HolidayRng.Cells.Count
ReDim Holidays(0 To nHolidays - 1)
Holidays = HolidayRng.Value2 ' CAREFUL - this automatically assumes dates in the range!
Else
nHolidays = 0
End If
'
totalDays = eDate - sDate + 1
startDay = Weekday(sDate, vbMonday)
endDay = Weekday(eDate, vbMonday)
'
' First calculate the number of whole weeks in the date span.
' Whole weeks are defined as all weeks that start on Monday and
' end on Sunday.
'
If (startDay = 1) Then
If (endDay = 7) Then
extraDays = 0
Else
extraDays = 7 - endDay
End If
Else
If (endDay = 7) Then
extraDays = 7 - startDay + 1
Else
extraDays = 7 - startDay + 1 + endDay
End If
End If
totWeeks = (totalDays - extraDays) / 7
'
' Now determine how many "extra" days are on either side of
' the whole weeks. Include only those "extra" days that are
' a part of the "workingDays" string.
'
extraDays = 0
If (startDay <> 1) Then
For i = startDay To 7
If (InStr(workingDays, CStr(i)) > 0) Then
extraDays = extraDays + 1
End If
Next i
End If
If (endDay <> 7) Then
For i = 1 To endDay
If (InStr(workingDays, CStr(i)) > 0) Then
extraDays = extraDays + 1
End If
Next i
End If
'
retVal = totWeeks * Len(workingDays) + extraDays
'
' Now subtract out the holidays if applicable to the period in question
'
If (nHolidays > 0) Then
For i = LBound(Holidays) To UBound(Holidays)
If (InStr(workingDays, Weekday(Holidays(i, 1), vbMonday)) > 0 And _
Holidays(i, 1) >= sDate And Holidays(i, 1) <= eDate) Then
retVal = retVal - 1
'Debug.Print Format(Holidays(i, 1), "dd mmm, yyyy") & " was removed: it is a " & Format(Holidays(i, 1), "dddd")
Else
'Debug.Print Format(Holidays(i, 1), "dd mmm, yyyy") & " was not removed: it is a " & Format(Holidays(i, 1), "dddd")
End If
Next i
End If
'
NetWorkingDays = retVal
End Function
Hi just a quick question,
I currently have a simple VBA macro set up where it searches from cell B3:B10000 to search for cells with the exact color 49407 and if it does then it will display it in a message box. This part of the program works fine however when i try to add a second loop where it searches from cell D3:D10000 for a date that is 15 days before today's date it does not work and it shows every result in the sheet. i tried using both DateAdd and taking 15 away from the currentDate which i had set to = "Now()".
Basically my question is as follows am i doing this wrong and if so how do i correct it?
Also is it possible to put all messages into one message box instead of multiple boxes popping up one after the other?
The current code i have is as follows:
Sub dateSub()
Dim jobStatus As Boolean
jobStatus = False
Dim currentDate As Date
currentDate = Now()
Dim subDate As Date
subDate = DateAdd("d", -15, currentDate)
Dim jobID As String
Dim dateID As String
For Each ambercell In Range("B3:B10000")
For Each dateCell In Range("D3:D10000")
If ambercell.Cells.EntireRow.Interior.Color = 49407 & dateCell.Value < (currentDate - 15) Then
jobID = ambercell.Text
dateID = dateCell.Text
MsgBox ("List of Job ID's that are still amber & are 15 days Overdue: " & jobID & " on " & dateID)
End If
Next
Next
End Sub
I was going to set up this simple macro and then expand on it in the future to maybe move all Amber cells over into a new sheet or look into more things i could do with VBA macros
Any help with this program will be greatly appreciated.
Thanks,
AlmightyThud
Try this:
Sub dateSub()
Dim jobStatus As Boolean
jobStatus = False
Dim currentDate As Date
currentDate = Now()
Dim subDate As Date
subDate = DateAdd("d", -15, currentDate)
Dim jobID As String
Dim dateID As String
For Each ambercell In Range("B3:B10000")
If ambercell.Cells.EntireRow.Interior.Color = 49407 Then
'For Each dateCell In Range("D3:D10000")
If ambercell.offset( ,2).Value < (currentDate - 15) Then
jobID = ambercell.Value
dateID = ambercell.offset( ,2).Value 'dateCell.offset( ,2).Value
MsgBox ("List of Job ID's that are still amber & are 15 days Overdue: " & jobID & " on " & dateID)
Else
jobID = ambercell.Value
dateID = ambercell.offset( ,2).Value 'dateCell.offset( ,2).Value
MsgBox ("List of Job ID's that are still amber : " & jobID & " on " & dateID)
End If
'Next
End If
Next
End Sub
I'm trying to loop through a column of dates, and any date that is within two other set dates (First Day of Week, Last Day of Week) or (First Day of Month, Last Day of Month).
When I go to assign the date in the column to a variable, I get a type mismatch error.
Sub JobsDue(ByRef DateStart As Date, ByRef DateEnd As Date)
Dim LastRow As Integer
LastRow = Sheet1.Cells(Rows.count, "B").End(xlUp).Row
Dim JobDueDate As String
Dim JobPN As String
For i = 10 To LastRow
JobDueDate = Sheet1.Range("B" & 10, "B" & i).Value (ERROR OCCURS HERE)
JobPN = Sheet1.Range("C" & 10, "C" & i).Value
If (JobDueDate) >= DateStart And (JobDueDate) <= DateEnd Then
lbJobsDue.AddItem (JobPN & "," & CDate(JobDueDate))
End If
Next i
End Sub
Private Sub comboxJobsDue_Change()
If comboxJobsDue.Value = "This Week" Then
StartOfWeek = Date - Weekday(Date) + 2
endofweek = Date - Weekday(Date) + 6
lblJobsDue.Caption = (StartOfWeek) & "-" & (endofweek)
Call JobsDue((StartOfWeek), (endofweek))
ElseIf comboxJobsDue.Value = "Next Week" Then
StartOfWeek = Date - Weekday(Date) + 9
endofweek = Date - Weekday(Date) + 13
lblJobsDue.Caption = (StartOfWeek) & "-" & (endofweek)
ElseIf comboxJobsDue.Value = "This Month" Then
FirstDayInMonth = DateSerial(Year(Date), Month(Date), 1)
LastDayInMonth = DateSerial(Year(Date), Month(Date) + 1, 0)
lblJobsDue.Caption = FirstDayInMonth & "-" & LastDayInMonth
ElseIf comboxJobsDue.Value = "Next Month" Then
FirstDayInMonth = DateSerial(Year(Date), Month(Date) + 1, 1)
LastDayInMonth = DateSerial(Year(Date), Month(Date) + 2, 0)
lblJobsDue.Caption = FirstDayInMonth & "-" & LastDayInMonth
End If
End Sub
The error occurs on Line 7, when I run the program to debug, JobDueDate gets a date but it is in the format of "9/25/2013", the other dates are of the format 8/18/2014 WITHOUT quotation marks. Can anyone explain to me why this error is happening and how I can go about fixing it?
Thanks in advance, Evan
See the line declaration reading "Dim JobDueDate As String" (line 4 I think) You're telling the system you want it as a string... Perhaps you want Dim JobDueDate As Date so you can use date functions on it.
DateStart and End are being passed in as dates so they would error on the code calling this sub if they passed in invalid dates.
Additionally, you appear to be attempting to assign a range of dates to a date field. You either need a collection of dates or an array of dates to handle this.
Ive searched for several hours and since my knowledge of VBA is very limited I'm at a loss. I have an "Inventory Total" for several different items going across the top row (Row B) which is updated by imputing a positive or negative amount on a line below it along with the date of update at the far left (column 1). I have another book that needs to keep track of only the subtractions made to each field by the month.
I already have an (auto_run) macro, so I plan to add this to it. It needs to check today's date and if its the first of the month take the total of all negative numbers (per column) for THAT MONTH ONLY and add it to the top line of the other book.
The part I need to know is how to get the totals per month in VBA.
This is what I'm using to to check today's date:
If Date - Day(Date) + 1 = Date - Day(Date) + 1 And Range("'Monthly Office Inventory'!A2") <> Date - Day(Date) + 1 Then
I'm thinking something like a nested IF check for a value between the first of last month and the end of last month, using the date functions.
Help please?
Sub Datetest()
Dim i As Integer
Dim x As Integer
Dim rng1 As Range
Dim rng2 As Range
Dim crninvbk As Worksheet
Dim mntlisbk As Worksheet
Set crninvbk = Worksheets("Current Office Inventory")
Set mntlisbk = Worksheets("sheet1")
PreviousMonth = DateAdd("m", -1, Date)
Negativemonthly = 0
For x = 2 To 23
For i = 3 To 100
If crninvbk.Cells(i, 1).value >= dhFirstDayInMonth And crninvbk.Cells(i, 1).value <= dhLastDayInMonth Then
If crninvbk.Cells(i, x).value < 0 Then
Negativemonthly = Negativemonthly + crninvbk.Cells(i, x).value
End If
End If
Next i
mntlisbk.Cells(2, x) = Negativemonthly
MsgBox (Negativemonthly)
Negativemonthly = 0
Next x
MsgBox (Negativemonthly)
End Sub
Function dhFirstDayInMonth(Optional dtmDate As Date = 0) As Date
' Return the first day in the specified month.
PreviousMonth = DateAdd("m", -1, Date)
dhFirstDayInMonth = DateSerial(Year(Date), _
Month(PreviousMonth), 1)
End Function
Function dhLastDayInMonth(Optional dtmDate As Date = 0) As Date
' Return the last day in the specified month.
PreviousMonth = DateAdd("m", -1, Date)
dhLastDayInMonth = DateSerial(Year(Date), _
Month(PreviousMonth) + 1, 0)
End Function