VBScript : checking if the user input is an integer - vbscript

Within a VBScript, I need to make sure the user inputs a integer.
Here is what I have now :
WScript.Echo "Enter an integer number : "
Number = WScript.StdIn.ReadLine
If IsNumeric(Number) Then
' Here, it still could be an integer or a floating point number
If CLng(Number) Then
WScript.Echo "Integer"
Else
WScript.Echo "Not an integer"
End If
End if
The problem is that CLng() doesn't test if my number is an integer : the number is converted anyway.
Is there a way to check if a number is an integer ?
EDIT :
The suggested answer doesn't work as well for me. Here is a new version of my code :
WScript.Echo "Enter an integer number : "
Number = WScript.StdIn.ReadLine
If IsNumeric(Number) Then
' Here, it still could be an integer or a floating point number
If Number = CLng(Number) Then
WScript.Echo "Integer"
Else
WScript.Echo "Not an integer"
End If
End if
and here is the output :
U:\>cscript //nologo test.vbs
Enter an integer number :
12
Not an integer
U:\>cscript //nologo test.vbs
Enter an integer number :
3.45
Not an integer

This will actually work:
WScript.Echo "Enter an integer number : "
Number = WScript.StdIn.ReadLine
If IsNumeric(Number) Then
' Here, it still could be an integer or a floating point number
If CStr(CLng(Number)) = Number Then
WScript.Echo "Integer"
Else
WScript.Echo "Not an integer"
End If
End If
Previously, the problem was that you were comparing a string vs an integer which would never evaluate to true.
Now, you take a string, check if it's numeric, transform it to CLng() which will return only the integer part of the number, transform it back to a string and finally compare it against the original string.
If you enter... "asdasD" (or any other non-numeric thing) it doesn't pass the "isNumeric" check.
If you enter "10.5" (as a string) when converted to CLng() you get 10 when then gets converted to "10" and compared against "10.5". Since the strings don't match, it says it's not an integer.
If you enter "10" converted to CLng() it's 10, back to string it's "10" which returns a true when matching it against "10", meaning it is an integer.
A few years too late I know, but I was looking into this myself just now and got puzzled by it. Hope it helps anyone else wondering around like myself.

This is very similar to your code:
WScript.Echo "Enter an integer number : "
Number = WScript.StdIn.ReadLine
If IsNumeric(Number) Then
' Here, it still could be an integer or a floating point number
If CLng(Number) = Number Then
WScript.Echo "Integer"
Else
WScript.Echo "Not an integer"
End If
End If

cogumel's answer above almost gets it, but failed for me in odd ways. I discovered that it would return true for "5" (in quotes), but not 5 (without quotes). When doing the final comparison you need to convert the original input to string as well, to make it all work reliably. Here it is wrapped in a neat function:
public function is_integer( input )
is_integer = false
If IsNumeric(input) Then
If CStr(CLng(input)) = CStr(input) Then is_integer = true
End If
end function
I've also tested this with zero (true), negative integers (true), both in and out of quote marks.

If you do something like this, it should work:
if Number = CInt(Number) Then

CLng would throw an exceprion for numbers bigger than 2147483647 or lower than -2147483648.
WScript.Echo "Enter an integer number : "
Number = WScript.StdIn.ReadLine
If IsNumeric(Number) Then
' Here, it still could be floating point number out of CLng's range
If CDbl(Number) <= 2147483647 and CDbl(Number) >= -2147483648 Then
' Here, it still could be floating point number
If CLng(Number) & "" = Number & "" Then
WScript.Echo "Integer"
Else
WScript.Echo "Not an integer"
End If
Else
WScript.Echo "Not an integer"
End If
End If

Here is a slightly different way to do it, it doesn’t matter if you are passing an integer, long, or a string. The function also checks if the number is a positive number, but you can change that by removing Abs().
If IsNumber("1010") Then
MsgBox "Valid whole number"
Else
MsgBox "Not a valid whole number"
End If
Function IsNumber(ByVal Number)
IsNumber = False
If IsNumeric(Number) Then
If CStr(Number) = CStr(Abs(Fix(Number))) Then
IsNumber = True
End If
End If
End Function

