redim nested array - arrays

i have an array path... this array contains a list of nested array paths. it could look something like this:
path( 0 1 2 3 4 5 6 7 8 )
"1" | 1, 1, 1, 1, 1, 1, 1, 1, 1 |
"2" | 4, 3, 1, 4, 2, 3, 4, 3, 2 |
"3" | 1, 1, , 2, 1, 2, 3, 3, 2 |
"Val" A, B, C, D, E, F, G, H, I
now i have a small loop to get the maximum of the second row.
x = 1
For c = 0 To UBound(path)
If IsArray(path(c)) Then
If CInt(path(c)(x)) <= maxDimension1 Then
maxDimension1 = CInt(path(c)(x))
End If
End If
Next
redim preserve pathValues(maxDimension1 - 1)
i must now find the maximum number of elements for the elements in row "2" and redim the array-Element in pathValues to this.
i tried:
For Dimension2 = 1 To maxDimension1
For c = 0 To UBound(Path)
If IsArray(Path(c)) Then
If CInt(Path(c)(x)) = Dimension2 Then
If CInt(Path(c)(2)) >= maxDimension2 Then
maxDimension2 = CInt(Path(c)(2))
End If
End If
End If
redim PathValues(c)(maxDimension2) //Syntax Error
next
next
is there a way to avoid a workaround with multidimensional array?
for explanation: the pathValues would look like this in the end:
PathValues() = (C,(E, I),(B, F, H),(A, D, G))

I fixed it by recursively calling a function that uses x as "depth" and the full path to create one single array containing empty elements for the values that get written in later.
one just needs to add a statement sorting out the upper bounds you do not want because they belong to other arrays. for all else it works fine
Function iterate_Path(path As Variant, x As Integer, value_x As Variant) As Variant
Dim insideArray, returnPath
returnPath = Array()
For c = 0 To UBound(path)
If IsArray(path(c)) Then
If CInt(path(c)(x)) = value_x Then
If x <> UBound(path(c)) Then
If CInt(path(c)(x)) > UBound(returnPath) + 1 Then
ReDim Preserve returnPath(CInt(path(c)(x)) - 1)
End If
returnPath(path(c)(x) - 1) = iterate_Path(path, x + 1, path(c)(x))
ElseIf CInt(path(c)(x)) > UBound(returnPath) + 1 Then
ReDim Preserve returnPath(CInt(path(c)(x)) - 1)
End If
ElseIf CInt(path(c)(x)) > UBound(returnPath) + 1 Then
ReDim Preserve returnPath(CInt(path(c)(x)) - 1)
If x + 1 = UBound(path(c)) Then
returnPath(CInt(path(c)(x)) - 1) = iterate_Path(path, x + 1, path(c)(x))
End If
ElseIf x + 1 = UBound(path(c)) Then
If CInt(path(c)(x)) > UBound(returnPath) + 1 Then
ReDim Preserve returnPath(CInt(path(c)(x)) - 1)
End If
returnPath(CInt(path(c)(x)) - 1) = iterate_Path(path, x + 1, path(c)(x))
End If
Else
returnPath(CInt(path(c)(x)) - 1) = Empty
End If
Next
iterate_Path = returnPath
End Function

Related

Loop in range of cells with fixed last row

