Date function changing DD-MM-YYYY to MM-DD-YYYY output - excel

I'm setting up a userform for employees to fill in data. They need to fill in the date like DD-MM-YYYY the output must also be DD-MM-YYYY. However the code I use changes input 5-12-2019 (DD-MM-YYYY), to output 12-5-2019 (MM-DD-YYYY). In the userform it stays like (DD-MM-YYYY) expect for when you tranfer it to your excel sheet. If the month is above 13 it doesn't change, so input 13-12-2019 (DD-MM-YYYY) stays output 13-12-2019 (DD-MM-YYYY). How is it possible that the code changes the output but not everytime the same way, did I do something wrong in the code?
Private Sub TextBox1_BeforeUpdate(ByVal cancel As MSForms.ReturnBoolean)
If IsDate(Me.TextBox1.Text) Then
Me.TextBox1.Text = Format(Me.TextBox1.Text, "DD-MM-YYYY")
Else
MsgBox "Vul een geldige datum in", vbRetryCancel + vbCritical
End If
End Sub
Public Function IsTime(Expression As Variant) As Boolean
If IsDate(Expression) Then
IsTime = (Int(CSng(CDate(Expression))) = 0)
End If
End Function

Read the date as a string. E.g. 5-12-2009.
Split the string by -.
The 0th value is the day, the 1st is the month, the 2nd is the year.
From there, you have a fully functioning date, using DateSerial().
Public Function StringToDate(myInput As String) As Date
Dim day As Long
Dim month As Long
Dim year As Long
Dim dateArray As Variant
dateArray = Split(myInput, "-")
day = dateArray(0)
month = dateArray(1)
year = dateArray(2)
StringToDate = DateSerial(year, month, day)
End Function
Public Sub Main()
Debug.Print month(StringToDate("05-10-2001"))
Debug.Print StringToDate("05-10-2001")
End Sub

Related

Getting Type Mismatch Error while calling sub procedure

I am taking two input from USERFORM "CheckIn Time (hh:mm format)" and "Checkout Time (hh:mm format)" through TextBox, and trying to get immediate output in 3rd Text Box (hh:mm format) which shows difference between check in and checkout.
To achieve this I am using Call Sub procedure method.
However I am getting error
"Run time 13: Type mismatch".
I am new to VBA and I am literally stuck at this since 2 weeks. Please help.
I tried changing DATA type but didn't get any positive result.
Private Sub CHKIN_Change() 'Calling GetTime
Call GetTime
End Sub
Private Sub CHKOUT_Change() 'Calling GetTime
Call GetTime
End Sub
Private Sub TOTALHRS_Change() 'Calling GetTime
Call GetTime
End Sub
'below Calculating difference b/t Checkin & Checkout, displaying in "TOTALHRS" textbox
Sub GetTime()
Dim Time1, Time2, TotalTime As Date
Time1 = CHKIN.Text
Time2 = CHKOUT.Text
TotalTime = DateDiff("s", Time1, Time2)
TotalTime = Totalhour / 86400
TOTALHRS.Text = Format(Totalhour, "hh:mm")
End Sub
'Using below code to convert checkin and checkout input in hh:mm format.
Private Sub CHKIN_AfterUpdate()
Dim tDate As Date
Dim tString As String
With CHKIN
'Check if user put in a colon or not
If InStr(1, .Value, ":", vbTextCompare) = 0 Then
'If not, make string 4 digits and insert colon
tString = Format(.Value, "0000")
tDate = TimeSerial(Left(tString, 2), Right(tString, 2), 0)
CHKIN.Value = Format(tDate, "HH:MM")
Else
'Otherwise, take value as given
.Value = Format(.Value, "hh:mm")
End If
End With
Exit Sub
End Sub
Desired result wanted: checkout - checkin = hh:mm
Example: 23:20 - 9:35 = 13:45

Workbook reference via VBA doesn't accept variable

