how to get one dimensional vector from an array in vba - arrays

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)

Related

Aggregating part of a 2d array in a column in said array

I have a 2d array, with flexible dimensions:
arr_emissions(1 to n, 0 to m)
Where n is 22 or larger, and m is 6 or larger.
In the smallest case column m = 6 should contain the sum of columns m = 2 - 5.
I could ofcourse simply add them, but as the dimensions of the array are flexible I would like to implement a more robust method, that preferly doesn't loop over the entire array.
I was hoping to implement the native application.WorksheetFormula.Sum(). I saw an implementation in this answer, but that only works for complete rows or columns.
Example:
I have arr_emissions(0 to 111,1 to 6). It is populated in a loop from 1 to 111.
The data in the array is as follows:
(1,1) #3-4-2020# 'a date value
(1,2) 1,379777
(1,3) 0
(1,4) Empty
(1,5) Empty
Don't know if this helps, but this takes a source array v and then populates a new array w with the sum of columns 2-4 of the corresponding row of v.
Sub x()
Dim v, i As Long, w()
'just to populate source array
v = Range("A1").CurrentRegion.Value
ReDim w(1 To UBound(v, 1))
For i = 1 To UBound(w)
'each element of w is sum of columns 2-4 of corresponding row of v
w(i) = Application.Sum(Application.Index(v, i, Array(2, 3, 4)))
Next i
'write w to sheet
Range("G1").Resize(UBound(w)) = Application.Transpose(w)
End Sub
Thanks to the answer from SJR I found myself a working solution. This is all within a larger piece of code, but for this example I filled some variables with fixed numbers to match my example from my question.
Dim days as Integer
days = 111
Dim emissions_rows as Integer
emissions_cols = 6
ReDim arr_emissions(0 To days, 1 To emissions_cols) As Variant
Dim arr_sum As Variant
Dim sum_str As String
sum_str = "Transpose(row(2:" & emissions_rows - 1 & "))"
arr_sum = Application.Evaluate(sum_str) '= Array(2,3,4,5)
arr_emissions(emissions_index, emissions_cols) = Application.Sum(Application.Index(arr_emissions, emissions_index + 1, arr_sum))
The code writes a string to include the variables, so to take the second column untill the second to last column, which is then evaluated into an array.
That array is then used within the sum function, to only sum over those columns.
The result is then written to the last column of arr_emissions().
emissions_index is an index that is used to loop over the array.

Jagged Array to 2D Array

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? :)

Error 9 using ReDim Preserve

This function returns a error 9, why? I already read couple of similar questions here but nothing really explained me well.
I'm really trying to understand why ReDim Preserve doesnt work in this case because from "j+1" onwards no input is made(i already checked my cells), so isnt overwriting nothing.
Heres the code
Function DadosAnoIndenizações()
ReDim dados(1 To 10000, 1 To 2)
j = 0
For i = 5 To 10000
If (IsNumeric(Worksheets(2).Cells(i, 8).Value) And Not IsEmpty(Worksheets(2).Cells(i, 8).Value)) Then
Ano = CInt(Right(Worksheets(2).Cells(i, 8).Value, 4))
SD = Worksheets(2).Cells(i, 11).Value
j = j + 1
dados(j, 1) = Ano
dados(j, 2) = SD
End If
Next i
ReDim Preserve dados(1 To j, 1 To 2)
DadosAnoIndenizações = dados
End Function
Thanks for any help guys
You are trying to change the first dimension of the array. Redim preserve can only change the last dimension of the array, which is why you're getting the error. You can find this information listed MSDN's website: ReDim Statement (Visual Basic), specifically the "Resizing with Preserve" section:
Resizing with Preserve. If you use Preserve, you can resize only the
last dimension of the array. For every other dimension, you must
specify the bound of the existing array.
For example, if your array has only one dimension, you can resize that
dimension and still preserve all the contents of the array, because
you are changing the last and only dimension. However, if your array
has two or more dimensions, you can change the size of only the last
dimension if you use Preserve.
Typically the way around that is to have the first dimension be your 1 to 2 and the second dimension be your 1 to j and then do a Application.Transpose when writing the results to the worksheet.

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