I need to loop in a range (in my case column A) to get following results:
A B
1 = 2 - 1
2 = 3 - 1
3 = 3 - 2
4 = 4 - 1
5 = 4 - 2
= 4 - 3
= 5 - 1
= 5 - 2
= 5 - 3
= 5 - 4
I want number 5 to be deducted by 4, 3, 2 ,1 and then number 4 by 3, 2, 1 and so on.
I was somehow able to achieve this with collection but since dataset is rather big script is running 30+ minutes.
At this point I'm trying to figure out arrays but I don't know how to get desired result. My main concern is whether I can loop from bottom to top (From number 5 to 1, not 1 to 5) and how to fixate last row (fix number 5, conduct deductions and then fix number 4, do math magic and loop to 3 and so on).
My current code is:
Dim Arr As Variant
Dim lastc, lastr As Long
lastc = FindColNumber
lastr = ws.Cells(ws.Rows.count, lastc).End(xlUp).Row
Arr = ws.Range(ws.Cells(2, last), ws.Cells(lastr, lastc))
For i = LBound(Arr, 1) To UBound(Arr, 1) - 1
If (Arr(i, 1) > 0) And (Arr(i + 1, 1) > Arr(i, 1)) Then
Arr(i, 1) = Arr(i, 1) - Arr(i + 1, 1)
Code does deduction as following: 5-4, 4-3, 3-2, 2-1 and that's not what I need.
Any tips?
Thank you.
As stated in the comments, you will need two loops and another output array:
Sub lkjlkjkdl()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim Arr As Variant
Dim lastc As Long, lastr As Long
lastc = 1 'FindColNumber
lastr = ws.Cells(ws.Rows.Count, lastc).End(xlUp).Row
Arr = ws.Range(ws.Cells(2, lastc), ws.Cells(lastr, lastc))
Dim cnt As Long
cnt = ((UBound(Arr, 1) - 1) * UBound(Arr, 1)) / 2
Dim k As Long
k = 1
Dim outarr As Variant
ReDim outarr(1 To cnt, 1 To 1)
For i = LBound(Arr, 1) + 1 To UBound(Arr, 1)
Dim j As Long
For j = LBound(Arr, 1) To i - 1
outarr(k, 1) = Arr(i, 1) - Arr(j, 1)
k = k + 1
Next j
Next i
ws.Range("B2").Resize(cnt, 1).Value = outarr
End Sub

vba loop through array, store values to arrayi

I have some data, stored in arrays like
Dim arrA, arrB, arrC, arrAi, arrBi
Dim i as integer, x as integer
for i = 1 to 100
if cells(i,1).value = "criteria" then ' just add value to array when it meets some criteria
x = x + 1
arrA(x) = cells(i,1).value
arrB(x) = cells(i,2).value
arrC(x) = cells(i,3).value
end if
next i
redim preserve arrA(1 to x)
redim preserve arrB(1 to x)
redim preserve arrC(1 to x)
And the data looks like
arrA: 26.1 40.2 80.3 26.0 41.3 78.7 25.8 40.8 80.0
arrB: 10 11 10 66 67 64 32 32 33
arrC: 1 2 3 1 2 3 1 2 3
Since the values in arrA 26.1, 26.0, 25.8 (position 1, 4, 7) belong to group 1 (referencing to values in arrC at same position), I would like to store 26.1 26.0 25.8 to arrAi and 10 66 32 to arrBi for subsequent calculations.
How can I loop through the 3 arrays and store values to another array as described above?
Thanks in advance.
Try the next way, please:
Sub handleArraysFromArrays()
'your existing code...
'but you fistly must declare
Dim arrA(1 To 100), arrB(1 To 100), arrC(1 To 100)
'....
'your existing code
'...
Dim k As Long, kk As Long
ReDim arrAi(1 To UBound(arrA))
ReDim arrBi(1 To UBound(arrA))
For i = 1 To UBound(arrC)
If arrC(i, 1) = 1 Then k = k + 1: arrAi(k, 1) = arrA(i, 1)
If arrC(i, 1) = 2 Then kk = kk + 1: arrBi(kk, 1) = arrA(i, 1)
Next i
ReDim Preserve arrAi(1 To k): ReDim Preserve arrBi(1 To kk)
Debug.Print UBound(arrAi), UBound(arrBi)
End Sub

Using a sub to call an array within a function

