Variable in class interface

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,834
Office Version
  1. 365
  2. 2019
Platform
  1. Windows
This is in a standard module:

Code:
Option Explicit
    
Public Sub Test()
    
    Dim MyClsInterface As ClsInterface
    
    Select Case Sheet1.Cells(2, 1).Value
    
        Case vbNullString
            
            Set MyClsInterface = ClassFactory(Val:="Empty")
            
        Case Else
    
            Set MyClsInterface = ClassFactory(Val:="Not empty")
            
    End Select
    
    Dim Rng As Range
    
    Dim Rngelement As Range
    
    Dim ws As Worksheet
    
    For Each ws In ThisWorkbook.Worksheets
    
        With ws

            Set Rng = .Range(.Cells(2, 6), .Cells(10, 6))
        
        End With
        
        Set MyClsInterface.Rng = Rng
        Set MyClsInterface.Rngelement = Rngelement
        
        Call MyClsInterface.SomeMethod
          
    Next ws
    
    Set ws = Nothing
     
    Set Rng = Nothing
    
    Set Rngelement = Nothing
    
End Sub
    
Private Function ClassFactory(ByRef Val As String) As ClsInterface

    Select Case Val
    
        Case "Empty"
            
            Set ClassFactory = New ClsEmpty
            
        Case "Not empty"
        
            Set ClassFactory = New ClsNotEmpty
            
    End Select

End Function


This is ClsInterface:

Code:
Option Explicit
    
    Private pRng As Range
    Private pRngElement As Range

Public Property Get Rng() As Range

    Set Rng = pRng
    
End Property

Public Property Set Rng(ByVal R As Range)

    Set pRng = R
    
End Property

Public Property Get Rngelement() As Range
    
    Set Rngelement = pRngElement
    
End Property

Public Property Set Rngelement(ByVal RElement As Range)

    Set pRngElement = RElement
    
End Property

Public Sub SomeMethod()

End Sub


This is ClsNonEmpty:

Code:
Option Explicit

    Implements ClsInterface

    Private pClsInterface_Rng As Range
    Private pClsInterface_RngElement As Range
    
Public Property Get ClsInterface_Rng() As Range

    Set ClsInterface_Rng = pClsInterface_Rng
    
End Property

Public Property Set ClsInterface_Rng(ByVal R As Range)

    Set pClsInterface_Rng = R
    
End Property

Public Property Get ClsInterface_RngElement() As Range
    
    Set ClsInterface_RngElement = pClsInterface_RngElement
    
End Property

Public Property Set ClsInterface_RngElement(ByVal RElement As Range)

    Set pClsInterface_RngElement = RElement
    
End Property

Private Sub ClsInterface_SomeMethod()
    
    Dim Coll As Collection
    Set Coll = New Collection
    
    Coll.Add "apple"
    Coll.Add "orange"
    
    Dim CollElement As Variant
     
    For Each CollElement In Coll
    
        For Each ClsInterface_RngElement In ClsInterface_Rng.Cells
        
            If InStr(1, ClsInterface_RngElement.Text, CollElement, vbBinaryCompare) <> 0 Then MsgBox "hi"
                                                                                                        
           
        Next ClsInterface_RngElement
        
    Next CollElement
    
    Set CollElement = Nothing

End Sub


This is ClsEmpty:

Code:
Option Explicit

    Implements ClsInterface

    Private pClsInterface_Rng As Range
    Private pClsInterface_RngElement As Range
    
Public Property Get ClsInterface_Rng() As Range
    
End Property

Public Property Set ClsInterface_Rng(ByVal R As Range)

End Property

Public Property Get ClsInterface_RngElement() As Range
    
End Property

Public Property Set ClsInterface_RngElement(ByVal RElement As Range)

End Property

Private Sub ClsInterface_SomeMethod()

End Sub


The above code does not compile. The error message is:

Code:
    Variable required -can't assign to this operation

and points to this line:

Code:
    For Each ClsInterface_RngElement In ClsInterface_Rng.Cells

in particular, highlighting this word:

Code:
    ClsInterface_RngElement

If I changed it to:

Code:
For Each pClsInterface_RngElement In ClsInterface_Rng.Cells
        
        If InStr(1, ClsInterface_RngElement.Text, CollElement, vbBinaryCompare) <> 0 Then MsgBox "hi"
           
