Getting the first and last dates in a month - vba

I have two comboboxes that lets the user select a date and year. What I want to do is to translate this into my query in access, which requires a [start date] and an [end date] parameter.
I.E. user picks "May" and "2013" in the combo boxes
My query is setup between [start date] and [end date], so I want to translate this month and year selection from the combo boxes into two strings (startdate and enddate, then pass them as command parameters) that contain MM/DD/YYYY, MM/DD/YYYY. What is the best way to take two strings and get the first valid day and last valid day. I have:
FirstDayInMonth = DateSerial( _
Year(Date), Month(Date), 1)
LastDayInMonth = DateSerial( _
Year(dtmDate), Month(dtmDate) + 1, 0)
But I need to make the switch from a string into a date format to get back the first/last day of the selected month, using only the month ("MAY") and year ("2013")? Am I missing something relatively simple?

Make the "Month" combo box have two columns (Column Count property is 2):
1 | Jan
2 | Feb
...
12 | Dec
Set the Bound Column of the combo box to 1 so its .Value is the month number, but display only the month name (hide the number) by setting the width of the first column to zero:
Column Widths: 0";0.75"

So, do you get the month and year (as integer or long, not a date yet) from the comboboxes?
Then try this:
Dim m As Long
Dim y As Long
Dim d_from As Date
Dim d_until As Date
m = CLng("01") ' get these two from your comboboxes
y = CLng("2013")
d_from = DateSerial(y, m, 1)
d_until = DateAdd("m", 1, d_from)
d_until = DateAdd("d", -1, d_until)
When you have the first date, you calculate the second (last day in month) by adding one month, then going one day back.

Related

How to display a month in VBA given conditions

