Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

need help with (simple?) vba problem

Status
Not open for further replies.

praxitas

Technical User
Feb 25, 2009
3
US
hi
i am sure the answer to this is silly, but here goes. i have the following code. it includes a class called transforms, with members and come a function to test the class. the problem is that i have a class method called ReverseLastTransform() which is supposed to reverse the +/- of the values in each of the vector array values, bit this is not working. i am sure i am doing overlooking something really obvious. any help will be appreciated

'CLASS-----------------------------
Public VectorStack As New Collection

Public Sub AddVector(item As Variant)
'perform validation before adding to ensure 0 to 3) double vector array
VectorStack.add (item)
End Sub

Public Sub DeleteVector(index As Integer)
VectorStack.Remove (index)
End Sub

Public Sub ReverseLastTransform()
Dim count As Integer
count = VectorStack.count
Dim VectorElement As Variant

For Each VectorElement In Me.VectorStack.item(count)
VectorElement = VectorElement * -1
Next VectorElement
End Sub

Public Sub ReverseAllTransforms()
'placeholder for class method
MsgBox "we are in ReverseAllTransforms"
End Sub

'TEST CODE------------------------------------
Public Function TestTransform()
Dim MyTransformStack As New transform
Dim vector_1(0 To 3), vector_2(0 To 3), vector_3(0 To 3) As Variant

vector_1(0) = 5#: vector_1(1) = 5#: vector_1(2) = 5#: vector_1(3) = 91#
vector_2(0) = 6#: vector_2(1) = 6#: vector_2(2) = 6#: vector_2(3) = 92#
vector_3(0) = 7#: vector_3(1) = 7#: vector_3(2) = 7#: vector_3(3) = 93#


MyTransformStack.AddVector vector_1
MyTransformStack.AddVector vector_2
MyTransformStack.AddVector vector_3

MyTransformStack.ReverseLastTransform

End Function
 
For Each VectorElement In Me.VectorStack.item(count)

makes no sense
Me.VectorStack.item(count) returns the last vectorElement in the collection. You can not have a vectorElement "in" another vectorElement. You probably meant

For each vectorElement in Me.vectorStack
 
the vectorstack is a collection and the contents are 4 element vector arrays. the line
"For Each VectorElement In Me.VectorStack.item(count)"
was an attempt to reference the last stack element (VectorElement, which is an array), and then iterate the elements in this array using the "for next" loop. i seem to have learnet that i cannot change the value of the stack array elements in this way as i have done it now, but some version of it, perhaps using a different kind of loop should be possible or if i emloyed pointers and my variable scoping properly. instead my work around has been to create a temprary array, compute the reverse of the current stack vector array, delete the stack element, then add the minused version to its previous position. it seems like a clumsy way of doing things.
 
Perhaps this thread could help: thread222-882802.

If you would use a Class instead of an array of doubles as vector you could create a method for your vector object to reverse.

Code:
' Class Vector -----------------------
Option Explicit

Private Value(0 To 3) As Double

Public Property Get Item(Index As Long) As Double
    Item = Value(Index)
End Property
Public Property Let Item(Index As Long, newValue As Double)
    Value(Index) = newValue
End Property

Public Sub Init(ParamArray args())
    Dim i As Integer
    Dim Max As Integer
    
    Max = UBound(args)
    For i = 0 To Max
        Value(i) = args(i)
    Next i
End Sub

Public Sub Reverse()
    Dim i As Long
    
    For i = 0 To 3
        Value(i) = -Value(i)
    Next i
End Sub

'CLASS transform ------------------
Public VectorStack As New Collection

Public Sub AddVector(Item As Vector)
'perform validation before adding to ensure 0 to 3) double vector array
VectorStack.Add Item
End Sub

Public Sub DeleteVector(Index As Integer)
VectorStack.Remove (Index)
End Sub

Public Sub ReverseLastTransform()
    Me.VectorStack.Item(Me.VectorStack.count).Reverse
End Sub

Public Sub ReverseAllTransforms()
'placeholder for class method
MsgBox "we are in ReverseAllTransforms"
End Sub

To test you could use something like this

Code:
'TEST CODE------------------------------------
Public Function TestTransform()
    Dim MyTransformStack As New transform
    Dim vector_1 As New Vector, vector_2 As New Vector, vector_3 As New Vector

    vector_1.Init 5#, 5#, 5#, 91#
    vector_2.Init 6#, 6#, 6#, 92#
    vector_3.Init 7#, 7#, 7#, 93#
    MyTransformStack.AddVector vector_1
    MyTransformStack.AddVector vector_2
    MyTransformStack.AddVector vector_3
    
    MyTransformStack.ReverseLastTransform

End Function

 
I beleive what you call a "workaround" is the standard procedure for what you are trying to do. I beleive that the issue is that the pointers in a collection are "byVal" pointers. The same issue is with passing objects to functions byVal

Objects are always passed by reference. The ByRef and ByVal modifers indicate how the reference is passed to the called procedure. When you pass an object type variable to a procedure, the reference or address to the object is passed -- you never really pass the object itself. When you pass an object ByRef the reference is passed by reference and the called procedure can change the object to which that reference refers to. When an object is passed ByVal an copy of the reference (address) of the object is passed.

As is so often the case, an example will serve well to illustrate this:

Sub CallingProcedure()
Dim Range1 As Range
Dim Range2 As Range
Set Range1 = Range("A1")
Set Range2 = Range("A2")
Range1.Value = 123
Range2.Value = 456
'''''''''''''''
' Debug Group 1
'''''''''''''''
Debug.Print "BEFORE CALL::Range1: " & Range1.Address(False, False) & " = " & Range1.Value
Debug.Print "BEFORE CALL::Range2: " & Range2.Address(False, False) & " = " & Range2.Value
CalledProcedure R1:=Range1, R2:=Range2
'''''''''''''''
' Debug Group 2
'''''''''''''''
Debug.Print "AFTER CALL::Range1: " & Range1.Address(False, False) & " = " & Range1.Value
Debug.Print "AFTER CALL::Range2: " & Range2.Address(False, False) & " = " & Range2.Value
End Sub

Sub CalledProcedure(ByRef R1 As Range, ByVal R2 As Range)
R1.Value = 321
R2.Value = 654

Set R1 = Range("A3")
Set R2 = Range("A4")
End Sub

In the CallingProcedure, the variable Range1 is set to Range("A1") and the variable Range2 is set to Range("A2"). Then CalledProcedure is called, passing ByRef R1 and ByVal R2. The CalledProcedure sets the values of these ranges to new values and then changes the ranges to which R1 and R2 refer. Since R1 was passed ByRef, the CalledProcedure can change the cell to which Range1 in CallingProcedure refers to. As is confirmed by the second group of Debug.Print statements, the variable Range1 now refers to (points to) Range("A3"), not Range("A1"). However, since R2 was passed ByVal, the CalledProcedure cannot change the range to which Range2 refers to in CallingProcedure.
 
Disregard my last. Although that is a good discussion. The argument is not valid to this.
 
@ schweiger,majp

guys (?) thanks for taking time to reply. your responses have been very helpful
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top