IsDate Function not recognizing date - vba

I've got this code
If IsDate(EndTime) = True Then
Worksheets("Control_File2").Range("D" & lrow2).Value = EndTime
Else
Worksheets("Control_File2").Range("D" & lrow2).Value = "Not Provided"
End If
and currently End Time = "25/08/2021 07:35:47.546" but the code always goes to the "Else" condition.
why is it not recognizing it as a date?

As GSerg pointed out, the milliseconds are not being handled by IsDate().
Function IsDate2(Value As Variant) As Boolean
Rem I added this line to escape empty strings
If Len(Value) = 0 Then Exit Function
IsDate2 = IsDate(Split(Value, ".")(0))
End Function

Related

DateDiff Not Working while trying to extract hour difference [duplicate]

I've got this code
If IsDate(EndTime) = True Then
Worksheets("Control_File2").Range("D" & lrow2).Value = EndTime
Else
Worksheets("Control_File2").Range("D" & lrow2).Value = "Not Provided"
End If
and currently End Time = "25/08/2021 07:35:47.546" but the code always goes to the "Else" condition.
why is it not recognizing it as a date?
As GSerg pointed out, the milliseconds are not being handled by IsDate().
Function IsDate2(Value As Variant) As Boolean
Rem I added this line to escape empty strings
If Len(Value) = 0 Then Exit Function
IsDate2 = IsDate(Split(Value, ".")(0))
End Function

Proper use of boolean/case?

I'm having issues figuring out if I properly wrote this function. It'll be fed a string that either contains a "%" or a "#" as the last character ie. "TA_PQ_SI02_%". I just want this function to tell me if it's a % or #.
Did I do this in the most effiecient/proper way? I think not, and would like to learn why.
Private Function numberOrPercentCheck(ByVal cleanCode As String) As Boolean
Select Case cleanCode
Case Right(cleanCode , 1) = "#"
numberOrPercentCheck= True
Case Right(cleanCode , 1) = "%"
numberOrPercentCheck= False
Case Else
Debug.Print "Error: " & cleanCode & " is not formatted properly with a # or % at the end, and has been set to a default #"
numberOrPercentCheck = True
End Select
End Function
When you just want a Boolean:
Private Function numberOrPercentCheck(ByVal cleanCode As String) As Boolean
numberOrPercentCheck = Right(cleanCode, 1) = "#"
End Function
When you need a third possibility:
Private Function numberOrPercentCheck(ByVal cleanCode As String) As Variant
Select Case Right(cleanCode, 1)
Case "#": numberOrPercentCheck = True
Case "%": numberOrPercentCheck = False
Case Else: numberOrPercentCheck = "Error: " & cleanCode & " is not formatted properly with a # or % at the end"
End Select
End Function

How to check if a date cell in Excel is empty?

If feels like this should be really easy but I dont get it to work without retrieving the value of the cell again.
To start with, I have 2 date cells:
Dim agreedDate As Date
Dim completedDate As Date
THIS WORKS .. (but looks messy)
agreedDate = Worksheets("Data").Cells(Counter, 7).Value
completedDate = Worksheets("Data").Cells(Counter, 9).Value
If (IsEmpty(Worksheets("Data").Cells(Counter, 7).Value) = True) Or (IsEmpty(Worksheets("Data").Cells(Counter, 9).Value) = True) Then
[.. do stuff]
End If
THIS DOES NOT WORK - WHY NOT?!
agreedDate = Worksheets("Data").Cells(Counter, 7).Value
completedDate = Worksheets("Data").Cells(Counter, 9).Value
If (IsEmpty(agreedDate) = True) Or IsEmpty(completedDate) = True) Then
[.. do stuff]
End If
Is there a way to write the if statement in a clean and easy way?
Since only variables of type Variant can be Empty, you need a different test for Date types.
Check for zero:
If agreedDate = 0 Or completedDate = 0 Then
But a safer path would be to change the variables to type Variant and then do this test:
If IsDate(agreedDate) = False Or IsDate(completedDate) = False Then
The IsEmpty function determines indicated whether a variable has been initialized. If a cell is truly blank then it is considered uninitialized from the IsEmpty standpoint. However, declaring a variable in VBA gives it a default value. In this case the date type variables are essentially 0 or 30-Dec-1899 00:00:00 as demonstrated by the following short snippet.
Sub date_var_test()
Dim dt As Date
Debug.Print Format(dt, "dd-mmm-yyyy hh:mm:ss")
End Sub
If you want to 'tidy up' your code, you might also wish to allow the true boolean return of the IsEmpty function to resolve the boolean condition rather than comparing it to True.
If IsEmpty(Worksheets("Data").Cells(Counter, 7)) Or IsEmpty(Worksheets("Data").Cells(Counter, 9)) Then
[.. do stuff]
End If
Given that False is (for all intents and purposes) zero then this will work for your date type variables.
If Not (agreedDate or completedDate) Then
[.. do stuff]
End If
As Excel Hero pointed out, a date variable cannot be empty. In fact, a date variable is a number, so you should be able to do something like this. Also, notice that the code below uses "Value2".
Sub test()
Dim d As Date
d = Range("A1").Value2
If d = 0 Then
MsgBox "ok"
Else
MsgBox "not ok"
End If
End Sub

