Jagged Array to 2D Array - arrays

i had created a jagged array of non-contigeous columns from a range (excluding any blank or zero-filled columns). now i want to join the different columns in the jagged array and convert it to a 2-Dimensional array that we get if we pass a range to a variant. i am unable to pull the column names using INDEX or TRANSPOSE to populate XValues, Values and Series.Name of a 100%StackedBarChart, hence the need.
here are the screenshots:
JAGGED ARRAY:
RANGE ARRAY:
as you can see in the jagged array, each column cells are shown outermost and row cells 1 to 5 are shown innermost, whereas in range 2d-array, it is viceversa. the columns and rows are of same size viz., 5 rows and 2 columns.
how do i convert back the jagged array to a normal range type rectangular 2D-array? Can anyone help me quickly?
Thanks.

On Florent's idea, i actually wrote my own Jagged2Rectconverter:
Dim tarr
ReDim tarr(1 To UBound(TempArr(1), 1), 1 To UBound(TempArr, 1))
For c = LBound(TempArr, 1) To UBound(TempArr, 1)
For r = LBound(TempArr(c), 1) To UBound(TempArr(c), 1)
tarr(r, c) = TempArr(c)(r, 1)
Next r
Next c
now tarr() gives me the same Rect array:
any quicker way of doing this without looping? :)

Related

Excel VBA Should I use Arrays or a Queue or Other? w/ Criteria passed as parameters

I have a data set with 2500 rows and 65 columns. I have a specific set of criteria than involves Greater/Less than > / < ,AND, OR, and Like Operators that needs to be evaluated on EACH row.
For example:
If Column 2 equals 1007001500 OR 1007000510 AND Column 3 > 25 AND < 25 AND Column 4 equals "asset" AND Column 5 equals "S" Then I need to assign a unique value for this row or in other words I need to classify this row into the 1 of 10 categories I have for this 2500 R x 65 C data set (which is an imported excel file).
I am fairly familiar with 1D and 2D arrays and I have gotten to the point of importing all the Logic into either 1D or 2D array. I am at this point deciding whether to evaluate the logic in one long 1D Array String across 1 Row and 1 Column or a larger 2D array with each categories' logic segregated into a separate row within the 2D array.
But I have also arrived at the question, is there a better data structure approach? I have briefly research Excel VBA Queues and have turned here for more expertise.
My data set will always have the same Columns labels I can used to evaluate upon. However my logic criteria is always subject to change by the user of the macro. So I am looking for a way to basically pass all my criteria as parameters to a data structure.
An array/matrix is a good way to handle data in VBA. Here is the way that I store such data:
LRL = Cells(Rows.Count, 1).End(xlUp).Row 'COunts the rows
LCL = Cells(2, Columns.Count).End(xlToLeft).Column 'Counts the columns
ReDim Level_Array_Unsort(LRL, LCL) 'Dimensionalizes the matrix
'This stores the data
For i = 1 To LRL
For j = 1 To LCL
Level_Array_Unsort(i, j) = Cells(i, j)
Next j
Next

how to get one dimensional vector from an array in vba

Does anyone know how to get a real vector from one column of array in VBA?
I've done the following steps:
'' read one column from 2D array
Dim ixy()
ixy = Application.Index(ts.Vertices, , 1)
And everything was looking all right until I wanted to ReDim the vector and add one more value to the end:
ReDim Preserve ixy(LBound(ixy) To UBound(ixy) + 1, 1 To 1)
ixy(UBound(ixy)) = ts.Vertices(1, 1)
This simply doesn't work because I cant ReDim non-last dimension of array. So how to obtain a vector by reading a column from an array? In Locals window the variable ixy looks + : ixy : : Variant(1 to 32, 1 to 1) so it's not 1d array.
I know how to obey this with loops but just want to find clear solution with minimum code. Any suggestions?
From the INDEX function Remarks section:
If you set Row_num or Column_num to 0 (zero), INDEX returns the array of values for the entire column or row, respectively.
ixy = Application.Index(ts.Vertices, 0, 1)
or
ixy = Application.Transpose(ts.Vertices)

Filling a 3D array with 2D arrays in VBA