I found this simple program to validate numeric value from http://rindovincent.blogspot.com/p/vbscript-programs.html and with permission i am pasting the same. I hope it will be helpful for beginners like me
<HTML>
<HEAD><TITLE>Simple Validation</TITLE>
<SCRIPT LANGUAGE="VBScript">
<!--
Sub Submit_OnClick
Dim TheForm
Set TheForm = Document.ValidForm
If IsNumeric(TheForm.Text1.Value) Then
If TheForm.Text1.Value < 18 Or TheForm.Text1.Value > 40 Then
MsgBox "Age must be above 18"
Else
MsgBox "Thank You"
End If
Else
MsgBox "Please enter a numeric value"
End If
End Sub
-->
</SCRIPT>
</HEAD>
<BODY>
<H3>Simple Validation</H3><HR>
<FORM NAME="ValidForm">
Enter your age:
<INPUT NAME="Text1" TYPE="TEXT" SIZE="2">
<INPUT NAME="Submit" TYPE="BUTTON" VALUE="Submit">
</FORM>
</BODY>
</HTML>

another way,
if number > 0 then
...
end if

Related

Multiple condition loop

I need a VBScript loop asking to entered an integer between 1 to 10 including, if wrong symbol or number entered then asking again until the desired number is retrieved from user.
This is what I tried:
Option Explicit
Dim Num
Num=inputbox("Please enter integer number between 1 to 10")
'Checking if entered value is numeric
Do while not isnumeric(Num)
Num=inputbox("Please enter integer number between 1 to 10", "INCORRECT SYMBOL")
Loop
Do while (Num<1 or Num>10)
Num=inputbox("Please enter integer number between 1 to 10 ", "Number is NOT IN RANGE")
Loop
Do while not int(Num)
Num=inputbox("Please enter integer number between 1 to 10 ", "Number is NOT INTEGER")
Loop
does not work: when I enter 3 for example I am getting inputbox saying "Number is NOT INTEGER", when entering a letter I receive error message Type mismatch string, error code 800A00D.
You need one Loop. For each (variant) input you need to check:
is it Empty (User pressed Cancel or X) - Abort
is it a blank (zero length or sequence of spaces) string
is it numeric
is it an integer
is it in range - Accept
As in:
Option Explicit
Dim vNum, sNum, nNum
Do
vNum = InputBox("Please enter an integer beween 1 and 10 (inclusive)")
If IsEmpty(vNum) Then
WScript.Echo "Aborted"
Exit Do
Else
sNum = Trim(vNum)
If "" = sNum Then
WScript.Echo "Empty string"
Else
If IsNumeric(sNum) Then
nNum = CDbl(sNum)
If nNum <> Fix(nNum) Then
WScript.Echo "Not an Integer"
Else
If nNum < 1 Or nNum > 10 Then
WScript.Echo "Not in range"
Else
WScript.Echo nNum, "is ok"
Exit Do
End If
End If
Else
WScript.Echo "Not a number"
End If
End If
End If
Loop
WScript.Echo "Done"
Using different variables for the different data types may be pedantic, but should show why you had type problems.
Your
Do while not int(Num)
does not work as expected because here Num is a number between 1 and 10; rounding off the (not existing) fractional part gives Num again; Num evaluated in a boolean context/as a bool gives (always) True.
Update wrt comment:
Trim removes space from the head or tail of a string; WScript.Echo sends output to the console (cscript) or a dialog box (wscript).
Update:
As this question shows, I didn't make clear that pressing Cancel or X (Close) sets vNum to an empty variant, which is different from an empty/zero length string. So it should be treated as indication of the users intention to abort.
BTW: You need to read the Docs, but you can't believe them always (cf. here).

Round function not working properly

I tried to round off value using VBscript
here is my code
sql = "select lastcode from " & session("gasbook") & ".acccode where account='" _
& Trim(rsgrn.fields("stockcode")) & "'"
response.write sql
rs.Open sql, cn
if err.number<>0 then
cn.rollbacktrans
call HandleError(err.number,err.description,err.source)
Response.End
else
if (rs.EOF and rs.BOF) then
cn.RollbackTrans
Response.Write "GAS Code doesn't exist in " & session("gasbook")
Response.End
else
If clng(rs.Fields("lastcode")) <> 0 Then
cn.RollbackTrans
Response.Write "Stock Account must be control account in " _
& session ("gasbook")
Response.End
End If
end if
end if
dim tmp
tmp = rsgrn.Fields("amount")
response.write tmp
response.write round(tmp)
tmp has value 2984.5, but when I apply round on tmp it convert into 2984 instead of 2984.5.
The number is rounded to 2948 because the .Net framework follows the Bankers Rounding algorithm off of the IEEE 754 standard. It is not a question of if the number was rounded, it is rounded to the nearest even number due to standards.
Evidence: Here. and Here.
So, the round function is working perfectly to the IEEE Standards.
When in doubt, read the documentation. Without the optional second parameter numdecimalplaces, the Round function returns an integer:
numdecimalplaces
Optional. Number indicating how many places to the right of the decimal are included in the rounding. If omitted, integers are returned by the Round function.
Change the line
response.write round(tmp)
to
response.write round(tmp, 1)
if you want the value rounded to one decimal.