Next pClsInterface_RngElement

it works.

Note I DON'T have to change the ClsInterface_RngElement inside the loop, ie

Code:
    If InStr(1, ClsInterface_RngElement.Text, CollElement, vbBinaryCompare) <> 0 Then MsgBox "hi"

works.

But even if I DO change it to:

Code:
    If InStr(1, pClsInterface_RngElement.Text, CollElement, vbBinaryCompare) <> 0 Then MsgBox "hi"

it also works.

Can someone please explain what is wrong?

Thanks
 
I mean why would you want to use either of those for a For Each loop rather than just a local Range variable?
Maybe I'm misunderstanding things.

I have a range so to loop through it using a For Each Loop, I'd need a variable to do that.

Instead, how would you write it?
 
Upvote 0

Excel Facts

Can you AutoAverage in Excel?
There is a drop-down next to the AutoSum symbol. Open the drop-down to choose AVERAGE, COUNT, MAX, or MIN
Yes you need a range variable, but using a property makes no sense (even if it could work) and I don't see why you would want to use a module-level variable for it either?
 
Upvote 0
Yes you need a range variable, but using a property makes no sense (even if it could work) and I don't see why you would want to use a module-level variable for it either?
"My style" re methods within class modules is not to pass arguments.

So instead of:

Code:
Sub SomeMethod(Arg1 As String, Arg2 As integer)

    ' some code

End Sub

I prefer to define properties in class modules and use them, so the method becomes:

Code:
Private pArg1 As String
Private pArg2 As Integer

Public Property Get Arg1 As String

    Arg1=pArg1

End Property

Public Property Let Arg1 (A1 as Integer)

    pArg1 = A1

End Property

Public Property Get Arg2 As Integer

    Arg2= pArg2

End Property

Public Property Let Arg2 (A2 as Integer)

    pArg2 = A2

End Property

Sub SomeMethod()

    ' some code

End Sub
 
Upvote 0
I don't see how that is relevant? Your variable for the For Each loop is essentially a temp variable so it wouldn't be something you pass as an argument or a property.
 
Upvote 0
I don't see how that is relevant? Your variable for the For Each loop is essentially a temp variable so it wouldn't be something you pass as an argument or a property.
I finally see what you mean (I think)!

Yes, it's unecessary and actually does nothing, so I shouldn't have created it in the first place.

A local temp variable, (RngElement dcalred in the class), would be good enough to loop through the collection.
 
Upvote 0
I finally see what you mean (I think)!

Yes, it's unecessary and actually does nothing, so I shouldn't have created it in the first place.

A local temp variable, (RngElement dcalred in the class), would be good enough to loop through the collection.
I've delved deeper and realised the confusion.

Within the standard module, I had other Subs that contained For Each Loops.

So to loop through them, instead of creating a local variable, RngElement, within each Sub, I created a module level variable.

That's why in the classs, it contained the RngElement Property.
 
Upvote 0
To me, that's lazy programming rather than good programming. And still doesn't make sense as regards the property.
 
Upvote 0
To me, that's lazy programming rather than good programming. And still doesn't make sense as regards the property.
Lazy because instead I should declare a local variable within each Sub that performs a For Each Loop?

I thought it was more efficient, only declaring it once.


So I have other subs within the standard module, eg:

Code:
Sub SomeSub1(Arg1 As Range)

    For Each Arg1 In .....


    Next Arg1

End Sub

Sub SomeSub2(Arg1 As Range)

    For Each Arg1 In .....

    Next Arg1

End Sub


As regards the Property, that was because I was passing in the argument into the class, the equivalent of the Subs above, ie:

[code]

(Arg1 As Range)
 
Upvote 0
But why are you passing Arg1 to the sub in the first place?
 
Upvote 0
But why are you passing Arg1 to the sub in the first place?
Are you refering to Sub SomeSub1(Arg1 As Range) and Sub SomeSub2(Arg1 As Range)?

Simply because I won't have to write:

Code:
Dim RngElement As Range

in both Sub SomeSub1 and Sub SomeSub2 because they both use a For Each Loop.
 
Upvote 0

Forum statistics

Threads
1,215,635
Messages
6,125,942
Members
449,275
Latest member
jacob_mcbride

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top