I have an "input array" (wich listcount is not fixed). I need to create a new array for each item inside that "input array", and add each item as the first item of its own array.
I can't define the array of arrays' size, because the amount of sub-arrays is not fixed.
How should it be defined?
Based on the description you've given, follow my suggestion.
Please, give us your feedback.
Private Function AmazingFunction(inputArray As Variant)
Dim size As Long
Dim i As Long
Dim tmp As Variant
Dim newArray() As Variant
size = UBound(inputArray) ' Array size
ReDim newArray(size) ' Resizes another array to the same size
For i = 0 To size ' For each value
tmp = CreateArray(length:=0) ' Allows you to dynamically create arrays
' In this case, an array of only one element is created.
tmp(0) = inputArray(i) ' Sets the value of the first array element
newArray(i) = tmp
Next
AmazingFunction = newArray
End Function
Auxiliary function to create arrays dynamically:
Private Function CreateArray(length As Long)
Dim arr() As Variant
ReDim arr(length)
CreateArray = arr
End Function
Here is an example of how to use the function:
Private Sub UseTest()
Dim outArray As Variant
Dim intArray As Variant
Dim element As Variant
Dim inputArray(2) As Variant
inputArray(0) = "a"
inputArray(1) = "b"
inputArray(2) = "c"
outArray = AmazingFunction(inputArray)
For Each intArray In outArray
For Each element In intArray
Debug.Print element
Next
Next
End Sub
Related
For any 2-column array A, set every 2nd-column element to be a 1-dimensional array with a size indicated by the first column.
For example: the row [3,""] would become [3,("","","")]
Something like this?
Option Base 1
Sub NestArrays()
Dim OuterArray(3,2) as variant 'create OuterArray with hypothetical numbers 3,5,7
OuterArray(1,1) = 3
OuterArray(2,1) = 5
OuterArray(3,1) = 7
for i = 1 to Ubound(OuterArray) ' for every row in OuterArray
size = OuterArray(i,1) ' set variable "size" equal to the element in 1st column
OuterArray(i,2)=Array(1 to size) ' <--- this doesn't work, set 2nd-col element = array(size)
next i
''''test
OuterArray(1,2)(1) = "aardvark"
debug.print OuterArray(1,2)(1)
End Sub
Use an intermediate array and ReDim as size is dynamic. You possibly want a safeguard on size as well as it needs to be >0 (just a thought)
Option Explicit
Option Base 1
Public Sub NestArrays()
Dim outerArray(3, 2) As Variant, i As Long, size As Long 'create OuterArray with hypothetical numbers 3,5,7
outerArray(1, 1) = 3
outerArray(2, 1) = 5
outerArray(3, 1) = 7
Dim arr()
For i = 1 To UBound(outerArray) ' for every row in OuterArray
size = outerArray(i, 1) ' set variable "size" equal to the element in 1st column
ReDim arr(1 To size)
outerArray(i, 2) = arr
Next i
''''test
outerArray(1, 2)(1) = "aardvark"
Debug.Print outerArray(1, 2)(1)
End Sub
The host array is declared to hold items of type variant. As you can assign an array to a Variant you can proceed as follows
Dim myIndex as long
For Lbound(OuterArray,1) to Ubound(OuterArray,1)
OuterArray(myIndex,2) = Split(String$(OuterArray(myIndex,1),","),",")
Next
If you need the new array to be also an array of variants you will need to create a function that generates the appropriate size of array.
Public Function VarArray(ByVal ipCount As Long) As Variant
Dim mySd As Object
Set mySd = CreateObject("Scripting.DIctionary")
Dim myIndex As Long
For myIndex = 1 To ipCount
mySd.Add myIndex, 0
Next
VarArray = mySd.Items
End Function
So that
OuterArray(myIndex,2) = Split(String$(OuterArray(myIndex,1),","),",")
becomes
OuterArray(myIndex,2) =VarArray(OuterArray(myIndex,1))
I can't seem to find this problem addressed anywhere.
I need to declare a bunch of dynamic arrays as follow:
Dim list1 () as variant
Dim list2() as variant
Dim list3() as variant
...
Dim listN() as Variant
Each list is a one-dimensional dynamic array. However, I wouldn't know what "N" will be during the program. I want to make these "N" lists dynamic as well. I have tried two-dimensional dynamic arrays. But the "redim" statement requires both dimensions to be declared at the same time. In particular, I do this:
Dim BigList() as variant
...
Redim BigList(listNum, listLength)
To access/pass into a sub "list1", "list2" , "list3"..., calling "BigList(1)", "BigList(2)" gives me error. In particular, somewhere in my code, there is this portion:
sub ProcessList(byref listToProcess() as variant)
...
end sub
sub main()
...
call ProcessList(list1)
call ProcessList(list2)
...
call ProcessList(listN)
end sub
Now I can do a loop:
for i = 1 to N
Call ProcessList(list"i")
next i
This requires list"i" to be a one-dimensional dynamic array. So, after a redim BigList(listNum,listLength) and I do this:
for i = 1 to N
Call ProcessList(BigList(i)) 'i refers to listNum
next i
This gives me error "Incompatible type".
Here is one example of creating a Dictionary which is keyed to integer values (i.e., the N) and each value is initially an empty array.
You can then use something like the ExtendList function to resize those empty arrays as needed.
Sub foo()
Dim BigList As Object
Dim N As Long
Dim v as Variant
'Create an empty dictionary object
Set BigList = CreateObject("Scripting.Dictionary")
'Add N empty array to the dictionary:
N = 3
For i = 1 To N
BigList(i) = Array()
Next
'Resize one of the items in your BigList
BigList(2) = ExtendList(BigList(2), 1, 10)
v = BigList(2) 'Here you can examine v in the Locals window and see it is an array, of dimensions 1 x 10
End Sub
Function ExtendList(lst, a As Long, b As Long)
ReDim lst(a, b)
ExtendList = lst
End Function
On review of your edited question, I think you merely misunderstood how the ReDim statement works:
Redim BigList(listNum, listLength)
This re-dimensions the BigList based on the parameters listNum and listLength. It does not (as it seems you may have expected) create a list of arrays within BigList.
I think this might also work (untested, and remember arrays are zero-index):
ReDim Preserve BigList(listNum)
BigList(listNum) = Array()
ReDim BigList(listNum)(listSize)
I am trying to use excel 2010 VBA to populate an array containing three arrays. The first is a string type array and the other two are integer type arrays. The relevant portion of the macro is below.
Option Explicit
Option Base 1
Private Type T_small
myStr() As String
y() As Integer
z() As Integer
End Type
Sub ColorByPoint()
On Error GoTo ErrHandler
Dim I As Integer, SCCount As Integer, PCCount As Integer, CLCount As Integer
Dim N As Integer, M As Integer, K As Integer, P As Integer
Dim x() As String, y() As Integer, z() As Integer
Dim pvtItM As Variant
Dim xName As String, str As String
Dim xlRowField As Range
Dim PC As ChartObjects
Dim WS As Sheet3
Dim SC As SeriesCollection
Dim MyObj As Object
Dim PvTbl As Object
Dim CelVal As Integer
Dim rng As Variant, lbl As Variant, vlu As Variant
Dim ItemField1 As PivotItem, ItemField2 As PivotItem
Dim ValueField As PivotField
Dim dField As PivotCell
Dim oPi As PivotItem
Dim acolRng As Range
Dim arowRng As Range
Dim myStr() As String
Dim iData() As T_small
Dim xSSN() As String
Set WS = Application.ActiveWorkbook.ActiveSheet
Set MyObj = Worksheets("Pivot1").ChartObjects("MyChart").Chart
Set PvTbl = Worksheets("Pivot1").PivotTables("PivotTable1")
Set rng = PvTbl.PivotFields("SSN").PivotItems
Set lbl = PvTbl.DataFields
M = 1
SCCount = MyObj.SeriesCollection.Count 'Series count
PCCount = PvTbl.TableRange1.Rows.Count 'Rows Count
CLCount = PvTbl.TableRange1.Columns.Count 'Columns Count
Set acolRng = PvTbl.ColumnRange
Set arowRng = PvTbl.RowRange
Worksheets("Pivot1").Activate
P = PCCount
ReDim Preserve myStr(P)
ReDim Preserve y(P)
ReDim Preserve z(P)
ReDim Preserve iData(P)
For N = 2 To PCCount
ReDim Preserve iData((iData(2).myStr(2)), (iData(N).y(N)),(iData(N).z(N)))
Next N
For I = 2 To PvTbl.TableRange1.Rows.Count Step 1
For K = 2 To PvTbl.TableRange1.Columns.Count Step 1
M = K
N = K
iData(I).myStr(I) = PvTbl.Cells("myStr" & I, "K").Value
iData(I).y(I) = PvTbl.Cells("I", "M").Value
iData(I).z(I) = PvTbl.Cells("I", "N").Value
Next K
Next I
The problem is that the line
ReDim Preserve iData((iData(2).myStr(2)), (iData(N).y(N)), (iData(N).z(N)))
continues to give me a "Run Time error 9 Subscript out of range" error. I've tried everything I can think of to get past this including using "N"'s instead of the "2" indexes throughout, adding and removing parentheses, etc.
What causes the runtime error?
The problem is you are accessing the array indexes of your T_small properties. You never define (or change) the bounds of iData(x).myStr; rather you only define the bounds of myStr, which is not part of your iData array.
In other words, the of bounds error comes from trying to access iData(x).myStr(x) because iData(x).myStr has no bounds defined.
This should work:
' Now that the iData bounds have been defined, update the property bounds.
ReDim Preserve iData(N).myStr(myStr(N))
ReDim Preserve iData(N).y(y(N))
ReDim Preserve iData(N).z(z(N))
Note that I am having a bit of difficulty following exactly what your code is trying to accomplish, so the above only addresses the specific error you are getting.
I need to know how can I add an item to an existing array using a user input.
I tried something like this:
Dim MyArray(100) as String
UBound(MyArray) = Inputbox("What's the name of your new array item?")
Ubound(myArray) returns a Long datatype, it literally return the length/size of the array.
If you want to read or assign a value then you must fully qualify the array ie.
MyArray(ubound(myArray)) = "new Value" or MyArray(100) = "new Value"
Sub Main()
Dim MyArray(100) As String
MyArray(UBound(MyArray)) = InputBox("What's the name of your new array item?")
MsgBox MyArray(UBound(MyArray))
End Sub
You could use a dynamic array instead:
Dim MyArray() As String
' Then to add a new element:
Redim Preserve MyArray(1 to SafeUBound(MyArray) + 1)
MyArray(SafeUBound(MyArray)) = InputBox("Who's yer daddy?")
Function SafeUBound(vArray As Variant) As Long
Dim x As Long
On Error Resume Next
x = UBound(vArray)
If Err.Number = 0 Then
SafeUBound = x
Else
SafeUBound = 0
End If
End Function
The call to SafeUbound is necessary because calling UBound or LBound on an uninitialized array will throw an error.
I am trying to find this but I can't! Is it possible to move/copy and VBA Array to a Range Variable, I am not saying a Range cells, it's a Range that you declare (ex: DIM ran as Range)
I want something like this:
Public Function test()
Dim ran As Range
Dim myArray(4) As Integer
myArray(1) = 1
myArray(2) = 2
myArray(3) = 3
myArray(4) = 4
'If I do this, it works!
Range("A1:A4") = myArray
'But I want this and it does not work!
ran = myArray
End Function
Thanks!
Even though the Range is declared in code, it's still a Range, not an array. If myArray is actually a Range object (in which case you should re-think your naming conventions) you should be able to do what your example showed.
However if your variable myArray is some other type of object (like and array) you can't just set it like that, you would have to write a method that converts myArray to a range.
EDIT:
I'm guessing that the reason that Range("A1:A4") = myArray works is because the assignment operator has been overloaded to support it as short-hand for Range("A1:A4").Value = myArray.
A Range however is not just an array, it's a data structure specific to Ranges of a workbook
When you declare Dim ran As Range you haven't actually initialized your Range object yet. I'm guessing that if you did the following it would work:
Dim ran As Range("A1:A4")
Dim myArray(4) As Integer
myArray(1) = 1
myArray(2) = 2
myArray(3) = 3
myArray(4) = 4
ran = myArray
If you set a variant to a worksheet range you get a 2 dimensional array. Try this
Sub MoveArray()
Dim myArray
myArray = Range("A1:B3").Value
Range("A6:B8").Value = myArray
End Sub
Or this
Sub MoveArray2()
Dim myArray
Dim myArray2
Dim myRange
Dim i As Integer
Dim j As Integer
myArray = Range("A1:B3").Value
Set myRange = Range("A6:B8")
For i = 1 To myRange.Rows.Count
For j = 1 To myRange.Columns.Count
myRange.Cells(i, j) = myArray(i, j)
Next j
Next i
myArray2 = myRange
End Sub
In either case the variant becomes an array rather than a range object and the loops set the values of the range from the array.
Edit
As you can see from the comments in the questions/answers in this thread a range is not an array, it is a complex object that has many properties and methods. One of the properties (I think the default property) is value. This property is in fact a 2 dimensional array (or at least behaves like one) of the values of the cells in the range. As such if myArray is also a 2 dimsensional aray the code myRange = myArray will execute. What will happen is the value of the cells that the range refers to will be set to the values in the array. The range refers to these cells, but it is the values in the cells that change rather than the range object.
As such if if you transfer a range to a diferent set of cells the new set of cells retains it's values.
On a practical side if you want to change the values of the cells that a range referes to you can do it as shown below:
Sub Test1()
Dim myArray(1 To 4, 1 To 1)
Dim myRange As Range
myArray(1, 1) = 1
myArray(2, 1) = 2
myArray(3, 1) = 3
myArray(4, 1) = 4
Set myRange = Range("A1:A4")
myRange = myArray
End Sub