QTP: Checking If an array of strings contains a value

I am having trouble getting my test case to run correctly.
The problem is in the code below, the first if statement to be exact. QTP complains that an object is required
For j=Lbound(options) to Ubound(options)
If options(j).Contains(choice) Then
MsgBox("Found " & FindThisString & " at index " & _
options.IndexOf(choice))
Else
MsgBox "String not found!"
End If
Next
When I check the array I can see that it is populated correctly and 'j' is also the correct string.
Any help with this issue would be greatly appreciated.
Strings in VBScript are not objects, in that they do not have member functions. Searching for a substring should be done by using the InStr function.
For j=Lbound(options) to Ubound(options)
If InStr(options(j), choice) <> 0 Then
MsgBox("Found " & choice & " at index " & j
Else
MsgBox "String not found!"
End If
Next
A concise way to check if an array of strings contains a value would be to combine the Filter and UBound functions:
If Ubound(Filter(options, choice)) > -1 Then
MsgBox "Found"
Else
MsgBox "Not found!"
End If
Cons: you don't get the indexes where the elements are found
Pros: it's simple and you have the usual include and compare parameters to specify the matching criteria.
Function CompareStrings ( arrayItems , choice )
For i=Lbound(arrayItems) to Ubound(arrayItems)
' 0 - for binary comparison "Case sensitive
' 1 - for text compare not case sensitive
If StrComp(arrayItems(i), choice , 0) = 0 Then
MsgBox("Found " & choice & " at index " & i
Else
MsgBox "String not found!"
End If
Next
End Function
Hi if you check exact String not sub-String in the array use StrComb because if use InStr then if array = "apple1" , "apple2" , "apple3" , "apple" and choice = "apple" then all will return pass for every array item.
Function CompareStrings ( arrayItems , choice )
For i=Lbound(arrayItems) to Ubound(arrayItems)
' 1 - for binary comparison "Case sensitive
' 0 - not case sensitive
If StrComp(arrayItems(i), choice , 1) = 0 Then
CompareStrings = True
MsgBox("Found " & choice & " at index " & i
Else
CompareStrings = False
MsgBox "String not found!"
End If
Next
End Function

How to indicate if string has numeric value

I loop over string variable data which may have integer numeric value, like "123". If this string variable has numeric value, I want to indicate it and thought to use some like this:
If IsNumeric(CInt(data)) Then
WScript.Echo "Number"
Else
WScript.Echo "String"
End If
But CInt() raises error every time data variable can't be converted to integer:
Type mismatch: 'CInt'
How can I indicate if string has integer value in vbscript?
IsNumeric Function of vb script can be used to determine whether an expression can be evaluated as a number.It returns Boolean value depending upon expression
Please be noted that IsNumeric returns False if expression is a date expression.
Now, in your code you have mistaken that even if it is not number, you trying to convert it into integer
You can use this in your code like this--
If IsNumeric(data) Then
WScript.Echo "Number"
Else
WScript.Echo "String"
End If
only for integers:
If VarType(data) = vbInteger Then
WScript.Echo "Integer"
Else
WScript.Echo "Something else"
End If
for numbers:
If IsNumeric(data)
WScript.Echo "Number"
Else
WScript.Echo "string"
End If

VBScript Data Validation - Numeric 1 Results in Infinite Loop

DISCLAIMER: I'm still an uber-n00b with programming concepts and know just enough VBS to hurt myself, so I'm likely to slur/slaughter some of the terms/concepts/ideas that are entailed with this program I'm trying to write. You, the vastly superior programmer who has every right to flame me, have been warned.
I've been trying to write a VBScript to validate data, specifically Dates. Since my users are kind of poor with keyboards, I figured I'd make it easy by separating the entry of each part of the date (Month & Day only, I've got the Year set statically).
Previously, I was having problems with validating the numbers with only 1 "Do...Loop", as I was trying to verify if it was Numeric Input and checking at the same time if it was within the specified range (1 - 12, for the 12 months of the year).
This is what the previous code roughly looked like:
Do
' If...Then Statements Here
Loop Until (dtFirstMonth > 0) _
And (dtFirstMonth < 13) _
And IsNumeric(dtFirstMonth) _
And (dtFirstMonth <> "") _
And (dtFirstMonth <> vbNull)
This often resulted in "Data Type Mismatch" errors, so I had to split the Validation Critera to two separate "Do...Loop" statements, as you can see in the current code I have below:
Sub srTest()
Do
dtFirstMonth = InputBox("Please Enter a Numeric Month for the Starting Range", _
"Starting Range Month")
If (dtFirstMonth = vbNull) _
Or (dtFirstMonth = "") _
Or Not IsNumeric(dtFirstMonth) Then
MsgBox "Please Enter a Valid Numeric Month",, "Enter Month Number"
ElseIf (dtFirstMonth <> vbNull) _
And (dtFirstMonth <> "") _
And IsNumeric(dtFirstMonth) Then
Do
dtFirstMonth = Round(dtFirstMonth)
Wscript.Echo dtFirstMonth ' Infinite Loop Here (Basically, As Soon As We Get Into Loop with a Value of 1, We're Stuck)
dtFirstMonth = CInt(dtFirstMonth)
' Must Convert User Input to Integer to
' Prevent Data Mismatch Errors In
' Following "If" Statement; Besides,
' It Passed the First Test to be a
' Numeric Value in the First Place
If (dtFirstMonth < 1) Or (dtFirstMonth > 12) Then
MsgBox "Please Enter a Valid Numeric Month",, "Enter Month Number"
Exit Do
' Drop Out of 2nd Level Loop to
' Enter Into 1st Level Loop
End If
Loop Until (dtFirstMonth > 0) _
And (dtFirstMonth < 13) _
And IsNumeric(dtFirstMonth) _
And (dtFirstMonth <> "") _
And (dtFirstMonth <> vbNull)
If (dtFirstMonth < 1) Or (dtFirstMonth > 12) Then
dtFirstMonth = ""
End If
' dtFirstMonth Was Converted to Integer Earlier
' This is to Meet the Value that Didn't Pass
' the Nested Do & If Statement (Level 2 Do Loop)
' Sets dtFirstMonth to "Empty String" to Continue
' Looping in the Level 1 "Do...Loop" Statement;
' If Omitted, Level 1 "Do...Loop" is Satisfied,
' Thus Ending the Subroutine (Since the Value
' of dtFirstMonth is Still a Numeric Value)
End If
Loop Until IsNumeric(dtFirstMonth) _
And (dtFirstMonth <> "") _
And (dtFirstMonth <> vbNull)
Wscript.Echo dtFirstMonth
End Sub
srTest
I had to set up the 1st "Do...Loop" to check that the User Input (dtFirstMonth) was a indeed a Numeric Value and not a Null Value nor an Empty String. The Nested "Do...Loop", or 2nd "Do...Loop", statement is where I have the same Criteria plus the extra Criteria defining the desired ranges (any number between 1 and 12).
This is working perfectly for number 2-12, but when the script parses the number 1, I enter into an Infinite Loop.
I've checked to make sure that the Infinite Loop is occurring in the 2nd "Do...Loop" by replacing the entire 2nd "Do...Loop" section with "Wscript.Echo dtFirstMonth". By doing this, I get the expected results: a single Echo, not an infinite number of them (technically, I get 2, as I do have another "Wscript.Echo dtFirstMonth" string at the bottom of the Subroutine for the purpose of debugging, but either way, it's not an Infinite Loop).
I've also changed the criterion for the lower range to be like this, yet this doesn't remediate the error:
Do
' If...Then Statements Here
Loop Until (dtFirstMonth >= 1)
I've also tried this, with no resulting success:
Do
' If...Then Statements Here
Loop Until (dtFirstMonth >= CInt(1))
In all reality, there really is no need for this segment, since I converted the User's Input to an integer anyway.
Since this was starting to get confusing, I decided to add the "Round" statement before the script passed the User's Input to the "CInt" function, hoping that it would make sure that it wasn't getting caught as a 0 value or decimal value somehow; yes, this is irrational thought on my part, but I still wanted to explore all avenues (there's also the fact that I have some users with "Fat Finger Syndrome" and some others with "Abuse The Program" mentality, so I figured I'd make sure the script accounted for decimal entries). I added the "Round" string before and after the nested "Do...Loop" and I still had the Infinite Loop issue.
This is as far as I've been able to get on this and now I'm stuck.
I realize that there are likely better ways to do Date/Time Validation in VBScript, and I'm certainly open to any new suggestions, but I'd love to solve this for the pure sake of edification.
Way too much code for a simple input of a number. Just try to keep it short and simple. Example:
Do
dtm = InputBox("Please Enter a Numeric Month for the Starting Range", _
"Starting Range Month")
Select Case True
Case isNull(dtm), (not isNumeric(dtm)), dtm = "", dtm = empty, (dtm < 1 OR dtm > 12)
' too exhaustive, but just for the sake of the example.
MsgBox "Please enter an amount between 1 and 12"
Case else
' Hey, this seems to be a valid amount!
Exit do
End Select
Loop While True
' Do something with dtm
Just showed you some creative Select Casing, this supports lazy exit, so if a value is Null, it escapes before getting evaluated where evaluating could throw an error.
The problem is with your attempt to check for null values:
(dtFirstMonth = vbNull)
The proper way to check for nulls, as demonstrated in AutomatedChaos' answer, is with the IsNull function. vbNull is actually a constant that's used with the VarType function. The value of vbNull is 1, which is why that particular value behaved differently from other entries. That's the fundamental problem, and if you replace every dtFirstMonth = vbNull with IsNull(dtFirstMonth), you won't get an infinite loop when entering 1.
Now, the actual place where your code infinitely loops is interesting. I would expect the first conditional If (dtFirstMonth = vbNull) to evalute true for an entry of "1", and you would get the message box "Please enter a valid numeric month". However, the Else condition is triggered. This is weird because normally, when you compare a string to a number, VBScript will attempt to convert the number to a string or vice versa, so if dtFirstMonth is "1", it should be equal to vbNull (which is 1). However, there appears to be a special case when you compare a string variable to an integer variable. See this example:
' vbNull = 1, built-in constant
dtFirstMonth = "1"
MsgBox (dtFirstMonth = vbNull) ' False
MsgBox ("1" = vbNull) ' True
MsgBox (dtFirstMonth = 1) ' True
MsgBox (CInt(dtFirstMonth) = vbNull) ' True
I don't know if this is a bug or just an obscure detail about VBScript's implicit conversion, but it does illustrate that implicit conversion can be unpredictable in VBScript.
As far as alternative methods go, you may be interested in the IsDate function, which returns True if the given expression can be converted into a date. It may not be ideal for your users and their keyboard skills, but it would reduce your code to:
Do
str = InputBox("Enter a date (MM/DD)")
If IsDate(str) Then
Exit Do
Else
WScript.Echo "Please enter a valid date"
End If
Loop
dt = CDate(str)
' Put your static year here; CDate will default to the current year
dtActual = DateSerial(2007, Month(dt), Day(dt))
WScript.Echo (dtActual) & " - Thanks!"
Note that IsDate should return False for the typical edge cases ("", Null, Empty, etc.), so there's no need for a separate check.
I found a simple program to generate Date and time from http://rindovincent.blogspot.com/p/vbscript-programs.html. I am pasting the same program with permission.
<html>
<body>
<center>
<script type="text/vbscript">
d=CDate("October 22, 2010")
document.write(d&"<br/>")
document.write("Current system date is:"&date&"<br/>")
document.write("Current system time is:"&time&"<br/>")
document.write(DatePart("m",Now())&"<br/>")
document.write(DateAdd("yyyy",1,"31-Jan-10") & "<br />")
document.write(MonthName(10,true)& "<br />")
fromDate="22-sep-10 00:00:00"
toDate="21-oct-10 23:59:00"
document.write(DateDiff("m",fromDate,toDate)&"<br />")
document.write(DateDiff("y",fromDate,toDate) & "<br />")
document.write(DateDiff("w",fromDate,toDate) & "<br />")
document.write(DateDiff("h",fromDate,toDate) & "<br />")
</script>
</center>
</body>
</html>

Resources