This question already has answers here:
How to initialize a multidimensional array variable in vba for excel
(5 answers)
Closed 1 year ago.
in python it is possible to declare a list in a list for example like this
l=[[1,0,0],[0,1,0],[0,0,1]]
how do i do the same but in VBA excel
Declaring an array in VBA is different from initializing its contents (unlike python).
You declare a variable to be a 2D array of size N, M with
Dim a(1 to N, 1 to M) as Variant
but this creates a fixed sized array and not a dynamic array. It is better to declare an array as follows
Dim a() as Variant
ReDim a(1 to N, 1 to M)
and to fill the array with values you need a double loop, or assigning elements manually
a(1,1) = ...
a(1,2) = ...
Notice that I declared arrays that are 1-based, instead of 0-based (first element is a(1,1), and not a(0,0)) because when reading in a table from an Excel worksheet with
a = Range("A2").Resize(N,M).Value
Debug.Print a(3,1)
it creates such an array.
Note that it is possible to declare a dynamic array and fill it in with jagged form (array of arrays) using the following code
Dim a() as Variant
a = Array( Array(1,2,3), Array(4,5,6), Array(7,8,9) )
which you have access to in VBA with the following form
Debug.Print a(2)(0)
' 7
Notice that they arrays produced by the Array() command are 0-based with indexes varying between 0..N-1. Additionally, since the above is jagged array (array of arrays), the elements are accessed using sequential indexers as in a(i)(j) instead of a(i,j)
So it really depends on how you want to use the 2D array to decide how to best declare it.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am having difficulties in trying to understand the following code. I found it here in the following link: vba: get unique values from array
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
'Set d = New Scripting.Dictionary
Dim i As Long
For i = LBound(myArray) To UBound(myArray)
d(myArray(i)) = 1
Next i
Dim v As Variant
For Each v In d.Keys()
'd.Keys() is a Variant array of the unique values in myArray.
'v will iterate through each of them.
Next v
EDIT: I quite understand the whole code but I could not understand the last section being
Dim v As Variant
For Each v In d.Keys()
'd.Keys() is a Variant array of the unique values in myArray.
'v will iterate through each of them.
Next v
and I cannot understand this line
d(myArray(i)) = 1
EDIT: I am looking for a code that executes the same objective but I would rather want to understand fully what I am applying than just copy and paste something that I do not understand.
More specifically, there are several elements in the macro that I am constructing and this one is among the ones I am looking for.
As first objective I need to find the duplicates in my dataset
After finding the duplicates I need to count how duplicates there are if there are 4 duplicates row my item is complete,
Then, if there are more than 4 duplicates, I need to transfer the duplicates to another sheet and store them there
On the other hand, if there are less than 4 duplicates, I would need to find such items and try to match these items with an inventory to try to find out the remaining elements in order to stack a full set of 4 elements.
This macro will serve me to fulfill point 4. Once I identify the items that have less than 4, I need to find such items and try to match them with the ones that I have in another sheet. I need to do so with the code above as I would rather use an array in a macro than functions in excel itself in order to avoid confusion to the user with phantom figures.
Section by Section:
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
'Set d = New Scripting.Dictionary
This creates the dictionary object
Dim i As Long
For i = LBound(myArray) To UBound(myArray)
d(myArray(i)) = 1
Next i
With dictionary objects, there are two ways to add a new item:
d.Add Key, Value
This method causes an error if the dictionary already has that key
d(Key) = Value
This method is technically a reassignment for the value of the specified key. If the key doesn't exist, it gets added implicitly. If the key already exists, the value just gets updated.
So what the code is doing, is it cycles through each value in the array and:
Reassigns the current index as the dictionary value with the current dictionary key (the array's value)
If the key doesn't already exist, create it.
This results in a dictionary with one key for every unique value. Any duplicate values would have just been reassigned the value for the existing key, instead of creating a new key.
Dim v As Variant
For Each v In d.Keys()
'd.Keys() is a Variant array of the unique values in myArray.
'v will iterate through each of them.
Next v
Elaboration: d.Keys returns all of the keys in the dictionary in the form of an array. Since the keys are the unique values from myArray, d.Keys is an array on the unique values from myArray.
I have a short question about ReDim-ming dynamic arrays - more precisely in which cases is it required?
I understand I need to ReDim Preserve array(x) As Variant when adding entries into the array. Adjusting/changing existing information in an array works well like: array(x) = "Added text " & array(x)
But are there any other cases when I need to worry about ReDim or maybe even other special requirements when handling dynamic arrays?
I'm writing a code which will include large dynamic arrays that get data added from many different sources before For-looping through it to write the date into a list on another sheet. I can't let an error pop up in the future because I missed something.
ReDimis used to change the size of an array. You can ReDim an array not initialized like this:
Dim arr() As Variant
x = 200
ReDim arr(1 to x)
You can also do this on initialized arrays:
Dim arr(1 to 2) As Variant
ReDim arr(1 to 5) <-- will delete previous stored values
ReDim Preserve arr(1 to 5) <-- will preserve previous stored values
Note that using the Preserve will only change the last dimension on multidimension arrays, so Dim arr(1 to 5, 1 to 2) if you want to keep your data using ReDim Preserve you can only change the second dimension from 1 to 2 to 1 to x.
Like Tom said, changing the size of your array in every loop will impact on the performance so you should first calculate the maximum size of your array and then dimension it, or dimension the size way over what you need and lastly redim it to your needs when you end.
It is easy creating an array in MS Excel VBA, be it 1-dimensional or multi-dimensional, and set it to type Integer or String. Is it possible to do complex arrays however along these lines (this is not true code but represents what I mean):
1 to 100 rows
1 to 100 columns
f_Depth: Float
1 to 4 points
l_X: Long
l_Y: Long
The Excel integer-only (or float-only or whatever you choose) makes it very difficult to work with the code.
By "complex array" do you mean array of mixed type? If so, you can use Collection which accepts objects of any type:
Dim Data As New Collection
Data.Add (1)
Data.Add ("Hello world")
Data.Add (3.14)
i want to be able to initialize an array to store the values of a conversion. but i don't know how many values there will be until compile time so i want the range to go from
pseudo-code:
1 to <some expression>
namely i want it as
Dim Colvals(1 To Len(EndColumn)) As Integer
but when the code is sent to compile it throws
Constant Expression required
any idea how to do it? i really don't want to limit the versatility of the program by forcing the specification of the range.
You want to redimension your array using a Redim statement:
Dim Colvals() As Integer
ReDim Colvals(1 To Len(EndColumn))
It seems strange that it requires a Constant for the Dim and not the Redim, but it's true.
I was just doing some yicky code and I thought, instead of using three dynamic arrays, as such:
dim x() as string, y() as string, z() as string
It will be nicer to have a 3 dimensional dynamic array. But; the help and my fumbling experiments has not revealed the method of defining them.
This does not work:
dim x()() or dim(,2) or dim(,)
Any ideas anyone?
A dynamic array is declared the same way regardless of the number of dimensions (arrays in LotusScript can have up to 8 dimensions). According to your example I think it is a two dimensional array you want, where the first dimension is limited to three entries.
If you first declare the array as:
Dim x() As String
You can then specify bounds according to the following example:
Redim x( 0 To 2, 0 To 9 ) ' A two dimensional array
And if you need to enlarge the array later (and keep all the values) you can do it like this:
Redim Preserve x( 0 To 2, 0 To 99 )
Please keep in mind that only the bounds of last dimension can be changed once the number of dimensions of the array has been set.
You could use lists instead of arrays.
Dim x list as String
That is fully dynamic and takes a string as index. List can't contain lists, but lists can contain objects, so you might want to do
Public Class ListContainer
Public level2 List as String
End Class
This way you never need to REDIM preserve. A forall loops you savely through a list