I have this code in VBS:
Dim Arg()
Set objArgs = WScript.Arguments
for i=0 to objArgs.Count
Arg(i) = Replace(objArgs(i),"\n",vbNewLine,1,-1,1)
... (yes, the for has a Next at the end)
(example arguments: "hello\nworld" "test" 0 64)
But when I run it, it throws an error: The subscript is out of range (line 4, column 3).
Am I incorrectly using the arrays, or is the problem in the for, or what is wrong?
Arrays in VBScript are zero ordinal based that means that if you have for example ten elements in the array they will be numbered zero to nine.
So when using Count it will return the number of elements not their position in the array so you will need to minus one from the Count or VBScript will report a "Subscript out of range" error as there is no 11th element in the array to iterate to.
As suggested in the comments, you want to do this;
For i = 0 To objArgs.Count - 1
The other issue is you declare a dynamic array (Dim Args()) but never initialise it before trying to insert elements into it. You could see this answer to a similar question that explains the problem. When using a dynamic array declaration you need to initialise it using ReDim.
Useful Links
subscript out of range while adding items to array
Visual Basic scripting dynamic array
Related
I have a query which I am trying to solve
I know that one can use strcmp(s1,s2) to compare two different strings to see whether they are the same. It gives 1 if that is the case.
However, how would one tackle this problem if you have a variable length array full of strings and you want to the whether all strings in the array are the same.
For example: ['NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'] we can see that all the strings are the same in this array. However, how would one go about with using strcmp(s1,s2).
Thanks guys!
If you want all pairwise comparisons between strings: call ndgrid to generate indices of all combinations, and then index into your cell array of strings and call strcmp:
x = {'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
[ii, jj] = ndgrid(1:numel(x));
result = strcmp(x(ii), x(jj));
In this case
result =
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
because all strings are the same.
You probably had a pairwise comparison using strcmp in mind, but you can use it directly on cell arrays:
x={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'}
result=all(strcmpi(x{1},x(2:end)))
Compare the first element to the remaining elements. It returns true only if all elements are equal. For a pairwise comparison you could us:
[~,~,c]=unique(x);
result=bsxfun(#eq,c,c.')
If you're solving the problem with a matrix (i.e. every row is a string) there are no particularly nice solutions in my opinion, but if your strings are contained into a cell array, things are getting easier and nicer.
So we start by creating such cell array:
myStrings={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
where each cell contains a string. This will make your code more robust as well since every string can have a different length (this is not true if you concatenate all your strings in a matrix).
Then you specify which string you want to find inside such cell array:
stringThatMustBeTested='NACA64A010';
Now you can use cellfun(), which is a function that applies another function to every cell of a given cell array as follows:
results=cellfun(#(x) strcmp(x,stringThatMustBeTested),myStrings);
Such line simply means "apply strcmp() to every generic cell x inside myStrings and compare the cell with stringThatMustBeTested".
Variable results will be a logical output in which element j will be true if the j-th cell in your cell array is equal to the string you want to test. If results is entirely composed by 1s (which you can check as if sum(results)==length(results)), then all the strings are the same in myStrings (given that stringThatMustBeTested is the unique string in your cell array but anyways, this solution can be extended to a broader string search inside a cell).
Like the title says, a cell A1 contains the formula ={1,2,3}, which is a valid input for a cell, can I use VBA to get the elements of the array.
Note that Range("A1").Value returns the value 1, but Range("A1").Formula returns the string ={1,2,3}. So the only way I could think of is to parse the formula and separate the values with the , (like CSV line).
Is there any other way to return an array of values in vba in this situation. I even tried to read it as an array into a variant with v=Range("A1:A2").Value2 but v(1) contains 1 only.
You can first get the FormulaArray property of the Range object, then Evaluate it to return the full array:
v = Evaluate(Range("A1").FormulaArray)
You can access the elements as you expect (and/or manipulate them as having declared an Array normally):
v(1) --> 1
v(2) --> 2
v(3) --> 3
I'm having some troubles doing something easy: checking the most recent date in an array. I create an array of webelements. There are some dates in this array in "fixed" places and I want to take the most recent of them.
This is what I'm doing:
Set cc = Description.Create
cc("micclass").value="WebElement"
cc("name").value="arrow_down"
Set collcc=Browser("Br").Page("Page").ChildObjects(cc)
For i=lbound(collcc) to ubound(collcc)
Msgbox collcc(x).getroproperty("innertext")
x =x +9
Next
The problem is that the script stops at the beginning of the for, saying that there is a "wrong number of arguments or invalid property assignment ubound" (and the same happens with lbound.
What am I doing wrong?!
Just from memory, but i think ChildObjects does not return an array. Try with
for i = 0 to collcc.Count - 1
....
next
Child object is the collection of objects so you needs to loop through "for each " Snippet given below
for each col in collcc
Msgbox col.getroproperty("innertext")
Next
Thanks
Sai
I have the below code, i want to check if index 3 in array is existing or not, but i always got this error :
Microsoft VBScript runtime error '800a0009'
Subscript out of range: '[number: 0]'
urlArray=Split(url1,"/")
If (not isNull(urlArray(3))) then
If (urlArray(3)="site") Then
newUrl=urlArray(0) &"/"& urlArray(1) &"/"& urlArray(2) &"/m/" & urlArray(4) & "/" & urlArray(5)
Else
newUrl= url1
End If
Else
newUrl= url1
End If
Use function "IsArray" to make sure that variable is array, see here:
IsArray returns True if the variable is an array; otherwise, it
returns False. IsArray is especially useful with variants containing
arrays.
Use function "UBound" to check upped bound of array, see here:
Returns the largest available subscript for the indicated dimension of
an array. UBound(arrayname[, dimension])
The lower bound for any dimension is always 0.
I am not 100% what the role of the 1: is here. At which index to start the copy? But then why not two such parameters for the rank 2 array?
To be a little more explicit:
In Fortran90 and up you access a single array value by giving a single index, and access a subarray (a window of the array) by giving a range of indices separated by a colon.
a(1) = 0.
a(2:5) = (/3.14,2.71,1.62,0./)
You can also give a step size.
a(1:5:2) = (/0,2.71,0./)
And finally, you can leave out values and a default will be inserted. So if a runs from index 1 to 5 then I could write the above as
a(::2) = (/0,2.71,0./)
and the 1 and 5 are implied. Obviously, you shouldn't leave these out if it makes the code unclear.
With a multidimensional array, you can mix and match these on each dimension, as in your example.
You're taking a slice of array2, namely the elements in the D'th column from row 1 to C and putting them in the slice of array1 which is elements 1 through A
So both slices are 1-dimensional arrays
Slice may not be the correct term in Fortran