I have a set of data where each item has a 2D array of information corresponding to it. I'd like to create a 3D array where the first dimension is the item name and the second and third dimensions are taken up by the info corresponding to the item.
I can read the data for each item into a 2D array, but I can't figure out how to get the 2D array read into the 3D array.
I know the sizes of all the dimensions so I can create an array of fixed size before I begin the reading and writing process.
I'd like to do this by looping only through the names of the items and not looping through every cell of every 2D array.
It is easy to get the 2D arrays read in to an ArrayList but I want to be able to name the items and be able to read these back in to excel and it seems difficult to do with an ArrayList.
The question is: how do I read a 2D selection from excel into a 3D fixed sized array in VBA?
Here is an example of each approach: array of arrays or Dictionary of arrays. The Dictionary approach is considerably easier than the array of arrays if what you want is keyed lookup of values. There might be merits to the array of arrays in other cases.
This is dummy code with no real purpose but to show a couple things: grabbing a single value and an array of values. I am building a 2D array of values by grabbing some Range data which is easy and 2D. From there I build up the arrays of these values and then put them into the relevant data structure. Then I poke at the data structure to get some values out of it.
Array of Arrays approach is shown first (and outputs on the left of the picture).
Sub ArraysOfArrays()
Dim arrA() As Variant
Dim arrB() As Variant
'wire up a 2-D array
arrA = Range("B2:D4").Value
arrB = Range("F2:H4").Value
Dim arrCombo() As Variant
ReDim arrCombo(2, 1) As Variant
'name and give data
arrCombo(0, 0) = "arrA"
arrCombo(1, 0) = arrA
'add more elements
ReDim Preserve arrCombo(2, 2)
arrCombo(0, 1) = "arrB"
arrCombo(1, 1) = arrB
'output a single result
'cell(2,2) of arrA
Range("B6") = arrCombo(1, 0)(2, 2)
Dim str_search As String
str_search = "arrB"
'iterate through and output arrB to cells
Dim i As Integer
For i = LBound(arrCombo, 1) To UBound(arrCombo, 1)
If arrCombo(0, i) = str_search Then
Range("B8").Resize(3, 3).Value = arrCombo(1, i)
End If
Next i
End Sub
Couple key points here:
You can only expand the array using ReDim. ReDim is very particular that you only change the last dimension of the array when used with Preserve. Since I need one of them to track the number of entries, I do that in the second index which is... unnatural. If you know the size in advance, this painful step is skipped.
My final array is a 2xN array where the 2 contains a name and a YxZ array of data.
In order to find a given array in the mix, you have to iterate through them all.
Dictionary of Arrays is far less code and more elegant. Be sure to add the reference Tools->References in the VBA editor to Microsoft Scripting Runtime.
Sub DictionaryOfArrays()
Dim dict As New Scripting.Dictionary
'wire up a 2-D array
arrA = Range("B2:D4").Value
arrB = Range("F2:H4").Value
dict.Add "arrA", arrA
dict.Add "arrB", arrB
'get a single value
Range("F6") = dict("arrB")(2, 2)
'get a array of values
Range("F8").Resize(3, 3) = dict("arrA")
End Sub
Picture of input data and results
Data to copy if you want it (paste in B1)
a b
1 2 3 10 11 12
4 5 6 13 14 15
7 8 9 16 17 18

How to reference an array and write to another array with more than one column per iteration

I am curious if I can copy multiple columns to a new array from an existing array in one iteration of a loop. Suppose we have the following general example:
Array1 contains 10,000 elements in column1, 10,000 elements in column2, and 10,000 elements in column 3, etc.
Let's say that I want a new array generated off that information, only I want only columns 1 and 2 populated. Can I do this by looping only once with a correctly dimensioned target array? For instance:
'Assume TargetArray has already been ReDimmed to the size of Array1 in the code prior
For i=0 to UBound(Array1)
TargetArray(x,1)= Array1(x,1)
TargetArray(x,2)=Array1(x,2)
Next
So can this be done in one step, or do I have to make a loop for each dimension I want to add to the array. Is there any speed savings by doing two operations per loop as stated above (assuming it works).
Thanks for all of your help!
Have you tried just using Range objects? I just made 100 values in columns A and B, and copy them to F and G. Or are you trying to plug values from the first three columns into an equation to give you values for the new two columns?
Sub CopyRange()
Dim Array1 As Range
Dim Array2 As Range
Set Array1 = Range("A1:B100")
Set Array2 = Range("F1:G100")
Array2.Value = Array1.Value
End Sub
Your example should work as what RubberDuck commented.
It is similar in below example which works at my end.
I can't fit it to comments so I have no choice to post it as answer.
Dim TargetArray ' declared as Variant type, not array of variants
ReDim TargetArray(0 To Ubound(Array1, 0), 0 To 1) ' for 2 columns
For i = 0 To Ubound(Array1, 1)
TargetArray(i, 0) = Array1(i, 0)
TargetArray(i, 1) = Array1(i, 1)
Next
Is this close to what you have? If so, then that should work.

Excel VBA: Replace first row by an array

I have a first row with 100 cells and I created an Array of Strings, which represent the new row content.
I would like to replace the content of all the first row with the content of my Array in VBA, how can I do that?
Say your array is called myArray, it's enough to do this:
For j = LBound(myArray) To UBound(myArray)
Sheets("your sheet").Cells(1,j+1).Value = myArray(j)
Next j
The functions LBound() and UBound() are respectively returning the first and the last index of your array.
Please note that when writing Cells(1,j+1) I'm assuming two important things:
1) Your start index starts with 0, so I want to start the insertion of the values from the column 1 (j+1 = 0+1 = 1).
2) You want to override the first row (because the row index is equal to 1).
You might want to customize this, for example creating independent indexes - when I say "independent", I mean "not depending on the lower and the upper bound of your array, nor being hard-coded like I did for the "row 1".
You can read and write between a Range and an Array in one line. It is more efficient than using a loop.
Note: The array must be 2 Dimensional to write to a range.
Public Sub ReadToArray()
' Create dynamic array
Dim StudentMarks() As Variant
' Read values into array from 100 cells in row 1
StudentMarks = Sheets("Sheet1").Range("A1:CV1").Value
' Do something with array
' Write the values back to sheet
Sheets("Sheet1").Range("A1:CV1").Value = StudentMarks
End Sub

Resources