QTP: Checking If an array of strings contains a value - vbscript

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

Related

Microsoft VBScript runtime error '800a000d' Type mismatch: 'LastID'

I do a function to assign an ID. But when I click button, this error comes out.
Microsoft VBScript runtime error '800a000d' Type mismatch: 'LastID'
Public function AssignSanctionID(DeptID,SectID,SanctionType)
REM obtain Transaction ID
dim CmdX
dim SQLX
dim RsX
dim Prefix
dim LastID
dim CurrID
dim NewCurrID
'- Set Connection
HariNi=now()
Tahun=year(HariNi)
Bulan=month(HariNi)
if len(bulan)=1 then
Bulan= "0" & Bulan
end if
If Cint(Tahun) < 2016 then
Pref1= DeptID & "/" & SectID & "/"
Prefix=DeptID & "/" & SectID & "/" & Tahun & "/" & Bulan & "/"
else
Pref1= DeptID & "/%/" & SectID
Prefix=DeptID & "/" & Tahun & "/" & Bulan & "/"
end if
set CmdX = server.CreateObject("ADODB.Command")
Set RSX = Server.CreateObject("ADODB.Recordset")
SQLX = " SELECT * FROM Sanction " _
& " WHERE SanctionID like '%" & Pref1 & "%' " _
& " ORDER BY ID DESC"
CmdX.ActiveConnection = objconn
CmdX.CommandText = SQLX
RsX.Open CmdX,,0,1
if not(RsX.BOF and RsX.EOF) then
If Cint(Tahun) < 2016 then
LastID = right(RsX("ID"),4)
else
LastID = mid(RsX("ID"),13,4)
end if
else
if Bulan="04" then
LastID=0
end if
end if
RsX.Close
set RsX = nothing
'Set ID
If LastID<>"" then
'CurrID = left(4)
CurrID=int(LastID)+1
end if
if len(currid)>0 then
select case len(currid)
case 1
newcurrid = "000" & currid
case 2
newcurrid = "00" & currid
case 3
newcurrid = "0" & currid
case 4
newcurrid = currid
end select
else
NewCurrID="0001"
end if
If Cint(Tahun) < 2016 then
NewCurrID=Prefix & NewCurrID
else
NewCurrID=Prefix & NewCurrID & "/" & SectID
end if
AssignSanctionID = NewCurrID
end function
Hard to help if I don't see the data.
From quick view of the code the issue is here:
CurrID=int(LastID)+1
You are trying to cast LastID but are you sure that it is convertible? Could list all possible values?
Short answer: CInt only works with Numerical values. If you have letters in your value, then Cint wont work.
Bit longer answer:
Having read the Blog that we should be more welcoming (https://stackoverflow.blog/2018/04/26/stack-overflow-isnt-very-welcoming-its-time-for-that-to-change/?cb=1), here is a very general answer, but that might lead you on the correct way to fix it yourself.
Type Mismatch is an error you can get when using a variable the wrong way. For example if you try to do numerical functions with Strings (which means the variable contains letters a-z etc) you will get "Type Mismatch" as you cant add or subtract text in a mathematical way... On the other hand you cant add Integer variables (the variable only contains a number AND isnt contained within "quote marks").
So below is a few ways to assigna a variable and what type it becomes:
LastID=1 'This makes LastID an INT (number)
LastID="1" 'This makes LastID a String but a CInt(LastID) can turn it into an INT because it ONLY contains numbers.
LastID="IT" 'This makes LastID a String that CANT in any way be cast to INT as it contains letters.
LastID=IT 'This row will either create an error except if you already have a variable called IT, then LastID will get the same value as the IT variable...
This should hopefully get you on your way to fix this issue...

ComboBox strategies to function

I have four combo box everything does the same as follows:
Select Case combobox1.selectedItem
case 0
str=str & "' AND"
case 1
str= str & "'"
end case
select case combobox2.selected item
case 0
str=str & "' AND"
case 1
str= str & "'"
end case
Similarly the other two comboboxes have the same body
I want to replace this code block by a method call and implement the select clause body in a method body and call it when required.
Please give me a solution
Create a method that takes the input as combobox selected index i.e an integer
now in the method write as follows:
method1(int x)
{
Select Case x
case 0
str=str & "' AND"
case 1
str= str & "'"
end case
}
Call method1 where required.

VBS using LIKE to compare strings "Sub or Function not defined"

I'm trying to make a script to connect a network printer to a user computer.
The script uses the computer name who needs the printer as a parameter.
Printers names are similar their printserver name, eg. server_USA has printers like printer_USA01, printer_USA02.
But it's throwing the error "Sub or Function not defined" when arrives at the first like... why ?
Set shl = WScript.CreateObject("WScript.Shell")
strName = Wscript.Arguments.Item(0)
'input Printer name
strPrinter = InputBox("Please enter share name of printer to install:", _
"Add network printer")
if strPrinter = "" then
msgbox "Can't be empty."
WScript.quit
elseif strPrinter Like "printer_USA*" then
strServer = server_USA
elseif strPrinter Like "printer_SPAIN*" then
strServer = server_SPAIN
else
'Printer name NOT registered, input printserver manually:
strServer = inputbox("Please enter the name of the printserver","printserver")
if strServer = "" then
msgbox "Can't be empty."
WScript.quit
End if
End if
'ADD
shl.run "RUNDLL32 PRINTUI.DLL,PrintUIEntry /ga /c\\" & strName & " /n\\" & strServer & "\" & strPrinter
there is no Like operator in VBScript. You could use Instr.
if strPrinter = "" then
msgbox "Can't be empty."
WScript.quit
elseif Instr( 1, strPrinter, "printer_USA", vbTextCompare ) > 0 then
strServer = server_USA
The vbTextCompare constant ( value=1) is used to Perform a textual comparison
you can use StrComp to have same result in this way
If StrComp(strPrinter,"printer_USA",vbTextCompare)=0 then
strServer = server_USA
End IF
equal 0 mean zero different between strPrinter and printer_USA with ignore the letter case because we use vbTextCompare .
You can replace vbTextCompare with 1 and you will have same result.
If letter case is important you can use vbBinaryCompare or 0.
A way to do that with select case. This version of instr() is case sensitive, but other versions aren't. instr() returns the position of the found substring, which here is always one.
select case 1
case instr(strPrinter, "") + 1
wscript.echo "empty"
case instr(strPrinter, "printer_USA")
wscript.echo "server_USA"
case instr(strPrinter, "printer_SPAIN")
wscript.echo "server_SPAIN"
case instr(strPrinter, "printer_ITALY"), instr(strPrinter, "printer_RUSSIA")
wscript.echo "other known ones"
case else
wscript.echo "not registered"
end select
I used the following alternative (VBScript Regular Expressions)…
Uses slightly different syntax from LIKE but easiest solution to make a match successfully similar to LIKE operator.
dim regExp
set regExp=CreateObject("VBScript.RegExp")
regExp.IgnoreCase = true
regExp.Global = true
regxp.Pattern = ".*Test Pattern.*" ' example only, basic pattern
if regExp.Test(MyString) then
' match successful
end if

Difference between isEmpty(value) and Trim(value) = ""

I'm new to vb i don't get the difference between these 2 statements:
isEmpty(value)
and
Trim(value) = ""
Can you explain it? Are they equals?
edit:
i have a code like this in my example
if isempty(request.form("alias")) then
...
elseif trim(request.form("alias")) = "" then
...
end if
All VBScript variables are Variants, but there are subtypes. An empty/not initialized variable has the subtype Empty. The value of such a variable 'works' like 0 or "" in expressions:
>> Dim EmptyVar
>> WScript.Echo VarType(EmptyVar), TypeName(EmptyVar), 1 + EmptyVar, "a" & EmptyVar & "c"
>>
0 Empty 1 ac
>> WScript.Echo CStr(EmptyVar = 0), CStr(EmptyVar = "")
>>
True True
A string variable (initialized by a literal or a string expression) has the subtype String.
It may be empty - i.e. contain no characters - but such a beast is not of subtype Empty:
>> Dim NixStr : NixStr = ""
>> WScript.Echo VarType(NixStr), TypeName(NixStr), 1 & NixStr, "a" & NixStr & "c"
>>
8 String 1 ac
>>
The VBScript function IsEmpty() checks whether a variable is empty/not initialized:
>> WScript.Echo CStr(IsEmpty(EmptyVar)), CStr(IsEmpty(NixStr))
>>
True False
That is why you should check the return value of Inputbox() with IsEmpty() - did the user cancel/abort - and against "" - did the user try to feed "" to the program.
Trim returns the string without ony spaces on the left or right. Eg, " hello world " will become "hello w world".
isEmpty returns a boolean. If the string is empty ("") it will return true, otherwise it will return false.

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