I need help writing one line of code in VBA to return the Month-Ending date. The logic for Month-Ending date works like this...
If the last day of the month ends on...
Sunday: Then last day of that month is that previous Saturday. (Yesterday)
Monday: Then last day of that month is that previous Saturday. (2 days ago)
Tuesday: Then last day of that month is that previous Saturday. (3 days ago)
Wednesday:Then last day of that month is the upcoming Saturday (3 days in the future)
Thursday: Then last day of that month is the upcoming Saturday (2 days in future)
Friday: Then last day of that month is the upcoming Saturday (1 day in future)
My current code is below. The formatting of the Month-Ending date is as follows. 2016-07-02
Sub Macro1()
With ActiveWorkbook.Connections("ABC Query").ODBCConnection
.BackgroundQuery = True
.CommandText = Array( _
"exec [dbo].[getBSC_Monthly] #MonthEndDate = **where I need the line of code**")
The Weekday() function will tell you what the current day of the week is (Sun=1, Mon=2, etc.). So, if Weekday() < 4, then you want the date Weekday() days ago. If WeekDay() >= 3, then you want 7 - Weekday() days in the future.
Function MonthEnd(d)
Dim actualmonthend, dow, ans
actualmonthend = DateSerial(Year(d), Month(d) + 1, 1) - 1
dow = Weekday(actualmonthend)
If (dow < 4) Then
ans = actualmonthend - dow
Else
ans = actualmonthend + (7 - dow)
End If
MonthEnd = ans
End Function
if you really just want an expression this would work:
DateSerial(Year(d), Month(d) + 1, 1) - 1 - Weekday(DateSerial(Year(d), Month(d) + 1, 1) - 1) + (7 * Abs(Weekday(DateSerial(Year(d), Month(d) + 1, 1) - 1) >= 4))
Related
What I want to do is to get the data of each "administrative" week (Monday to Sunday), that is if a month starts a Wednesday,the next week when I would launch the query, I would want the data from Wednesday, Thursday, Friday, Saturday, Sunday of the past week. This would get me data of week 1, and so forth for each week of the current month.
I made the following query:
with connection.cursor() as cursor:
sql = 'SELECT COUNT(*) ' \
'FROM panneau ' \
'WHERE year(datecreation) = year(now()) ' \
'AND month(datecreation) = month(now()) ' \
'AND datecreation [I don't know what to put here] '
cursor.execute(sql)
test = cursor.fetchall()
print(test)
But I don't know what to put in the last line.
In the end I should have 4 to 5 variables with the data of each "administrative week", which would take into account when the first week of the month starts and when the last week of the month ends.
Edit : for example with the month on July 2022
Week 1 = Friday 1st to Sunday 3rd.
Week 2 = the 4th to 10th.
Week 3 = 11th to 17th
Week 4 = 18th 24th
Week 5 = 25th to 31st
Some help would be helpful please, thank you.
To get the previous administrative week, you can check if a potential date exists in a range of prior week dates, offset by the current datetime's dow, generated by generate_series:
select p.datecreation from panneau p
where date(p.datecreation) in
(select date(p1.dt) from
(select now() - (extract(dow from now())::text || ' days')::interval - ((7-v)::text|| ' days')::interval dt
from generate_series(1,7) v) p1
where extract(month from p1.dt) = extract(month from now() - (extract(dow from now())::text || ' days')::interval))
See fiddle.
Currently I have this:
Now() - Weekday(Now(), vbMonday) + 1
The problem is, if I use a different week, the same date still shows.
I have a dropdownlist that shows me the days from the week I select. Now it selects it from this week, so also in week 1 the date of monday is already the 9th.
How it should be:
I select a weeknumber and the dates that correspondent with that weeknumber need to be shown in the dropdownlist.
Can somebody please help me? I really don't know what to do..
You could use something like this, if I've got you.
Function FirstMondayInWeek(intWeekNum As Integer) As Date
Dim d As Date
d = DateSerial(Year(Now) - 1, 12, 31)
Do Until Weekday(d, vbMonday) = 1
d = d + 1
Loop
FirstMondayInWeek = DateAdd("WW", intWeekNum - 1, d)
End Function
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
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.
DateAdd("m", -(Month(Date) - 1) Mod 3 - 1, Date)
This gives me 6/28/2015 while I need 20150630 . I can work on the format part but don't know how to get the last day of previous quarter instead of today's date of last quarter.
This should work for VBA. It just determines the first day of the current quarter and then subtracts one day.
Debug.Print DateAdd("q", DatePart("q", Date) - 1, "1/1/" & Year(Date)) - 1