VBA - Why IsNumeric is not evaluating correctly - vba

I have following code in VBA to evaluate a variable lngPNumber to send the "correct" value to a WorksheetFunction.vLookup function:
Dim lngPNumber As Variant
lngPNumber = ActiveSheet.Cells(objInitialCell.Row, INT_ACCP_COL_PNUMBER).Value
If IsNumeric(lngPNumber) = False Or CDbl(lngPNumber) <> Round(CDbl(lngPNumber)) Then
lngPNumber = CStr(ActiveSheet.Cells(objInitialCell.Row, INT_ACCP_COL_PNUMBER).Text)
End If
lngPNumbercan be:
an integer value (f.i. 4111)
a float value (41.111111)
or just a
string value (normally "xxxx" but can also be filled with strings
like "asdasd", "dasdsadasd", etc...)
In the last both cases, I want to send the Cell Text and not the Cell Value where lngPNumberis obtained.
However, I get a Type Missmatch error if the value is a string like in the last example in the list. Any help?

The If will try to resolve both sides of the Or regardless if the first is false or true, so CDbl(lngPNumber) will error if lngPNumber is text.
So split them into two.
Dim lngPNumber As Variant
lngPNumber = ActiveSheet.Cells(objInitialCell.Row, INT_ACCP_COL_PNUMBER).Value
If Not IsNumeric(lngPNumber) Then
lngPNumber = CStr(ActiveSheet.Cells(objInitialCell.Row, INT_ACCP_COL_PNUMBER).Text)
ElseIF CDbl(lngPNumber) <> Round(CDbl(lngPNumber)) Then
lngPNumber = CStr(ActiveSheet.Cells(objInitialCell.Row, INT_ACCP_COL_PNUMBER).Text)
End If
Now the second will fire only if lngPNumber is a number.

Related

Formula Array returns nothing or just #VALUE! when using Evaluate

