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

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.

Related

How can I find the time number of days between a given date, and the given date's first day of the year in VBA?

For example, the inputted date is 2001/01/21 the output must be 21 because 21 days passed since the inputted date's first day of the year.
Transform the date to a value and do the same for the "new" date? Do the same in Dev.mode newCelldate.Value - yearStartdate.Value?
Copy and paste the following to your VB Editor. Then, run the "TestNumberOfDays" procedure.
Function FirstDayOfTheGivenYear(pDate As Date)
'this will return first day of the given year
FirstDayOfTheGivenYear = 1 * (CDate(pDate) - DatePart("y", CDate(pDate) - 1))
End Function
Function YTDDays(pDate As Date) As Long
'this will find the day differences between two dates
YTDDays = DateDiff("d", FirstDayOfTheGivenYear(pDate), pDate) + 1
End Function
Sub TestNumberOfDays()
'change the date according to your need
MsgBox (YTDDays("2001/01/30"))
End Sub
Like this:
InputDate = #2001/01/21#
OrdinalDay = DatePart("y", InputDate)

VBA get the last day of the month

I am pretty new to VBA. I have a range of dates and I need to write a code that will change the date in the cell to the last day of the month, used in a cell.
For example, if the date in the cell is 28/03/2018 I want it to be replaced by 31/03/2018. Any idea how I can do that?
You can also get the result you need with one line of code thanks to the Eomonth formula:
Range("A1") = Excel.Application.WorksheetFunction.EoMonth(Range("A1").Value2, 0)
You can use a user-defined function GetLastDayOfMonth() and pass the range you are interested in:
Option Explicit
Public Function GetLastDayOfMonth(ByVal myDate As Date) As Date
GetLastDayOfMonth = DateSerial(Year(myDate), Month(myDate) + 1, 0)
End Function
Public Sub TestMe()
Range("A1") = DateSerial(2000, 11, 11)
If Range("A1") = GetLastDayOfMonth(Range("A1")) Then
Debug.Print "LAST DAY!"
End If
Range("A1") = DateSerial(2000, 12, 31)
If Range("A1") = GetLastDayOfMonth(Range("A1")) Then
Debug.Print "LAST DAY! " & Range("A1")
Range("A1") = DateAdd("d", 1, Range("A1"))
End If
End Sub
The function checks the month and the year of the date, which is passed and it returns a new date, which is the last day of the month for this specific month and year.
Then in the TestMe version, you can compare a given date with the last day of the month, generated by the function. If the dates are the same, then this date is the last day of the corresponding month. Using DateAdd() it is possible to get the next day of the lastDay.
In the example above, I have explicitly written Range("A1") 9 times, thus it is probably easier to follow.
To get it really short you can use:
Sub test()
Dim myDate As Date
myDate = #3/28/2018#
Debug.Print DateSerial(Year(myDate), Month(myDate) + 1, 0)
End Sub
First, if you just want the last day of the month in Excel, use the =EOMONTH function, or see this SO post for the vba code:
VBA Run Macro Last Day of the Month
Rolling your own date time code is a bad idea. Don't do it.
This VBA function will calculate the last day of the month:
Public Function LastDay(ByVal d As Date)
Dim returnDate As Date
'First day of current month
returnDate = DateSerial(Year(d), Month(d), 1)
'Forward a month
returnDate = DateAdd("m", 1, returnDate)
'back one day
returnDate = DateAdd("d", -1, returnDate)
LastDay = returnDate
End Function
Works by jumping to the beginning of the month, adding a month then subtracting a day (so 1st Feb->1st Mar->28 Feb)
Like this in VBA:
Sub LastDayOfMonth()
Dim dates As Range, dt As Range
Set dates = Range("A1") //Update as required
For Each dt In dates
dt = Application.WorksheetFunction.EoMonth(dt, 0) //e.g. 01/06/2018 ~~~> 30/06/2018
Next
End Sub
VBA way:
Function LastDayOfMonth(ByVal d As Date)
LastDayOfMonth = DateSerial(Year(d), Month(d), 1)
LastDayOfMonth = DateAdd("m", 1, LastDayOfMonth)
LastDayOfMonth = DateAdd("d", -1, LastDayOfMonth)
End Function
Construct new date:
year: from old date
month: from old date
day: 1
Add 1 month to new date.
Subtract 1 day from new date.
Steps 2 and 3 save you from all complexities of date calculations.
For Excel way, please refer to the other answer.

Calculate the last day of the next month

How to calculate the last day of the next month using vb.net?
try yo use DaysInMonth Function which returns the number of days in the required month.
Example
System.DateTime.DaysInMonth(2016,May)
This will return (31), so you can get the date format in addition to this number to get last day of this month.
An other way is to get the first day of the month after and substract 1 day.
Dim d As DateTime
d = DateTime.Now.AddMonths(2)
d = New DateTime(d.Year, d.Month, 1).AddDays(-1)
If you after the actual date....
You could use DateSerial(Year, Month, 0) this will return the last day of the month prior to the month entered.
Entering DateSerial(2016, 07, 0) will return "30/06/2016"
To get the last day of next month do DateSerial(Now.Year, Now.Month + 2, 0)
This works fine for February and also the year end as well (DateSerial(2016, 3, 0) returns "29/02/2016", DateSerial(2016, 11 + 2, 0) returns "31/12/2016")
Dim N = DateTime.Now.AddMonths(1)
Dim D = New DateTime(N.Year, N.Month, DateTime.DaysInMonth(N.Year, N.Month))
D will have the last day of next month.

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

VB.NET Make a Date out of just Day

My user will typically enter some trip info including a day and month but typically they just enter the day. For example they would enter "TRIP1500/31" where the 31 is implied that its in JULY. The trip date can be at most 7 days in the past or 7 days in the future. So now what Im trying to do is guess what month that day is meant to be. So far I have:
Dim diff As Integer = CInt(tripDay) - Date.Now.Day
Select Case diff
Case 0
'same day so its probably current month
End Select
What I'm having trouble with is the other cases where the current day and the trip day overlap month-to-month. If the current day and trip day are in current month then the most difference they can be is +/-7 days but what about the other cases? Any help appreciated.
Function GetTripDate(day As Integer) As Date
Dim today As Date = Date.Today
For i As Integer = -7 To 7
Dim dt As Date = today.AddDays(i)
If dt.Day = day Then Return dt
Next
Throw New ArgumentOutOfRangeException("Invalid trip day.")
End Function
This gives you the date(incl. month) of the nearest date with the given day:
Dim maxDiffDays = 7
Dim tripDay = 31
Dim today = Date.Today
Dim tripDate = New Date(today.Year, today.Month, tripDay)
Dim tripDates = {tripDate.AddMonths(-1), tripDate, tripDate.AddMonths(1)}
Array.Sort(Of Date)(tripDates, Function(d1, d2) ((today - d1).Duration).CompareTo((today - d2).Duration))
Dim nearestDate = tripDates.First()
If ((today - nearestDate).Days <= maxDiffDays) Then
Console.WriteLine("Nearest month for trip date is: " & nearestDate.Month)
End If
It creates a Date from a given day, then it creates the two surrounding dates one month after and previous this date. This array will be sorted from the positive timespan from today(TimeSpan.Duration). So the firs't date in the array is the nearest date with the correct month.