Find date, given WEEKNUM and WEEKDAY - VBA - vba

I'm trying to find a way of finding a date value, given the WEEKNUM and WEEKDAY
For example
WEEKNUM = 9
WEEKDAY = 4 '(Wednesday)
I can use the below function to find the WEEKNUM from the date, but how can I go the other way around?
Function WEEKNUM(D As Date, FW As Integer) As Integer
WEEKNUM = CInt(Format(D, "ww", FW))
End Function

You could use a table on a hidden sheet, and just used Vlookup to find the correct date. EG
DATE WEEKDAY WEEK NO WEEKDAY + WEEK NO
01/03/2016 Tuesday Week 10 Tuesday 10
02/03/2016 Wednesday Week 10 Wednesday 10
In VBA, you could then look up the name of the sheet, which is the weekday, and got the week number from the filename of the workbook, then use vlookup to find the correct date.
weekNum = Mid(ThisWorkbook.Name, 6, 2)
searchStr = ActiveSheet.Name & " " & weekNum & " " & Format(Now(), "YYYY")
rowNo = Application.WorksheetFunction.Match(searchStr, Sheets("WEEKLIST").Range("D:D"), 0)
strSubject = Format(Sheets("WEEKLIST").Range("A" & rowNo).Value, "DD/MM")

Related

VBA to find Second sunday for March every year

I have an if condition in my VBA code to check if it is spring Day light savings day, which is the second Sunday of March. The below code works for all except when 3/1/2015 (for example) is Sunday, then this shows 3rd Sunday. I can add another condition to check if it is Sunday then don't add 7 to the formula, but is there a better way of doing this?
If my_date = (DATEVALUE("3/1/" & this_year) + 7+ CHOOSE(WEEKDAY(DATEVALUE("3/1/" & this_year), 1),7,6,5,4,3,2,1))
This works:
For VBA :
DateSerial(this_year, 3, 1) + 6 - WorksheetFunction.Weekday(DateSerial(this_year, 3, 1), 3) + 7
For Excel:
DateSerial(this_year, 3, 1) + 6 - Weekday(DateSerial(this_year, 3, 1), 3) + 7
Enter the year you want to look at in Cell A1, then select a cell where you want to see the date of the 2nd Sunday in March for the given year and run this code:
Sub test()
Dim i As Integer
Dim dt As Date
Dim y As Integer
i = 0
y = Range("A1").Value
dt = "3/1/" & y
While i < 2
If WeekdayName(Weekday(dt), False, vbUseSystemDayOfWeek) = "Sunday" Then
i = i + 1
If i <> 2 Then
dt = DateAdd("d", 1, dt)
End If
Else
If i <> 2 Then
dt = DateAdd("d", 1, dt)
End If
End If
Wend
ActiveCell.Value = dt
End Sub
I thought I would just add this below code for anyone else who comes across this. I wanted to create a GENERAL purpose block of code that gets any day of week of any month. Ie. if I want the second Sunday or the last Sunday I could retrieve this from one function. Thus I have written the below. You can alter it to how you need it. Ie. Sunday/ Monday or first, second or third etc. This is done by cycling through the days of the month and if the day return which ever day of week you are looking for you save the day in a collection. Once your have cycled through the month you then cycle through the collection to retrieve the necessary date you need!
Function DayOfMonth(theDate As String) As String
'cycle through the given month
'check each day of month and if sunday add day of month to collection
'then cycle through collection for required sunday of month
'daylight savings only happens in march and november
On Error Resume Next
Dim i As Long
Dim testDate As String 'this get passed through function
Dim theYear As Long, theMonth As Long
Dim dayCollection As New Collection
theYear = Year(theDate)
theMonth = Month(theDate)
'build collection of sunday's day of month
For i = 1 To 31
testDate = i & "/" & theMonth & "/" & theYear
If Weekday(testDate, vbSunday) = 1 Then
dayCollection.Add i
End If
Next i
For i = 1 To dayCollection.Count
'2nd sunday
If i = 2 Then
DayOfMonth = dayCollection(i) & "/" & theMonth & "/" & theYear
End If
'last sunday of month
If i = dayCollection.Count Then
DayOfMonth = dayCollection(i) & "/" & theMonth & "/" & theYear
End If
Next i
'clear collection
Set dayCollection = New Collection
End Function
Cheers!
Here's a slight modification to Slubee's answer which I find a little more elegant and easier to follow:
DateSerial(Year, 3, 1) - WorksheetFunction.Weekday(DateSerial(Year, 3, 1), 2) + 14
The 1st term = the date value of March 1st
The 2nd term = a number between 1(Monday) and 7 Sunday)
So (1st term minus 2nd term) gives you the last Sunday in February... and clearly adding 14 will get you the second Sunday of March.
With this structure, the formula can more easily be adapted to similar use cases such as the start/end of daylight saving time in Europe (last Sunday of March/October) or the end of USA DST (first Sunday of November).
If you start from the last day of the previous month, you can correctly calculate the second Sunday of the target month, even if it begins on a Sunday.
The following code sample calculates the start and end date/time of Daylight Saving Time for US areas that observe DST.
If you are developing a function to do this, be sure to test years like 2020 where March begins on a Sunday.
Dim dteLast As Date
Dim dteStart As Date
Dim dteEnd As Date
' DST starts on the second Sunday in March at 2 AM
dteLast = DateSerial(Year(dteDate), 3, 1) - 1
dteStart = dteLast - Weekday(dteLast) + 15 + TimeSerial(2, 0, 0)
' DST ends on the first Sunday in November at 2 AM
dteLast = DateSerial(Year(dteDate), 11, 1) - 1
dteEnd = dteLast - Weekday(dteLast) + 8 + TimeSerial(2, 0, 0)
If my_date = (DateSerial(this_year, 3, 1) + (8 - Weekday(DateSerial(this_year, 3, 1)) Mod 7) + 7) Then

