Compare date times chosen with date and time picker in Excel VBA - excel

So i have a multi-page form that uses two "Date and time Picker" controls named StartDate and EndDate. I want to ensure that the user does not enter the StartDate later than the EndDate. I have the following questions. Is the StartDate.value initially "" or is it null? Is what's returned by StartDate a string or a date? Here is what I have so far.
As a side remark I am also somewhat confused by this line of code even after reading the documentation.
emptyRow = Application.WorksheetFunction.CountA(Range("A:A")) + 1
Private Sub StartDate_Change()
Dim emptyRow As Long
'Submits the date in the first empty row immediately since the form does not retain datepicker data after the page changes.
If (EndDate.Value) <> "" And CDate(StartDate.Value) >= CDate(EndDate.Value) Then
MsgBox ("Please enter a valid date")
MultiPage1.Value = 4
Else
Sheet1.Activate
emptyRow = Application.WorksheetFunction.CountA(Range("A:A")) + 1
Cells(emptyRow, 18).Value = StartDate.Value
End If
End Sub

DateTimePickers return Dates.
If you want to test that the EndDate is greater than StartDate, then code such as the following should do the trick:
(StartDate.Value < EndDate.Value)

Related

InputBox data validation and end loop

I have some code to enter dates via InputBox (see below). The problem is that the Else doesn't work (ie. if the user enters something other than the format mm/dd/yy it doesn't stop). How do I make it so that the user has to enter it in the format presented?
Also, I want to end the loop with the endDate. Right now, if you enter 01/10/20 as the start date and 12/31/20 as the end date, it will stop at January 1, 2021. How do I make it stop at December 31, 2020?
Dim startDate As Date
Dim endDate As Date
startDate = InputBox("Enter project start date in format mm/dd/yy", "User date", Format(Now(), "dd/mm/yy"))
endDate = InputBox("Enter project end date in format mm/dd/yy", "User date", Format(Now(), "dd/mm/yy"))
If IsDate(startDate) Then
startDate = Format(CDate(startDate), "mmm d, yyyy")
Else
MsgBox "Wrong date format"
End If
If IsDate(endDate) Then
endDate = Format(CDate(endDate), "mmm d, yyyy")
Else
MsgBox "Wrong date format"
End If
Range("A2").Value = startDate
Dim i As Long
Dim j As Long
Dim x As Integer
i = startDate
j = endDate
x = 3
Do Until i >= j
Cells(x, 1).Value = i + 7
i = i + 7
x = x + 1
Loop
End Sub```
When the date is incorrect it is displaying the message box but there is nothing to stop it from continuing through the code after the message box is closed. There are several ways you can fix this.
The first is to simply add the line
Exit Sub
after the msgbox is displayed.
However, I'm assuming you don't want the program to just give up after an incorrect input. Instead you likely want it to inform the user it was incorrect and ask for another input until they provide a valid format.
The way I typically do this is with a Do Until loop. Try this:
startDate = InputBox("Enter project start date in format mm/dd/yy", "User date",
Format(Now(), "dd/mm/yy"))
Do Until IsDate(startDate)
MsgBox "Wrong date format."
startDate = InputBox("Enter project start date in format mm/dd/yy", "User date",
Loop
endDate = InputBox("Enter project end date in format mm/dd/yy", "User date",
Format(Now(), "dd/mm/yy"))
Do Until IsDate(endDate)
MsgBox "Wrong date format."
startDate = InputBox("Enter project start date in format mm/dd/yy", "User date",
Loop
The second problem is because you are checking i's value before you add 7 to it. Plus, the endDate only gets printed if it happens to be a multiple of 7 away from the startDate. If you always want the end date to print you'll have to make some changes.
Try this instead:
i = startDate + 7
j = endDate
x = 3
Do Until i > j
Cells(x, 1).Value = i
i = i + 7
x = x + 1
Loop
Cells(x, 1).Value = endDate

Excel VBA - remove weekends from automatic timesheet print

I slightly amended some code I found online.
Purpose:
Click on a 'Print with Dates' button, then enter start date, and have Excel automatically generate/print a months worth of timesheets (much better than the previous spreadsheet having 6 weeks of pages to print, and you had to edit every date manually).
Issues:
It prints weekends, which wastes paper. Is there a way it can refer to a list of dates (weekends, public holidays), and not generate those for printing?
You'll see the date format is m/d/yyyy in the code, which strangely prints as dd/mm/yyyy (which is what I wanted). When the code was dd/mm/yyyy it was printing correctly (20/03/2019), but if it goes to the following month it was switching to American format m/d/yyyy (04/20/2019). I know it doesn't seem to make sense, but having it as m/d/yyyy actually prints as dd/mm/yyyy across any start/end dates. I'd like to know why, and also have dd/mm/yyyy in the code correctly printing across any date range.
CODE:
Sub PrintSheet()
Dim s As String
Dim d As Date
s = InputBox(Prompt:="Please enter the start date")
If Not IsDate(s) Then
MsgBox "Incorrect date", vbExclamation
Exit Sub
End If
For d = CDate(s) To DateAdd("m", 1, CDate(s)) - 1
Range("F2").Value = Format(d, "dddd")
Range("I2").Value = "" & Format(d, "m/d/yyyy")
ActiveSheet.PrintOut
Next d
End Sub
Cheers in advance :)
You can use the weekday function. It returns a number from 1 to 7. You can filter for 1-5 only for weekdays.
Sub PrintSheet()
Dim s As String
Dim d As Date
s = InputBox(Prompt:="Please enter the start date")
If Not IsDate(s) Then
MsgBox "Incorrect date", vbExclamation
Exit Sub
End If
For d = CDate(s) To DateAdd("m", 1, CDate(s)) - 1
If Weekday(d, vbMonday) < 6 Then
Range("F2").Value = Format(d, "dddd")
Range("I2").Value = "" & Format(d, "m/d/yyyy")
'MsgBox ("printing ") 'for testing
ActiveSheet.PrintOut
End If
Next d
End Sub

Textbox converts date into number

Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If Mid(TextBox1.Value, 4, 2) > 12 Then
MsgBox "Invalid date, please re-enter", vbCritical
TextBox1.Value = vbNullString
TextBox1.SetFocus
Exit Sub
End If
StartDate = DateSerial(Year(Date), Month(Date), Day(Date))
TextBox1.Value = Format(TextBox1.Value, "dd.mm.yyyy")
StartDate = TextBox1.Value
End Sub
This code works well for me and my colleagues to make sure the value entered in the textbox is a date. However, a colleague from a different country (but also with the dd.mm.yyyy date-format) gets weird results.
For example: If he enters 01.10.2017 the TextBox automatically format the date into 20.03.4917.
I suspect that in this case the entered value is not recognized as a date but as a number because 01102017 will transform into 20.03.4917 in Excel if you convert it as a date.
Does anyone have a suggestion or a guess how to work around this problem?
Thanks and best regards
You could split the date by . into an array ArrInput and then use DateSerial to make it a real date, that you can format.
Dim ArrInput As Variant
ArrInput = Split(TextBox1.Value, ".")
'StartDate = DateSerial(Year(Date), Month(Date), Day(Date)) 'I see no use in this at all
TextBox1.Value = Format$(DateSerial(ArrInput(2), ArrInput(1), ArrInput(0)), "dd.mm.yyyy")
StartDate = TextBox1.Value
The issue with Format(TextBox1.Value, "dd.mm.yyyy") is that here you let Excel guess which date format the string in TextBox1.Value is. It automatically casts into a number which is then converted into a string again.
To avoid date misunderstandings I recommend always to use the YYYY-MM-DD format according to ISO 8601. This is the only date format that is human readable and cannot be misunderstood. It also has benefits when sorting by dates that are actually strings.
To make your validation even more solid use something like:
Dim ArrInput As Variant
ArrInput = Split(TextBox1.Value, ".")
Dim ValidDate As Boolean
If UBound(ArrInput) = 2 Then 'make sure there are exactly two dots in the date
If ArrInput(1) > 0 And ArrInput(1) <= 12 And _ 'month <= 12
ArrInput(0) > 0 And ArrInput(0) <= 31 Then 'day <= 31
ValidDate = True
End If
Else
ValidDate = False
End If
If Not ValidDate Then
MsgBox "Invalid date, please re-enter in format dd.mm.yyyy", vbCritical
TextBox1.Value = vbNullString
TextBox1.SetFocus
Exit Sub
End If
TextBox1.Value = Format$(DateSerial(ArrInput(2), ArrInput(1), ArrInput(0)), "dd.mm.yyyy")
StartDate = TextBox1.Value
I do believe that your colleague enters the text string "01102017" without dots.
You might want to convert such kind of entries into a valid date:
' "01102017" => 01.10.2017 - 8 chars variant
' "011017" => 01.10.2017 - 6 chars variant
This needs to be done of cause prior to a date conversion.
Add a log of the input value to a free cell range and
have the workbook sent back to you:
...
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
Range("Z1").value = "'" & TextBox1.Value
If Mid(TextBox1.Value, 4, 2) > 12 Then
...
Check if only numbers are used:
How to check if a string contains only numbers?
and check the length of the string (6 or 8 chars variant) and check if the year part is within a valid range => try to convert to a date and offer it to the user.

VBA Excel - Problems with a simple macro to auto-fill cells for a budgeting spreadsheet I'm attempting to make

Disclosure: I'm fairly inexperienced at coding of most sorts but have a reasonable understanding of the logic behind it and quite often just need a little push with getting syntax's right etc.
What I'm trying to do is create a spreadsheet where across the top row is a list of consecutive dates. In the first few columns is data for bills etc. What I want my macro to do is look at the amount of a bill, the start and end dates and the frequency of the bill (weekly/monthly etc) and then populate the cells in that same row in the columns of the dates where the bill is due. I've spent the last day coming up with this code and I was pretty happy with it until I went to run it. I've already got rid of a few bugs where I was using a variable.Value which apparently doesn't exist but now I'm up against some issues outside of my grasp. And I've had no luck searching the internet.
The first problem that the debug finds is on this line:
currentDate = Cells(G, currentRow).Value 'Set Start Date
I'm getting a Run-Time Error '1004': Application-defined or Object-defined error. I'm sure that it's just a simple syntax problem or something. What that line is supposed to be doing (in the first instance) is looking at the Start Date in Cell "G3" which is formated as a date (04-Feb-14) and assigning the variable currentDate to that date so that I can then do a search across all the dates in the first row for that 'currentDate'.
Am I being clear enough? My code is below.
My Code:
Private Sub CommandButton1_Click()
Dim currentDate As Date
Dim currentRow As Integer
Dim repeatuntilDate As Date
Dim repeatuntilRow As Integer
currentRow = 3 'First row of entries
repeatuntilRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row 'Last row of entries
While currentRow < repeatuntilRow 'Loop from first row until last row of entries
currentDate = Cells(G, currentRow).Value 'Set Start Date
repeatuntilDate = Cells("H,currentRow").Value 'Set End Date
While currentDate <= repeatuntilDate 'Loop from Start Date until End Date
dateAddress = Range("J1:AAI1").Find(currentDate, LookIn:=xlValues).Address 'find the current date within the range of dates in row 1
Cells("dateAddress.Column,currentRow").Value = Cells("D,currentRow").Value 'Populate cell with amount
'Increment the currentDate by the chosen frequency
If Cells("E,currentRow").Value = "Weekly" Then
currentDate = DateAdd("ww", 1, currentDate)
ElseIf Cells("E,currentRow").Value = "Fortnightly" Then
currentDate = DateAdd("ww", 2, currentDate)
ElseIf Cells("E,currentRow").Value = "Monthly" Then
currentDate = DateAdd("m", 1, currentDate)
ElseIf Cells("E,currentRow").Value = "Quarterly" Then
currentDate = DateAdd("q", 1, currentDatee)
ElseIf Cells("E,currentRow").Value = "6 Monthly" Then
currentDate = DateAdd("m", 6, currentDate)
ElseIf Cells("E,currentRow").Value = "Annually" Then
currentDate = DateAdd("y", 1, currentDate)
' ElseIf Cells("E,currentRow").Value = "Once off" Then
' Exit While
End If
Wend
currentRow = currentRow + 1 'Once row is complete, increment to next row down
Wend
End Sub
to answer why you get Object Defined Error you missed the Cells property syntax which is:
Cells(row_index, col_index) which accepts long data type (numbers).
So it should be:
currentDate = Cells(currentRow, 7).Value 'G is the 7th column
But similarly you can refer to the col_index argument like this:
currentDate = Cells(currentRow, "G").Value 'take note of the qoutation marks ""

Excel VBA - compare date in cell to current date

(Excel 2010 VBA)
I have a cell (A1) containing a date in the format of mmm-yy ("Custom" category).
Foe example, if I enter 1/6/13 the cell shows June-13. That's fine.
In my VB macro I need to check this date whether the month is the current month and whether the year is the current year. I don't care about the day.
Does this help you:
Public Sub test()
d = Sheet1.Range("A1")
n = Now()
If Year(d) = Year(n) And Month(d) = Month(n) Then
MsgBox "It works"
End If
End Sub
Thanks to Dave and MiVoth I did :
Dim xdate As Date
xdate = Worksheets("sheet1").Range("A1")
If Month(Date) = Month(xdate) And Year(Date) = Year(xdate) Then
MsgBox "OK"
Else
MsgBox "not OK"
End If
That did the job!
Thank a lot to everyone,
Gadi
How about this:
Function MonthYear() As Boolean
MonthYear = False
If Not IsDate(Cells(1, 1)) Then Exit Function
If Month(Date) = Month(Cells(1, 1)) And Year(Date) = Year(Cells(1, 1)) Then
MonthYear = True
End If
End Function
The function returns true if month and year are the same as current date. If not it returns false.

Resources