I have a little problem with my sub. This sub is calling to different functions, by using the sub's data. The first function finds one is finding the amount of unique values and the second function finds these values. However, the first function works fine because its output is a scalar value. However, the second function's output is an array. I have tried to search for a solution, but so far I have not succeeded. I have a theory that the issue has something to do with the ByRef A() As Integer. I have written the codes below, both for the sub and the second function.
Sub Test()
Dim A() As Integer
Dim n As Integer
Dim BB As Integer
n = 10
ReDim A(n, 2) '5 unikke
A(1, 1) = 1
A(2, 1) = 7
A(3, 1) = 2
A(4, 1) = 6
A(5, 1) = 3
A(6, 1) = 5
A(7, 1) = 1
A(8, 1) = 1
A(9, 1) = 1
A(10, 1) = 4
A(1, 2) = 1
A(2, 2) = 7
A(3, 2) = 2
A(4, 2) = 6
A(5, 2) = 3
A(6, 2) = 5
A(7, 2) = 1
A(8, 2) = 1
A(9, 2) = 1
A(10, 2) = 4
BB = Unikke(A) 'Unikke is the second function that provides the amount of unique values
Dim FF() As Integer
ReDim FF(BB, 1)
FF = HvilkeUnikke(A) 'the second function, which has the output of an array a.k.a the problem
End Sub
This is the function:
Public Function HvilkeUnikke(ByRef A() As Integer) As Integer
Dim L() As Integer
Dim B As Integer
Dim i As Integer
Dim i2 As Integer
Dim A2() As String
Dim BB As Integer
Dim C() As Integer
BB = Unikke(A)
ReDim C(UBound(A), 2)
ReDim A2(BB, 1)
ReDim L(BB, 1)
For i = 1 To UBound(A)
C(i, 1) = A(i, 1)
C(i, 2) = A(i, 2)
Next
For i = 1 To UBound(C)
B = 0
For i2 = 1 To UBound(C)
If C(i, 1) = C(i2, 2) Then
B = B + 1
If B > 1 Then
C(i2, 2) = 0
End If
End If
Next i2
Next i
B = 0
For i2 = 1 To UBound(C)
If C(i2, 2) > 0 Then
B = B + 1
L(B, 1) = C(i2, 2)
End If
Next i2
HvilkeUnikke = L
End Function
The results are as expected, but they should be in a variable inside my sub.
(The solution)
Sub test()
Dim FF() As Integer
Dim i As Integer
Dim A() As Integer
Dim n As Integer
Dim BB As Integer
n = 10
ReDim A(n, 2) '7 unikke
A(1, 1) = 1
A(2, 1) = 7
A(3, 1) = 2
A(4, 1) = 6
A(5, 1) = 3
A(6, 1) = 5
A(7, 1) = 1
A(8, 1) = 1
A(9, 1) = 1
A(10, 1) = 4
A(1, 2) = 1
A(2, 2) = 7
A(3, 2) = 2
A(4, 2) = 6
A(5, 2) = 3
A(6, 2) = 5
A(7, 2) = 1
A(8, 2) = 1
A(9, 2) = 1
A(10, 2) = 4
BB = Unikke(A)
ReDim FF(BB)
FF = HvilkeUnikke(A)
'Testing on the worksheet
For i = 1 To BB
Cells(i, 1) = FF(i)
Next
End Sub
And the function
Public Function HvilkeUnikke(ByRef A() As Integer) As Integer()
Dim L() As Integer
Dim B As Integer
Dim i As Integer
Dim i2 As Integer
Dim A2() As String
Dim BB As Integer
Dim C() As Integer
BB = Unikke(A)
ReDim C(UBound(A), 2)
ReDim A2(BB, 1)
ReDim L(BB)
For i = 1 To UBound(A)
C(i, 1) = A(i, 1)
C(i, 2) = A(i, 2)
Next
For i = 1 To UBound(C)
B = 0
For i2 = 1 To UBound(C)
If C(i, 1) = C(i2, 2) Then
B = B + 1
If B > 1 Then
C(i2, 2) = 0
End If
End If
Next i2
Next i
B = 0
For i2 = 1 To UBound(C)
If C(i2, 2) > 0 Then
B = B + 1
L(B) = C(i2, 2)
End If
Next i2
HvilkeUnikke = L
End Function

How can I make a value in one array the value in another array (VBA)?