Currently I am trying to display a month given certain conditions in VBA. I have two columns named Quarter and Exact Month in Quarter. Based upon these two conditions, I would like to display a month.
For example, For Quarter 1 Month 1, I would like the new column to display January.
Thank you for your help.
You can just offset each quarter by a value of 3. For instance, Q2 will correspond with 3. When you add your quarter serial #, it will be converted into a calendar serial # (1-12). After that, you just need to set the desired format.
This will just be an excel solution, and if this needs to be in VBA, you can apply similar logic there.
You can do this a few ways. The below image just serves as an example. How to apply this will depend on your data structure. You may need to implement a VLOOKUP as such.
G2 = TEXT(Date(2018, E2 + VLOOKUP(D2,$A$2:$B:$5,2,0),"MMM")
[1] Only one Excel Formula in Column C - doesn't need any helper columns:
This example e.g. for cell C2 as shown in your post converts quarters * 3 months (1 quarter = 3 months) minus 1 plus month in quarter to DATE (argument year can be any year >= 1900) and displays the month's Long form via TEXT argument MMMM; quarter values are extracted from the last string position in column A ( here A2) via RIGHT:
=TEXT(DATE(1900,3*(RIGHT($A2,1)-1)+$B2,1),"MMMM")
[2] Approach via VBA Example Function
Uses the same logic as above:
Sub Test()
MsgBox getMonthInQuarter("Quarter 4", 3)
End Sub
Function getMonthInQuarter(ByVal quarter As Variant, ByVal month As Integer) As String
Const MonthsInQuarter As Integer = 3
Dim q As Integer: q = Val(Right(quarter, 1))
' Return function value
getMonthInQuarter = Format(DateSerial(1900, MonthsInQuarter * (q - 1) + month, 1), "MMMM")
End Function

Create a sql query based on selected month from dropdown combobox in excel userform

I have a userform in excel for attendance reporting. On the form the user chooses the employee they want to review, and then they can check a box that says year to date, or select individual months from a combobox drop down. This is all to query our sql server that has the data on it. Year to date is easy, because I know how to use the variables for current date and first day of the year. What I'm having trouble with is how to convert the user's month selection into a usable query. For example: If the user selects January for the drop down, the query would be
select * from [dbo.mytablename]
where [agent name] = '<value from a textbox that I know how to pass in>'
and [cal date] > '1/1/2018' and [cal date] < '1/31/2018'
Right now my only idea is to have cells on a holding spreadsheet in the workbook that have the first and last day of each month and then use the cell values. But I'd like to avoid that if possible. If you have any ideas that would be great!
First of all
and [cal date] > '1/1/2018' and [cal date] < '1/31/2018'
will select all data from Jan 1 to Jan 30 and not include any data from Jan 31.
Keeping this in mind, the check should be
and [cal date] > '1/1/2018' and [cal date] < '2/1/2018'
So if you do get a month from drop down you can do something like below
select * from [dbo.mytablename] t
join
(values
('Jan', 1),('Feb',2),('Mar', 3),
('Apr', 4),('May',5),('Jun', 6),
('Jul', 7),('Aug',8),('Sep', 9),
('Oct', 10),('Nov',11),('Dec', 12)
)v(mon,num)
on v.mon='<month name received from a text box>'
t.[agent name] = '<value from a textbox that I know how to pass in>'
and t.[cal date] > cast(cast(v.num as varchar)+'/1/2018' as date)
and t.[cal date] < cast(cast((v.num+1)%12 as varchar)+'/1/'+ cast(2018+ (v.num/12) as varchar) as date)
In SQL Server there are numerous techniques for date calculation/converions. If 2012+ you can use EOMonth() or DateFromParts().
I should also add [cal date] < '1/31/2018' should be [cal date] <= '1/31/2018'
Example
Select StrCast1 = try_convert(date,concat('January',' 1, ',2018))
,StrCast2 = EOMonth(try_convert(date,concat('January',' 1, ',2018)))
,FromParts1 = DateFromParts(2018,1,1)
,FromParts2 = EOMonth(DateFromParts(2018,1,1))
Returns
StrCast1 StrCast2 FromParts1 FromParts2
2018-01-01 2018-01-31 2018-01-01 2018-01-31
Assuming your month is a numeric value between 1 and 12, you can use something like
Dim fromDate As Date, toDate As Date
fromDate = DateSerial(2018, month, 1)
toDate = DateSerial(2018, month + 1, 1)
Debug.Print fromDate, toDate
This will work even with December, DateSerial accepts a 13 as month.
Note that you have to ask for < first day of next month to catch data from the last day of the month.
Side note: I assume you use a ADODB.Command to query the database. I would strongly suggest that you use ADODB.parameter to pass the dates (and the agent name) to the database - you don't have to deal with formatting or converting the dates so that the database understand them correctly. See for example https://stackoverflow.com/posts/10353908/edit to get an idea how this works.
Update
I assume you fill your combo box with values from a range and the value is linked to a cell. Use for example the match function to get the month as number (I would never trust that the name of a month is translated correctly by Excel or the database, there are too many things like regional settings that could cause that it breaks).
Assuming:
Range with month names: A1..A12
Linked cell: B1
Put the formula =MATCH(B1,A1:A12) in cell B2. VoilĂ , you have the number of the month.

VBA convert week and day to date

I have a table with week number and day of week.
Example:
J2 = 18
G2 = Monday
How can I convert this to 2018-04-30?
I can find lots of threads for converting the other way around, meaning date to week. But I can't find anything on week + weekday to date.
Anyone know of a method?
The (optional) second argument of the WEEKDAY function determines what the first day of the week is. The two most common choices are:
1: Sunday (1) to Saturday (7)
or
2: Monday (1) to Sunday (7)
But, you can start on Wednesday, Friday, etc if you want. Pick an option now.
So, start with 1st January (of whichever unspecified year you're working with), and subtract the weekday of 1st January, according to whichever start-day you picked. This gives you a baseline for Week 1. To get to the start of Week n, you just need to add 7*(n-1) days.
Finally, you need to add the weekday back on. I'm going to recommend using MATCH on an array. Your array will be your weekdays, in order, surrounded by curly brackets. So, for Sunday-to-Saturday, you would use
MATCH(G2,{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"},0)
to get a number from 1 ("Sunday") to 7 ("Saturday"), or #NA if cell G2 does not contain a day-name.
Stick it all together, and you get something like this:
=DATE(YEAR(NOW()),1,1) - WEEKDAY(DATE(YEAR(NOW()),1,1),1) + 7*(J2-1) + MATCH(G2,{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"},0)
Try this, necessary comments in code:
Option Explicit
Sub GetDate()
Dim year As Date, day As Long
'convert day in G2 to integer
Select Case Range("G2").Value
Case "Monday"
day = 1
Case "Tuesday"
day = 2
'rest of cases
End Select
'declare what year you want
year = "01-01-2018"
'move from first week to the week specified in J2
year = DateAdd("d", (Range("J2").Value - 1) * 7, year)
'move back to first day of the week
Do While DatePart("w", year, vbMonday) <> 1
year = DateAdd("w", -1, year)
Loop
'find date of particular day
Do While DatePart("w", year, vbMonday) <> day
year = DateAdd("w", 1, year)
Loop
End Sub
The determination depends critically on your definition of "week number".
If you are using the ISO-8601 definition, where a Week starts on Monday and week 1 contains the first Thursday of the year, you can use this worksheet formula:
=DATE(YEAR(TODAY()),1,-2)-WEEKDAY(DATE(YEAR(TODAY()),1,7),14)+$J$2*7+MATCH($G$2&"*",{"Monday";"Tuesday";"Wednesday";"Thursday";"Friday";"Saturday";"Sunday"},0)-1
you may need to change the commas to semicolons depending on your regional settings
To explain:
First, find the last Monday of the previous year:
DATE(YEAR(TODAY()),1,-2)-WEEKDAY(DATE(YEAR(TODAY()),1,7),14)
Then add seven(7) times the number of desired weeks:
+$J$2*7
Then add the number of days from Monday to the desired day for that week:
+MATCH($G$2&"*",{"Monday";"Tuesday";"Wednesday";"Thursday";"Friday";"Saturday";"Sunday"},0)-1

VBA Run Macro Last Day of the Month

I want to return the last day in the month. The month is selected from a drop-down combo box. If I select January, this will return "1/31/2017" but I just want it to return 31. What am I missing?
EndDate = WorksheetFunction.EoMonth(ComboBox1.Value & Year(Date), 0)
The function WorksheetFunction.EoMonth returns a Date, while you want a numeric value representing the Day (of the last day of the month).
So you need a Long variable, and you can use the Day function.
EndDate = WorksheetFunction.EoMonth(ComboBox1.Value & Year(Date), 0)
Dim myDay As Long
myDay = Day(EndDate)

VBA Set a specific date to be the first week of the year

I want to set a specific date (October 06 , 2014) to be the 1st Week of the year. So when I use the =weeknum() formulaR1C1 it will return the week number.
I'm currently working on a worksheet that gets updated daily so the week number will be updated every week only. In column ("D") indicates the week number. and column ("B") indicates the daily date.
If i use the =weeknum() formula on it returns the value of 41, but it needs to be week number 1.
How about creating your personalized function?
It just consists of counting how many days there are between the date you insert (myDate) and the date which is considered to be the first day of the year (first_day), dividing this number by 7, taking its integer and adding up 1. It will always give you the right one.
Public Function special_weeknum(ByVal myDate As Date) As Integer
Dim first_day As Date: first_day = #10/6/2014#
Dim myWeek As Integer: myWeek = Int((myDate - first_day) / 7) + 1
special_weeknum = myWeek
End Function
Please note that this approach would allow you also to pass the first day as a user input:
Public Function special_weeknum(ByVal myDate As Date, ByVal first_day As Date)
Dim myWeek As Integer: myWeek = Int((myDate - first_day) / 7) + 1
special_weeknum = myWeek
End Function
so that you will always be able to decide which is the day you must consider as first day of the year.