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
Related
I am trying to make my input message box a bit more sophisticated by using a formula to generate a default date in an input message box in excel.
Currently, it just gives a default value of "dd-mm-yyyy" to guide the user and then deposits it in cell B2. Code below:
Dim DispatchDate As Variant
Sheets("Template").Select
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", "dd-mm-yyyy")
Range("B2").Value = DispatchDate
Id like the default value to be the result of the following formula =IF(WEEKDAY(NOW()*1,2)>4,NOW()+3,NOW()+1)
Essentially making the default date today + 1 day unless on a Friday, which would be be today + 3 days (to account for weekends and no Friday dispatch).
I don't even know where to start with this. Any help would be appreciated.
This can be done with the IIF structure, that corresponds to the IF of the front-end:
Sub fnEvaluateDate()
Dim DispatchDate As Date
Sheets("Template").Select
With Excel.WorksheetFunction
DispatchDate = Format(IIf(.Weekday(VBA.Now() * 1, 2) > 4, VBA.Now() + 3, VBA.Now() + 1), "dd-mm-yyyy")
End With
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", DispatchDate)
Range("B2").Value = DispatchDate
End Sub
you can use evaluate method to extract value from formula:
Dim DispatchDate As Date
DispatchDate = Evaluate("=IF(WEEKDAY(TODAY(),2)>4,TODAY()+3,TODAY()+1)")
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", DispatchDate)
or you can convert sheet formula into VBA code:
Dim DispatchDate As Date
DispatchDate = IIf(Weekday(Date, 2) > 4, Date + 3, Date + 1)
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", DispatchDate)
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
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.
I have a UserForm where in a TextBox if user inputs a date format other than dd/mm/yyyy then an error message will pop up after clicking the submit button. Here is what I have so far, it only formats an invalid date input to dd/mm/yyyy but does not display the validation:
If IsDate(Me.DOBTextBox.Value) Then
Me.DOBTextBox = Format(Me.DOBTextBox.Value, "dd/mm/yyyy")
ElseIf Not IsDate(Me.DOBTextBox.Value) Then
MsgBox "Please enter a valid date format dd/mm/yyyy", vbCritical
DOBTextBox.SetFocus
Exit Sub
End If
Validate if there are 2 slashes / in it and day <= 31 and month <= 12:
Dim ArrInput As Variant
ArrInput = Split(Me.DOBTextBox.Value, "/")
Dim ValidDate As Boolean
If UBound(ArrInput) = 2 Then 'make sure there are exactly two slashes in the date
If ArrInput(1) > 0 And ArrInput(1) <= 12 And _
ArrInput(0) > 0 And ArrInput(0) <= 31 Then 'month <=12 & day <= 31
ValidDate = True
End If
Else
ValidDate = False
End If
If Not ValidDate Then
MsgBox "Please enter a valid date format dd/mm/yyyy", vbCritical
DOBTextBox.SetFocus
Exit Sub
End If
'code here that executes when date is valid
Dim MyValidDate As Date
MyValidDate = DateSerial(ArrInput(2), ArrInput(1), ArrInput(0))
Alternatively just try to convert the string date into a real date and check if day, month and year match the values in the string.
Dim ArrInput As Variant
ArrInput = Split(Me.DOBTextBox.Value, "/")
Dim ValidDate As Boolean
If UBound(ArrInput) = 2 Then 'make sure there are exactly two slashes in the date
Dim MyValidDate As Date
MyValidDate = DateSerial(ArrInput(2), ArrInput(1), ArrInput(0))
If Day(MyValidDate) = CLng(ArrInput(0)) And _
Month(MyValidDate) = CLng(ArrInput(1)) And _
Year(MyValidDate) = CLng(ArrInput(2)) Then
ValidDate = True
End If
End If
If Not ValidDate Then
MsgBox "Please enter a valid date format dd/mm/yyyy", vbCritical
'DOBTextBox.SetFocus
Exit Sub
End If
'code here that executes when date is valid
MsgBox "date is valid " & MyValidDate
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)