Visual Basic: Calculating days until birthday from today - vba

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.

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)

If using DateDiff function, using the interval "yyyy", is the function simply subtracting the difference between the year value of date1 and date2?

Macro does not appear to be taking days into account when calculating a person's age.
Sub alcohol_test()
Dim strBirthday As Date
strBirthday = CDate(InputBox("Input date of birth to be verified: ", "Date of Birth"))
If DateDiff("yyyy", strBirthday, Date) < 21 Then MsgBox ("Customer underage, sale of alcohol illegal.") _
Else MsgBox ("Age Confirmed: Alcohol may be sold")
End Sub
It is even worse:
When comparing December 31th to January 1st of the immediately succeeding year,
DateDiff for Year ("yyyy") returns 1, even though only a single day has elapsed, says Microsoft.
So you better compare two dates, e. g. if the birthday was before the day 21 years ago.
Dim datBirthday as Date
datBirthday = CDate(InputBox("Input date of birth to be verified: ", "Date of Birth"))
If datBirthday < DateSerial(Year(Date) - 21, Month(Date), Day(Date)) Then
I changed the variable name, as a beginning with "str" is a little misleading when you use date values.

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.

Day360 in vb.net

I want to use the Days360 function in VB.Net. I need to know the difference in days between two dates assuming 360 days in a year (not 365 days the DateDiff function uses).
For example DateDiff(DateInterval.Day,"16/10/2015", "04/02/2016") = 111 days, but Days360 should return 109 days.
Days360 function in Excel calculates the days between two dates using a fictional calendar that has 30 days in each month. This method is used for some financial purposes.
You can write a function to do the same calculation.
[Edit]
Excel supports two versions of the calculation: one common in the US (this is the default) and the other common in Europe (see the documentation of the DAYS360 function for details).
The code I originally posted implemented the European version. I have updated it to support both versions. Thanks to Nikhil Vartak for pointing this out.
Function Days360(startDate As DateTime, endDate As DateTime, euMethod As Boolean) As Integer
Dim months As Integer = (endDate.Year - startDate.Year) * 12 + endDate.Month - startDate.Month
If euMethod Then
'Use European method (start or end dates after the 30th of the month are changed to 30th)
Return months * 30 + Math.Min(30, endDate.Day) - Math.Min(30, startDate.Day)
Else 'Use US method
'If the start date is the last day of the month, change it to the 30th
Dim startDay As Integer = startDate.Day
startDay = If(startDate.Day >= DateTime.DaysInMonth(startDate.Year, startDate.Month), 30, startDate.Day)
'If end date is last of the month, change it to the 30th
Dim endDay As Integer = endDate.Day
endDay = If(endDate.Day >= DateTime.DaysInMonth(endDate.Year, endDate.Month), 30, endDate.Day)
'If end date is last of the month and start date is before 30th, change end date to 1st of the next month
If endDate.Day >= DateTime.DaysInMonth(endDate.Year, endDate.Month) And startDay < 30 Then
endDay = 1
months += 1
End If
Return months * 30 + endDay - startday
End If
End Function

In VB, calculating the 5th working day of every month

In VB, what coding could I use to calculate the 5th working day of every month? And if the 5th day is a holiday to go up one day.
You would need a list of holiday dates with which to compare. You would need to build and store that list separately. You did not say what variant of VB (VBA? VB.NET?) but in VB.NET you could do:
Dim datevalue As DateTime = New DateTime(DateTime.Year, DateTime.Month, 1)
Dim dayIsFound As Boolean = False
Dim workDays As Integer
workDays = 1
While Not dayIsFound
If ( dateValue.DayOfWeek <> DayOfWeek.Saturday _
And dateValue.DayOfWeek <> DayOfWeek.Sunday _
And Not HolidayList.Contains( dateValue ) _
workDays = workDays + 1
End If
If index >= 5 Then
dayIsFound = True
Else
dateValue = dateValue.AddDays(1)
End If
End While
Technically, it is possible to build an algorithm that determines the major holidays based on Federal guidelines (in the US) but it is complicated and may not conform to the holidays of the company to whom you are building this component.
The problem has 2 main components - first you need a list of public holidays, and second you need to count days of the week which are working days in your locale.
You can hard code your holidays for a quick solution, and if you want this code to keep working without modification you will need to Google for some algorithms / functions to calculate your holidays. Here is a link to some sample calculation functions for holidays, including Easter. http://www.cpearson.com/EXCEL/holidays.htm
Your main function can use the VB functions Weekday and WeekdayName (if needed) in conjunction with your list of public holidays to count all days that fall on a normal working day which isn't in your list of public holidays.
Use Weekday function for Saturday and Sunday. Holidays are dependent on the location and country and you need to implement your own function for that.
You need to count each valid working day until you get to the fifth one. E.g.
index = 0
Do
If dateValue.DayOfWeek <> DayOfWeek.Saturday _
AndAlso dateValue.DayOfWeek <> DayOfWeek.Sunday _
AndAlso Not HolidayList.Contains( dateValue ) Then
index = index + 1
If index >= 5 Then _
Exit Do
End If
dateValue = dateValue.AddDays(1)
Loop