I am trying to set up references to other workbooks, whereby the location is static: G:\XY\XY\[Workbook2019.xlsx]2019-04'!C1
Since these references change depending on what month it is, I want, for ease of use, set up an input-box where one can type in a number like 01 or 04 and it would exchange the month part in the reference.
My code looks like this so far:
Sub MonthRef()
Dim strMonth As String
strMonth = InputBox("Enter month as interger (e.g. 01 for Jan; 02 for Feb.)", "Month")
Range("B4").Formula = "='G:\XY\[XY.xlsx]2019-" & strMonth & " '!C1"
End Sub
weirdly enough, I seem to get the correct reference, but the cell wont accept the number for some reason and prompts me to select one of the sheets from a workbook.
I cannot seem to find the problem.
Any help is greatly appreciated!
Personally I'd flesh this out a little further to avoid other mistakes from user input as well. This can be done by using a function to test the user input is the correct criteria and looping until either it is, or the user cancels
Private Function TestUserInput(v As String) As Boolean
TestUserInput = False
If IsNumeric(v) And Len(v) <= 2 Then
If CLng(v) > 0 And CLng(v) <= 12 Then
TestUserInput = True
End If
End If
End Function
Public Sub MonthRef()
Dim strMonth As String
Dim IsUserInputValid As Boolean
Dim InputBoxPrompt As String
InputBoxPrompt = "Enter month as integer (e.g. 01 for Jan; 02 for Feb.)"
Do
strMonth = Trim(InputBox(InputBoxPrompt, "Month"))
' Test if strMonth is valid
IsUserInputValid = TestUserInput(strMonth)
' Handle User cancelled
If strMonth = vbNullString Then
Exit Sub
' If input is not valid then prompt user
ElseIf IsUserInputValid = False Then
MsgBox prompt:="Input not valid. " & InputBoxPrompt, Title:="Error"
End If
' Loop until input is valid or User cancels
Loop Until IsUserInputValid
Range("B4").Formula= "='G:\XY\[XY.xlsx]2019-" & Format(strMonth, "00") & "'!C1"
End Sub

Validate Input box entry between min and max number

I used InputBox for the "period" which is the month ("m").
When I try using it for the "year" ("YYYY") it does not function as expected.
My code for the "year" (same as in "period", only different values and variables):
Dim VYear as variant
Dim defY as variant
defY = Format(DateAdd("YYYY", 0, Now), "YYYY")
VYear = InputBox("Year covered","Year",defY)
If VYear > 2014 And VYear < defY Then
Range("I1").Value = VYear
ElseIf VYear = "" Then
Exit Sub
Else
Do Until VYear > 2014 And VYear < defY
MsgBox "Please enter a year not earlier than 2015 and not later than this year"
VYear = InputBox("Year covered")
Loop
End If
It does give me the default value of 2018. When I tried entering wrong values, it proceeds with the message in MsgBox as expected, but it would no longer accept ANY values, even the year "2018".
Cycle goes: MsgBox (Please enter....) then InputBox then MsgBox again.
I intentionally used As Variant so that even though users input letters, it won't give the error of "type mismatch".
It should look like this …
Option Explicit
Public Sub AskForYear()
Dim InputValue As Variant 'needs to be variant because input is FALSE if cancel button is pressed
Dim DefaultYear As Integer
DefaultYear = Year(Date) 'Get the year of the current date today
Do
InputValue = Application.InputBox(Prompt:="Please enter a Year between 2015 and " & DefaultYear & "." & vbCrLf & "Year covered:", Title:="Year", Default:=DefaultYear, Type:=1)
If VarType(InputValue) = vbBoolean And InputValue = False Then Exit Sub 'cancel was pressed
Loop While InputValue < 2015 Or InputValue > DefaultYear
Range("I1").Value = InputValue 'write input value
End Sub
It uses a Do loop that is at least run once (note the criteria is in the Loop While part). It keeps asking for a date between 2015 and this year until the criteria is met. Then it will continue to write into the range.
Note that there is a cancel criteria to catch if the user pressed the cancel button. Then it exits the sub without writing into the range.
This is just hypothetical for your specific case (asking for a year) but …
For this criteria it is not sufficient to test If InputValue = False if you plan to accept 0 as number input. Therefore you need also to test for Booleantype:
If VarType(InputValue) = vbBoolean
This is because False is automatically cast to 0.
Note that I used Application.InputBox instead of InputBox. These are 2 completely different ones:
Application.InputBox(Prompt, Title, Default, Left, Top, HelpFile, HelpContextID, Type)
'see the different parameters
InputBox(Prompt, Title, Default, XPos, YPos, HelpFile, Context) As String
In Application.InputBox you can provide a Type parameter which I set to 1 which means it only accepts numbers (see Application.InputBox Method). With just InputBox you cannot do this.
I recommend to use meaningful variable names, which makes it much easier to read and maintain the code. Also only use Variant if really necessary. In this case it is, because the Application.InputBox can either return a Boolean (cancel button) or number (input).
Another recommendation is to always specify a worksheet for a Range like Worksheets("Sheet1").Range("I1") otherwise Excel guesses which worksheet you mean and it might easily fail.

Stop changing date value in VBA

