Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class "let" stuck in infinite loop

Tags:

excel

vba

Forgive any stupid errors in the code, because this is my first attempt at using classes and I couldn't find any tutorials online that put it in really, really plain terms for fools like me. I did my best to sort of follow the MS guide at https://msdn.microsoft.com/en-us/library/aa716315(v=vs.60).aspx, but I don't really understand what I'm doing anyway, which makes it hard to interpret what I should be changing.

I am trying to make a class that stores three pieces of data, two integers and a string. I put this in a class module called tdata:

Sub tdata()

Dim tnumber As Integer, tacct As Integer
Dim ttype As String

Public Property Get t_acct() As Integer         'don't forget the account number!
    t_acct = tacct
End Property

Public Property Let t_acct(ByVal newval As Integer)
    t_acct = newval
End Property

Public Property Get t_numb() As Integer         'T1, T2, or T3 as applicable
    t_numb = tnumb
End Property

Public Property Let t_numb(ByVal newval As Integer)
    t_numb = newval
End Property

Public Property Get t_type() As String          'PF or MW
    t_type = ttype
End Property

Public Property Let t_type(ByVal newstr As String)
    t_type = newstr
End Property

End Sub

I then called it in my function using

Set t_info = New tdata
t_info.t_acct = wb2.Sheets(1).Cells(d, 1)             'd is just a row counter in a for loop
t_info.t_numb = Right(wb2.Sheets(1).Cells(d, 4), 1)
t_info.t_type = wb2.Sheets(1).Cells(d, 6)
references(CStr(wb2.Sheets(1).Cells(d, 5))).Add t_info

(this is not all the code, of course, but just the part where it is called)

I've got Option Explicit and all that fun stuff on and everything compiles fine, but when it gets to the second line of the function snippet, where it tries make t_info.t_acct equal to something, it heads to the Let function for that one, and stays there...forever. Specifically, it bounces between

Public Property Let t_acct(ByVal newval As Integer)
    t_acct = newval

forever. Why is this? How do I make it set (err, let) t_acct equal the thing I want it to?

like image 876
kumquatwhat Avatar asked Dec 08 '22 19:12

kumquatwhat


1 Answers

Your issue is here:

Public Property Let t_acct(ByVal newval As Integer)
    t_acct = newval
End Property

That should be assigning the encapsulated field (tacct), not itself.


I'm going to give you my secret recipe: whenever I create a new class module, I start with a private type:

Option Explicit
Private Type TData 'assuming class module is named 'Data'
    Number As Integer
    Account As Integer
    AccountType As String
End Type

And then, I declare a private field of that type, named this:

Private this As TData

Some might argue that this makes everything oh so confusing because this (the private field) isn't Me (the object instance) and in other languages this refers to the object instance and whatnot - if it confuses you, give it whatever name you like then (backing and encapsulated are perfectly fine too!).

Now all the properties become crystal-clear, and consistent:

Public Property Get Number() As Integer
    Number = this.Number
End Property

Public Property Let Number(ByVal value As Integer)
    this.Number = value
End Property

Public Property Get Account() As Integer
    Account = this.Account
End Property

Public Property Let Account(ByVal value As Integer)
    this.Account = value
End Property

Public Property Get AccountType() As String
    AccountType = this.AccountType
End Property

Public Property Let AccountType(ByVal value As String)
    this.AccountType = value
End Property

Property Get members return this.ThePropertyName, and Property Let members assign this.ThePropertyName with the supplied value - always. If a property needs to be an object type that isn't get-only, you'll want to supply a Property Set member:

Private Type TData
    '...
    SomeObject As Object
End Type
Private this As TData    

Public Property Get SomeObject() As Object
    Set SomeObject = this.SomeObject
End Property

Public Property Set SomeObject(ByVal value As Object)
    Set this.SomeObject = value
End Property

Avoid disemvoweling, prefixes and unreadable/meaningless names, use PascalCase for public members, favor consistency, and whatever you do, avoid underscores in public class members' names - otherwise the day you want to start using Implements is the day your code stops compiling. Follow that, and your class modules should always be crystal-clear.

like image 92
Mathieu Guindon Avatar answered Dec 10 '22 11:12

Mathieu Guindon