Getting return without gosub in my own function in vba

I've been battling with vba for a bit and surprisingly it's not getting much better.
I have written the following code so I can have a special comparison operator for an object.
Public Function myEquals(v As CCtypestore) As Boolean
If v Is Nothing Then
myEquals = False
Return
End If
If Me.Acronym = v.Acronym Then
myEquals = True
Return
End If
myEquals = False
Return
End Function
The object v I'm passing in is Nothing at the moment so I would have sort of expected the result to be a trivial False. Surprisingly instead I'm getting an error Return without gosub. Any clue why that might be?
Delete the Return statements!
In VBA, you set the return value with the line myEquals = ....
All in all, you can reduce your function to the following code:
Public Function myEquals(v As CCtypestore) As Boolean
If Not v Is Nothing Then
myEquals = (Me.Acronym = v.Acronym)
End If
End Function
Alternatively, use this:
Public Function myEquals(v As CCtypestore) As Boolean
On Error Goto ErrorHandler
myEquals = (Me.Acronym = v.Acronym)
Exit Function
ErrorHandler:
myEquals = False
End Function
Return is an old relic if you want to work with direct jumps in the code, i.e. build spaghetti code! See this example from the help file:
Sub GosubDemo()
Dim Num
' Solicit a number from the user.
Num = InputBox("Enter a positive number to be divided by 2.")
' Only use routine if user enters a positive number.
If Num > 0 Then GoSub MyRoutine
Debug.Print Num
Exit Sub ' Use Exit to prevent an error.
MyRoutine:
Num = Num/2 ' Perform the division.
Return ' Return control to statement.
End Sub ' following the GoSub statement.
Use Exit Function instead of Return.
You can also avoid those Exit Function by using a construction like
If .... Then
'some code
ElseIf...Then
'some other code
ElseIf...Then
'etc
Else
'final
End if

Make sure that a string is exactly a 5 digit number

I want to return true if some strings = 'XXXXX'
Where every X is a number 0 through 9
I know there must be a dozen ways to do this but I would like to know the best way.
yourString Like "#####"
If you want the simplest way, you can go with this:
Function MyFunction(myString As String) As Boolean
MyFunction = ((Len(myString) = 5) And (IsNumeric(myString)))
End Function
If you want the more efficient way, you'd have to run some tests for the different methods people suggested.
Edit: The previous solution doesn't work well (see the first 2 comments) but I'm letting it there since it's what has been accepted. Here is what I would do :
Function MyFunction(myString As String) As Boolean
Dim myDouble As Double
Dim myLong As Long
myDouble = Val(myString)
myLong = Int(myDouble / 10000)
MyFunction = ((Len(myString) = 5) And (myLong > 0) And (myLong < 10))
End Function
There is no error "protection" in that function, so if you try to check a too large number like 22222222222222, it will not work.
Similar question previously asked: link text
Basically want to check
(Len(s) = 5) And IsNumeric(s)
You can also use regular expressions to solve this problem. If you include Microsoft VBScript Regular Expressions 5.5 in your VBA project, you can use RegExp and MatchCollection variables as in the function below. (This is a modification of the response to this post at ozgrid.com.)
Public Function FiveDigitString(strData As String) As Boolean
On Error GoTo HandleError
Dim RE As New RegExp
Dim REMatches As MatchCollection
With RE
.MultiLine = False
.Global = False
.IgnoreCase = True
.Pattern = "^[0-9][0-9][0-9][0-9][0-9]$"
End With
Set REMatches = RE.Execute(strData)
If REMatches.Count = 1 Then
FiveDigitString = True
Else
FiveDigitString = False
End If
Exit Function
HandleError:
Debug.Print "Error in FiveDigitString: " & Err.Description
FiveDigitString = False
End Function