2
votes

Ive two dropdowns for selecting year and month. In month dropdown there is options JAN,FEB,MAR....DEC and ALL. In Year 2016,2017,2018,2019,2020

I need a function which returns first day of that selection. If 2017 and All selected, it should return 01/01/2017. If its 2017 and JUL, the return value should be 01/07/2017

Also another function just opposite. If user gives 2018 and All, it should return 31/12/2018. if user gives 2018 and FEB, it should return 28/02/2018

So which is the best solution for this case..

What I tried for first day is as follows

Function firstDay(year As String, month As String) As Date
    Dim fd As Date
    If LCase(month) = "all" Then month = "JAN"
    fd = DateValue("01 " & month & Space(1) & year)
    firstDay = fd
End Function

But for last day I didn't get how to do that or the solution I tried was not great. So expecting a better solution in that (Of cource for firstday also if there is better option)

3

3 Answers

2
votes

This should work for all months, regardless how long they are:

Function lastDay(year As String, month As String) As Date
    Dim fd As Date
    If LCase(month) = "all" Then month = "DEC"
    fd = DateValue("01 " & month & Space(1) & year) + 32
    fd = fd - Day(fd)
    lastDay = fd
End Function
1
votes

Im sharing a function I created which serves the purpose. So for those with similar requirement can use

Function lastDay(year As String, month As String) As Date
    Dim ld As Date
    If LCase(month) = "all" Then month = "DEC"
    ld = DateValue("01 " & month & Space(1) & year)
    Dim d As Double
    d = WorksheetFunction.EoMonth(ld, 0)
    ld = CDate(d)
    lastDay = ld
End Function
1
votes

Here's my version of your function.

Function endofdates(yr As Integer, _
                    mth As Integer, _
                    Optional firstday As Boolean = True) As Date
    If firstday Then
        endofdates = DateSerial(yr, mth, 0) + 1
    Else
        endofdates = DateSerial(yr, mth + 1, 0)
    End If
End Function

Edit1: Re-read your question and found out that you cannot use above so I've re-written it to suit your needs.

Function endofdates(yr As Integer, _
                    mth_name As String, _
                    Optional firstday As Boolean = True) As Date
    Dim mth As Integer, idx As Integer
    Const mlist As String = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"
    idx = InStr(1, mlist, mth_name, vbTextCompare)
    mth = Int(idx / 3) + (idx Mod 3)
    If firstday Then
        If mth = 0 Then mth = 1
        endofdates = DateSerial(yr, mth, 0) + 1
    Else
        If mth = 0 Then yr = yr + 1
        endofdates = DateSerial(yr, mth + 1, 0)
    End If
End Function

Edit2: I guess your logic using DateValue is simpler:

Function endofdates(yr As Integer, _
                    mth_name As String, _
                    Optional firstday As Boolean = True) As Date
    Dim dt As Date
    If firstday Then
        If LCase$(mth_name) = "all" Then mth_name = "jan"
        dt = DateValue("1 " & mth_name & " " & yr)
    Else
        If LCase$(mth_name) = "all" Then mth_name = "dec"
        dt = DateValue("1 " & mth_name & " " & yr)
        dt = DateSerial(Year(dt), Month(dt) + 1, 0)
    End If
    endofdates = dt
End Function