Excel keeps changing my date to US format. I have a user form where the user inputs a date. As an example, I enter 01/11/2018 (1st November 2018). I then put this value into a cell however it changes automatically to 11/01/2018 or 11th January 2018.
I've so far tried using the following code to force it to use UK format;
SHT_data_TASKS.Cells(1 + tableRows, 8).NumberFormat = "dd/mm/yyyy;#"
SHT_data_TASKS.Cells(1 + tableRows, 8) = form_addTask_Date.Value
But it does not help. I've also tried using CDate function but still no luck. I've checked my computer regional settings and they are all correct for the UK.
If I right click on the cell where the date is placed and chose format it shows as already being formatted to UK date! I'm not sure what is causing it to change.
This is the date code I use on control containing UK dates:
Private Sub UserForm_Initialize()
Me.txtDate = Format(Date, "dd-mmm-yyyy")
End Sub
On the AfterUpdate event for the date control:
Private Sub txtDate_AfterUpdate()
With Me
FormatDate .txtDate
End With
End Sub
In a normal module:
Public Sub FormatDate(ctrl As Control)
Dim dDate As Date
Dim IsDate As Boolean
If Replace(ctrl.Value, " ", "") <> "" Then
On Error Resume Next
dDate = CDate(ctrl.Value)
IsDate = (Err.Number = 0)
Err.Clear
On Error GoTo 0
If IsDate Then
ctrl.Value = Format(ctrl.Value, "dd-mmm-yyyy")
ctrl.BackColor = RGB(255, 255, 255)
Else
ctrl.BackColor = RGB(255, 0, 0)
End If
End If
End Sub
Then I transfer it to the worksheet (on a Save button) using the below code:
shtRawData.Cells(rLastCell.Row, CLng(lCol)) = CDate(ctrl.Value)
When you're about to write your date to the sheet:
Verify that it's being stored as a date (or date equivalent) with isdate()
Assign it via Range.FormulaLocal instead of value or value2.
Untested, but i.e.
Range("A1").FormulaLocal = #10/31/2018#

Using VBA to check if a date is between two dates

So, I have looked through many of the questions on this site to answer this question, and I believe that my code is correct, but it still doesn't verify correctly. I cannot figure out why though.
What I am trying to do:
I am in Excel with a User Form. I have a date input box and a calendar picker. When one is changed, the other updates. I am trying to verify that the date entered into the input box is a valid date and within a two years time span, and if it is then update the calendar picker.
Errors:
If a wrong date is entered into the input box then the program
errors out as it cannot update the calendar picker with an invalid
date. (This is an old error and thus why I do the validation check)
If any valid date is entered, it does not verify correctly in the "If" statement.
For instance:
If I enter 2/18/2016, it should see that it is a valid date, is later than the oldDate and more recent than the lateDate. Then update the calendar picker with the value of the input box. But, with this code it always resets the value of the input box and gives the message that it didn't verify.
Code:
Private Sub weekInput_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Dim tempDate
Dim oldDate
Dim lateDate
tempDate = weekInput.Value
oldDate = Date - 365
lateDate = Date + 365
'Doing this to try and error check if an invalid date is given. Doesn't work for some reason.
If IsDate(tempDate) And tempDate > oldDate And tempDate < lateDate Then
'Find date of that week's Monday
weekPicker.Value = weekInput.Value
Else
weekInput.Value = weekPicker.Value
MsgBox "Didn't verify"
End If
End Sub
Thank you to #RonRosenfeld for his answer in the comments on the question. Here is the corrected code which works. Added code that also shows an error message if the date doesn't validate by changing text color on the User Form from blending into the background to being red.
Changes Explained:
The first changes made was to declare what type of variable tempDate, oldDate, and lateDate were. Before, not having them declared made them Variant. This insures that they are recorded as a date type and thus can be compared as I was trying to do.
So:
Dim tempDate
Dim oldDate
Dim lateDate
Becomes:
Dim tempDate As Date
Dim oldDate As Date
Dim lateDate As Date
The second change is moving the IsDate() to its own If statement. This is due to the fact that if the inputted text was not a date, it would cause a fatal error before even reaching the other If statement as it was trying to save a non-date to a variable of date type. So tempDate = weekInput.Value became:
If IsDate(weekInput.Value) Then
tempDate = weekInput.Value
End If
The rest remained the same. Except I deleted the MsgBox and made a nicer, less obtrusive error message by changing the color of an error message from blending into the background to being red by adding these lines of code:
dateError.ForeColor = &H80000004
dateError.ForeColor = &HFF&
Answer:
Here is the full code:
Private Sub weekInput_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Dim tempDate As Date
Dim oldDate As Date
Dim lateDate As Date
If IsDate(weekInput.Value) Then
tempDate = weekInput.Value
End If
oldDate = Date - 365
lateDate = Date + 365
If tempDate >= oldDate And tempDate <= lateDate Then
weekPicker.Value = weekInput.Value
dateError.ForeColor = &H80000004
Else
weekInput.Value = weekPicker.Value
dateError.ForeColor = &HFF&
End If
End Sub

Resources