Im trying to evaluate Formula array to find a value from sheet with multiple criteria. The sheet name is Holiday_master
So in another sheet Temp_data I tried to exceute the following code to set that value in that cell using formula array
Public Function getCostMultiplier(dt As Date, wt As String) As Double 'dt is the date of entry, wt working time name "India Full Time","Singapore f........
Dim lRow As Integer
Dim we As Boolean
we = IsWeekend(dt)
Dim nhRange As Range
Dim d As Double
d = CDbl(dt)
Dim location As String
Select Case LCase(Trim(wt))
Case "india full time 45"
location = "INDIA"
Case "singapore full time 40"
location = "SINGAPORE"
Case "uk full time 40"
location = "UK"
End Select
Dim n As Integer
'n = Application.Evaluate()
lRow = Sheets("Holiday_master").Range("A1000").End(xlUp).Row + 1
Dim formula As String
Dim s As String
s = Application.Evaluate("RC11")
formula = printf("{=INDEX( Holiday_master!R2C3:R{0}C3,MATCH(1,(""{1}""=Holiday_master!R2C2:R{0}C2)*({2}=Holiday_master!R2C1:R{0}C1),0),1)}", lRow, location, d)
''''INDEX( Holiday_master!R2C3:R11C3,MATCH(1,("INDIA"=Holiday_master!R2C2:R11C2)*(43126=Holiday_master!R2C1:R11C1),0),1)
n = Application.Evaluate(formula)
getCostMultiplier = n
End Function
Public Function printf(mask As String, ParamArray tokens()) As String
Dim i As Long
For i = 0 To UBound(tokens)
mask = Replace$(mask, "{" & i & "}", tokens(i))
Next
printf = mask
End Function
So in Temp_data sheet in a cell I set the formula as getCostMultiplier(RC11,RC4)', so obviously it reaches my function with parameters26-01-2018andINDIA`
So in the code we have a final formula which is I commented there INDEX( Holiday_master!R2C3:R11C3,MATCH(1,("INDIA"=Holiday_master!R2C2:R11C2)*(43101=Holiday_master!R2C1:R11C1),0),1)
But its not evaluating as I expected or this could not be the way for evaluation of formula array.
If I execute that formula in that cell manually and on submitting (ctrl+shift+enter) it executes properly and returning the value.
So I didnt understand how to do that same from VBA or how to do that Evaluation. I never used Evaluation before
Convert the formula from xlR1C1 to xlA1 syntax.
n = Application.Evaluate(Application.ConvertFormula(formula, xlR1C1, xlA1))
Using Evaluate within VBA should be done with xlA1 syntax.
I got it working with R1C1 itself. The issue was, I specified curly braces there in the formula array which is not required in the case of Evaluate
So here is my modified formula code with error validation also added
formula = printf("=IFERROR(INDEX(Holiday_master!R2C3:R{0}C3,MATCH(1,(""{1}""=Holiday_master!R2C2:R{0}C2)*({2}=Holiday_master!R2C1:R{0}C1),0),1),1)", lRow, location, CStr(d))

How do I check whether value in active cell contains any letter or not?

For example cell "A1" is linked to cell "B1", so in formula bar for cell "A1" we have:
=B1
How can I check whether value in cell "A1" contains letter B?
I tried the following:
Dim Criteria_3 As Boolean
Dim Value As Range
Set Value = Selection
Dim x As Variant
Set x = Cells
Dim text As String
For Each x In Value
If IsNumeric(x) Then
Criteria_3 = VBA.InStr(1, x.Formula, text) > 0
As soon as value of "Text" is "" it does not work and I really struggle to fined the right solution.
your question is not really conclusive, so here are two options:
To check wheter the value contains B:
blnCheck = 0 < InStr(1, rngCell.Value, "B")
To check wheter the Formula contains B:
blnCheck = 0 < InStr(1, rngCell.Formula, "B")
Regarding your null string problem:
As soon as value of "Text" is "" it does not work and I really struggle to fined the right solution.
That's because you're using VBA.InStr(1, x.Formula, text) and in this case 1 is an invalid index on a string of length 0. You can omit that, or you can code around it like:
If Len(Trim(x.Formula)) = 0 Then
'## Do nothing
Else
Criteria_3 = VBA.InStr(1, x.Formula, text) > 0
End If
To your specific question of identifying when a value contains any alpha character(s):
You can use a function like this to test whether a value contains any letter, by evaluating the Ascii code for each character, and break when True:
Function ContainsAnyLetter(val) As Boolean
Dim ret As Boolean
Dim str$, ch$
Dim i As Long
str = LCase(CStr(val))
For i = 1 To Len(str)
ch = Mid(str, i, 1)
If 97 <= Asc(ch) And Asc(ch) <= 122 Then
ret = True
Exit For
End If
Next
ContainsAnyLetter = ret
End Function
In your code, you could call it like:
Criteria_3 = ContainsAnyLetter(x.Value) '## or x.Formula, depending on your needs
You can use LIKE
https://msdn.microsoft.com/en-us/library/swf8kaxw.aspx
Something like if rngCell.value like "*B*" then
if your goal is to check whether the cell contains any valid range reference, then you could go like this
Option Explicit
Sub main()
Dim cell As Range
For Each cell In Worksheets("Sheet001").Range("A1:A20") '<== jus a test range, set it as per your needs
MsgBox IsCellReference(cell.Formula)
Next cell
End Sub
Function IsCellReference(text As String) As Boolean
On Error Resume Next
IsCellReference = Not Range(Replace(text, "=", "")) Is Nothing
End Function

How can I convert an Userform Textbox value which is a String into a Long in Excel Vba?

Here I am trying to read a Textbox.Value which is a String into a Variable (i.e. text_bval) and converting that String into a Long using CLng function for my calculations. The CLng function is showing run time error like type mismatch.
See my code below:
Dim text_bval As String
Dim text_long As Long
Dim per As Integer
text_bval = text_box.value
user_entry = CLng(text_bval)
According to the MS Documentation, "If expression lies outside the acceptable range for the Long subtype, an error occurs."
In this case, your expression is text_bval, a string. If your string contains characters that cannot be converted to a number, an error will occur.
For example:
text_bval = "2" then CLng(text_bval) = 2
text_bval = "2.3" then CLng(text_bval) = 2
text_bval = "hello" then CLng(text_bval) = ERROR
In order to prevent an error from occuring, you should do something like the following:
user_entry = 0
On Error Resume Next
user_entry = CLng(text_bval)
On Error GoTo 0

Checking Data Types in a Range

I am trying to validate the data types of all cells in a user-selected range are the same, using a VBA function. I have the following code (simplified), which works for the most part:
Dim vTempRange As Variant
Dim vCell As Variant
vTempRange = DataRange.Value
For Each vCell In vTempRange
If Len(vCell) > 0 Then
'Use TypeName(vCell)
'Complete validation here
End If
Next vCell
Sometimes a user may select a column of percentages, sometimes a column of decimal values, and sometimes a time value (not associated with a date). VBA seems to see all three of these as a Double, which is technically not incorrect. The problem is, the format of the selection will be used as part of the final output, so 12:00:00 should display as such, and not 0.50, which is currently the case.
I looked into using something like this in conjunction:
Dim vCell As Variant
For Each vCell In DataRange
If Len(vCell) > 0 Then
'Use vCell.NumberFormat
'Complete validation here
End If
Next vCell
But the NumberFormat is not consistent. e.g., a user may have a percent listed as 0% vs. 0.000% or a time as h:m:s vs. hh:mm:ss, so I see it as being difficult to correctly capture this value.
Is there a way to accurately determine without user intervention when a time is selected vs. one of the other types? Determining a percent value versus a 0<x<1 decimal value would also be nice, but not required.
I have other options at my disposal, such as ignoring the formatting in the final output (really not desirable) or explicitly asking the user to identify the type (but this is neither as clean nor automatic as I would like).
Try this. Paste this in a module. You can then use it as a Worksheet formula.
I had this code in my database which was picked up from here and I modified it to suit your needs.
Public Function CellType(c)
Application.Volatile
Select Case True
Case IsEmpty(c): CellType = "Blank"
Case Application.IsText(c): CellType = "Text"
Case Application.IsLogical(c): CellType = "Logical"
Case Application.IsErr(c): CellType = "Error"
Case IsDate(c): CellType = "Date"
Case InStr(1, c.Text, ":") <> 0: CellType = "Time"
Case InStr(1, c.Text, "%") <> 0: CellType = "Percentage"
Case IsNumeric(c): CellType = "Value"
End Select
End Function
ScreenShot
You can further modify it to add an IF clause inside Case IsNumeric(c): CellType = "Value" to check for decimals, Scientific notation etc using INSTR
Declare vCell as Range and then do your check:
TypeName(vCell.Value)
That will accurately catch your dates.
YOu will likely need to add some if/then logic to capture "percents" since these are double-type values -- the "%" part is merely cell formatting, so you may be able to just check the Right(vCell.NumberFormat,1) = "%" .
VarType function
Returns an Integer indicating the subtype of a variable, or the type of an object's default property.
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/vartype-function
Ex1: using to write if.
Function DataType(x As Variant) As String
If VarType(x) = vbDate Then
DataType = "Date"
ElseIf VarType(x) = vbString Then
DataType = "String"
'.....
End If
End Function
Ex2: concatenate cells in range having value.
Function ConcatenateRange(cellRange As Range) As String
Dim cel As Range, temp As String
temp = ""
For Each cel In cellRange
'use VarType to check if the cell is empty.
'if the cell is not empty concatinate it.
If VarType(cel) <> vbEmpty Then
temp = temp & cel
End If
Next
ConcatenateRange = temp
End Function

How to check a variable if it have a value or not?

I have a variable which contains a range value which is selected by the user.
How can I check if it have a value or not?
I've tried these:
If variable_name.Value = Empty then ....
If variable_name.Value = " " then ...
But these are only good when the variable contains data like text or numbers or whitespace.
Any idea?
Depends what you are testing.
A range object or a cell value?
Sub test()
Dim rngObject As Range
Dim value As Variant
Set rngObject = Sheet1.Range("A1:D5")
If Not rngObject Is Nothing Then
'If not nothing then run this code
End If
value = rngObject.Cells(1, 1).value
If Not IsEmpty(value) Then
'if Not empty then run this code
End If
If value <> vbNullString Then
'if value is not nullstring then run this code
End If
End Sub