I want to create a piece of code that lets me assign a value from a array to another array, which are of different lengths. This is what I have so far.
A(1) = 0
A(2) = 0
A(3) = 6
A(4) = 5
A(5) = 7
n = 0
For i = 1 To 5
If A(i) <> 0 Then
n = n + 1
End If
Next i
ReDim B(1 To n) As Integer
For j = 1 To n
For i = 1 To 5
If A(i) <> 0 Then
B(j) = A(i)
End If
Next i
Next j
MsgBox B(2)
At the moment this returns 7 whereas it should return 5, all values in B are 7. How can I get this code to run?
The fact that you have nested loops should alarm you: this would be executed n * 5 times, which cannot be correct.
Change the second part so it only uses one loop, like this:
ReDim B(1 To n) As Integer
j = 1
For i = 1 To UBound(A)
If A(i) <> 0 Then
B(j) = A(i)
j = j + 1
End If
Next i
Note also that using UBound instead of 5 makes your code more generic. Note also that this loop is very similar to the loop that calculates n. The only difference is that you assign to B(j).
You could in fact combine it with the first loop, if you would re-dimension B twice, the second time with Preserve:
ReDim B(1 To UBound(A)) As Integer
n = 0
For i = 1 To UBound(A)
If A(i) <> 0 Then
n = n + 1
B(n) = A(i)
End If
Next i
' Shorten the array without losing data:
ReDim Preserve B(1 To n)
You are going to have to check B for the first empty array element and exit the loop so you do not continue to write.
Dim A() As Variant, B() As Variant
Dim i As Long, j As Long, n As Long
A = Array(0, 0, 6, 5, 7) '<~~ 0 to 4, not 1 to 5
n = 0
For i = LBound(A) To UBound(A)
If A(i) <> 0 Then
n = n + 1
End If
Next i
ReDim B(1 To n) '<~~ 1 to 3
For i = LBound(A) To UBound(A)
If A(i) <> 0 Then
For j = LBound(B) To UBound(B)
If IsEmpty(B(j)) Then
B(j) = A(i) '<~~ assigned a value; exit loop
Exit For
End If
Next j
End If
Next i
For j = LBound(B) To UBound(B)
Debug.Print B(j)
Next j
Given that arrays can be either zero-based or one-based, I prefer to use the LBound and UBound functions to define their scope.

Multiplying two dimensional arrays

how to multiply two dimensional a(5,3) and b (3,5)
so the arry c( , )= a(5,3) and b (3,5)
the first row of arry a * the columns of arry b then
the second row of arry a * the columns of arry b then
[EDIT] the code of your comment:
Dim arry1(5, 3) As Integer
Dim arry2(3, 5) As Integer
Dim i, j As Integer
For i = 1 To 5
For j = 1 To 3
arry1(i, j) = Int(9 * Rnd + 1)
Next i, j
For i = 1 To 3
For j = 1 To 5
arry2(i, j) = Int(9 * Rnd + 1)
Next i, j
Congrats! it works :)
Some comments:
when you use Dim a, b As Integer then b will be an Integer, but a will be a Variant. It is better to use Dim a As Integer, b As Integer so that both a and b will be Integers
why do you ReDim c(5, 5) As Integer ? You can use Dim c(5, 5) As Integer
Instead of printing to the form I would show the data in a textbox or label control
Dim a, b As Integer
Dim arry1(5, 3) As Integer
Dim arry2(3, 5) As Integer
ReDim c(5, 5) As Integer
Dim i, j, s As Integer
Print ""
Print Space(15); "the first arry"
Print ""
For i = 1 To 5
For j = 1 To 3
arry1(i, j) = Int(9 * Rnd + 1)
Print Space(3); arry1(i, j);
Next j
Print ""
Next i
Print ""
Print Space(15); " the second arry"
Print ""
For i = 1 To 3
For j = 1 To 5
arry2(i, j) = Int(9 * Rnd + 1)
Print Space(3); arry2(i, j);
Next j
Print ""
Next i
Print ""
Print Space(15); " the result"
Print ""
cmd1.Visible = False
For a = 1 To 5
For b = 1 To 5
For j = 1 To 3
s = s + (arry1(b, j) * arry2(j, a))
c(a, b) = s
Next j
s=0
Next b
Next a
For i = 1 To 5
For j = 1 To 5
Print Space(3); c(i, j);
Next j
Print ""
Next i
thank you for your answers i solved the problem by may self and its pleasure me if you tel your openion in my code ... thank you

Resources