Excel VBA Comparing between a given date and (given date - 2 months)

I am writing a code to ensure that the data date of a system is not later than 2 business month-end date. For instance, if the job run date for the system is 23/12/2015, the valid data date is 30/10/2015 and 30/11/2015. The dates involved are only business days.
I have this code below:
If DateDiff("m", dataDate, jobRunDate) > 2 Then
MsgBox "Error in dataDate"
End If
However, I do not know how to find:
The last day of the month
Compute 2 business month back
Any help will be greatly appreciated. Thanks!
To find the last day of the month, you can find the first day of the next month and subtract a day:
Dim last As Date
Dim current As Date
current = Now
last = DateSerial(Year(current), Month(current), 1) - 1
Debug.Print last
To get the last business day of a month, just subtract days until it falls on a weekday:
Do While Weekday(last, vbMonday) > 5
last = last - 1
Loop
Debug.Print last
Combining the 2 ideas and extracting it as a function gets you this:
Private Sub Example()
Debug.Print LastBizDayOfMonth(Year(Now), Month(Now) - 1)
Debug.Print LastBizDayOfMonth(Year(Now), Month(Now) - 2)
End Sub
Private Function LastBizDayOfMonth(inYear As Integer, inMonth As Integer) As Date
LastBizDayOfMonth = DateSerial(inYear, inMonth + 1, 1) - 1
Do While Weekday(LastBizDayOfMonth, vbMonday) > 5
LastBizDayOfMonth = LastBizDayOfMonth - 1
Loop
End Function
Here is how to get the last day of a month:
Sub LastDayOfMonth()
Dim d As Date
mnth = 12
yr = 2015
d = DateSerial(yr, mnth + 1, 0)
MsgBox d
End Sub
You must then subtract two months from that date. If the result falls on a Saturday or Sunday, you must decide if you want to go forward to the next Monday or backward to the previous Friday.

Determine number of days between dates

How do I get the whole date difference in VBA?
I know that to get the year or the month or the day I do:
DateDiff("yyyy", Me.DateofBirth, Me.Year).
I want the whole difference. Not just the year, and the two columns that I have are Date of Birth and Year.
Dates are stored internally in VBA as doubles, with the integer portion as the number of days since 1/1/1900. To get the difference between two dates, you can just subtract them:
Dim dob As Date
dob = DateSerial(1990, 1, 1)
Dim difference As Date
difference = Now - dob
Debug.Print Year(difference) - 1900 & " years, " & _
Month(difference) & " months, " & _
Day(difference) & " days."
If you want the total number of days, you can just subtract them and use the numeric value of the underlying double:
Dim dob As Date
dob = DateSerial(1990, 1, 1)
Dim days As Long
days = Now - dob
Debug.Print days & " days."

Visual Basic: Calculating days until birthday from today

I need to make a function what calculates days until birthday from todays date.
What I have so far is:
Function synnipaev(sk As Date, tana As Date)
synnipaev = DateDiff("d", sk, tana)
End Function
sk is birthdate in the Excel sheet (formated as 10.10.2001 DD/MM/YYYY)
tana is todays date in the Excel sheet ( =TODAY() DD/MM/YYYY)
It gives me the days but also includes the years.
How to make the function not include years?
DateDiff is simply giving you the total number of days between the two dates. You need to find the difference between the current date and the next birthdate:
Public Function DaysToBirthday(birthday As Date) As Integer
Dim targetYear As Integer
'Has the birthday already passed this year?
If Month(Now) > Month(birthday) Or _
(Month(Now) = Month(birthday) And Day(Now) > Day(birthday)) Then
'Then use next year.
targetYear = Year(Now) + 1
Else
targetYear = Year(Now)
End If
DaysToBirthday = CInt(DateSerial(targetYear, Month(birthday), Day(birthday)) - Now)
End Function
Note: VBA stores Date variables as Doubles, with days to the left of the decimal and time to the right. If all you care about are days, you can save the function call and do a simple subtraction.

How to loop through the weeks in a date range with vba

I have seen how to loop through weeks of a year, w1301,w1302,w1303, I can get the week number if i loop through + on week number but I believe there is a way to directly loop weekly with vba, i hope at least.
DateSerial(Year(Now), Month(Now), Day(Now)) To DateSerial(2013, 3, 1)
StartDate = #1/1/2013#
EndDate = #12/31/2013#
For DateLooper = StartDate To EndDate
I got the function for a week number from date
Public Function IsoWeekNumber(d1 As Date) As Integer
Attributed to Daniel Maher
Dim d2 As Long
d2 = DateSerial(Year(d1 - WeekDay(d1 - 1) + 4), 1, 3)
IsoWeekNumber = Int((d1 - d2 + WeekDay(d2) + 5) / 7)
End Function
You could just use the DateAdd function
For i = 1 To 52
Debug.Print DateAdd("ww", i, Now())
Next i
A day has an integer value of 1, so you could iterate by week like this:
startDate = #1/1/2013#
endDate = #12/31/2013#
For d = startDate To endDate Step 7
'do stuff
Next
The week number can be determined with the DatePart function, e.g.:
WScript.Echo DatePart("ww", Now)
This will work in both vbscript and vba.
I tried this solution and it seems to work, am not 100% sure of how it handles the 28,30,31 days of different months but i trust vba. i know am making a mistake probably :))
currentDate = "2013-01-02" ' coz i wanted to start on a wednesday
for week = 1 to 52
debug.print currentDate
currentDate = DateAdd("ww",1,currentDate)
next week