Build Object Hierarchy in Excel-VBA - excel

I'm losing quite some time copy-pasting identical properties and methods in various vba custom object I'm building. How do I create an custom-object hierarchy in VBA so one object and inherit properties and methods from others.
In python I would prob write something like:
Class Car(Object)
whatever
Class SlowCar(Car)
inherit whatever
Class FastCar(Car)
inherit whatever
tks in advance.

If i understand what you're saying, this can be done via the Class Module.
From the VBA Editor, select Insert > Class Module
Change the name of the class Module to whatever you want (Car for
example) via the Properties Window (press F4 to make it appear if it
does not already)
Now that you've created your class module you can define its variables and/or properties. The example below would go into your Car Class Module creates a object that holds a car name and a speed
Private carName As String
Private carSpeed As Integer
' Car Name
Public Property Get Name() As String
Name = carName
End Property
Public Property Let Name(result As String)
carName = result
End Property
' Car Speed
Public Property Get Speed() As Integer
Speed = carSpeed
End Property
Public Property Let Speed(result As Integer)
carSpeed = result
End Property
Then from your Module, you can do the following
Sub CreateMyCars()
Dim slowCar as Car
Dim fastCar as Car
Set slowCar = New Car
Set fastCar = New Car
slowCar.Name = "GoKart"
slowCar.Speed = 35
fastCar.Name = "Ferarri"
fastCar.Speed = 185
End Sub

VBA supports inheritance through the use of Interfaces, but they only "inherit" the signature of methods, not the implementation.
A way to reuse an object implementation would be through composition.
Class Car(Object)
whatever
Class SlowCar(Car)
Implements Car
private mCar as Car
Private Sub Class_Initialize
set mCar = new Car
End Sub
Private Sub Car_whatever
Call mCar.whatever
End Sub
And same for FastCar.

Related

Can't see created objects

I've created some simple classes in excel and I'm trying to create new objects from these classes. It works fine and let's me create them and I can also access the variables given to the object. I can't see the object in the local window though and I don't really understand why. Is it not created correctly because you are supposed to see your objects there I understand?
Here is the code for the class
Option Explicit
'Teams
Public Name As String
Public Group As String
Public GF As Integer
Public GA As Integer
Public Points As Integer
'Public Players(25) As String
Private Sub class_initialize()
Points = 5
End Sub
and here is the code where I try to create an object
Sub TestTeams()
Dim Madagaskar As Object
Set Madagaskar = New ETeam
MsgBox (Madagaskar.Points)
End Sub
If you put Stop on the line after the MsgBox call and run TestTeams, you will see the object in the locals window.
It will only be there while Madagaskar is in scope and you're in break mode.

Pass an object as parameter from a UserForm to another one

I create a Class type Employee
Private emplId As String
Private name As String
Private rank As String
Private post As String
I create a module with a function Inside who return an object type Employee.
Public Function FuncNewPerson(Emplid As String) As Employee
Dim newPerson As New Employee
With newPerson
newPerson.SetEmplid = Emplid
newPerson.SetName = mytab(25, 1)
newPerson.SetRank = mytab(23, 1)
newPerson.SetPost = mytab(27, 1)
Set FuncNewPerson = newPerson
I use two UserForms, in the first one after selection of an emplId via a ComboBox it initialize an object type Employee, then I fill all the TextBox of the first UserForm with the get property of the object :
RequestForm.TxtBoxPerson = person.GetName
RequestForm.txtBoxRank = person.GetRank
On this UserForm i have a Button who calls the second one :
Public Sub BtnVerify_Click()
Me.Hide
ValidationForm.Show
End Sub
In the second UserForm I have some other TextBox to fill :
ValidationForm.TxtBoxEmployee = person.GetEmplid
ValidationForm.txtBoxRank = person.GetRank
ValidationForm.txtBoxPost = person.GetPost
I would like to use the object who is already in memory so my first idea is to pass it as an argument from the first form to the second one.
Of course i already searched the web but i'm now more confused about it, that's why i ask some help here in order to :
get some clues
get a feedback about my way of doing this
Thank you
In the second form, create a suitable variable
Private Person as Employee
Then create a property
Property Set CurrentPerson(p as Employee)
set person = p
End Property
Then set this property in the code from your first form
Public Sub BtnVerify_Click()
Me.Hide
ValidationForm.Show
Set validationform.currentperson = person
End Sub

List the properties of a class in VBA 2003

I've searched all over to see if there is an easy answer to this question, but there doesn't seem to be...
I'm using Excel VBA 2003 (yes, I know it's out-of date, but I can't change this), and all I want to do is list the names and values of all the readable properties in a given custom class.
I'd like to do something like this:
Class definition (for class entitled cFooBar)
Option Explicit
Private pFoo As String
Private pBar As String
Public Property Get Foo() As String
Foo=pFoo
End Property
Public Property Get Bar() As String
Bar=pBar
End Property
Calling code
Dim myFooBar as cFooBar, P as Property
myFooBar=new cFooBar
For Each P in myFooBar.Properties
Debug.Print P.Name, P.Value
Next
Of course, this doesn't work because there doesn't seem to be a "Properties" collection member for custom classes (or at least not one that you can get at), and there isn't a "Property" type either.
Does anybody know a way around this?
TIA,
Campbell
As John mentions above, reflection is not supported in VBA. Here is a hack that I have used before. Basically you can create a Collection or Dictionary object to store your "properties" by name.
Option Explicit
Private pProperties As Object
Public Property Get Properties() As Object
Set Properties=pProperties
End Property
Public Property Let Properties(p as Object)
Set pProperties = p
End Property
Sub Class_Initialize()
Set pProperties = CreateObject("Scripting.Dictionary")
'Add/instantiate your properties here
pProperties("foo") = "this is foo"
pProperties("bar") = "this is bar"
End Sub
Calling code
Dim myFooBar As New cFooBar, P As Variant
For Each P In myFooBar.Properties.Keys()
Debug.Print P, myFooBar.Properties(P)
Next

Passing objects to procedures in VBA

I am working on a simple tool that will allow me to parse multiple CSV files and spit them out onto a fresh worksheet "merged" together. Here is my implementation (I've simplified it) and my issue:
Class A
private variables as types
property methods for accessing variables
Class B
private variables as types
property methods for accessing variables
Class C
Private cA as ClassA
Private cB as Collection 'Collection of ClassB
Class D - Part of my problem
Private cC as Collection 'Collection of ClassC
'Other member variables and their property get/lets
Public Sub AddA(A as ClassA)
If cC.Item(A.foo) is Nothing then
dim tempC as ClassC
set tempC = new ClassC
tempC.A = A
End if
End Sub
Main Module - Other half of my problem
Dim cC as New ClassC
'Initialize Class C, this all works fine
Dim tempA as ClassA
Set tempA = new ClassA
'Set tempA properties
cC.AddA tempA 'This is where my error is
I've tried passing it as ByVal and ByRef each gives me different errors ("byref argument type mismatch", "invalid procedure or argument", and "Object doesn't support this property or method"
I have no idea what to try next, I even tried the parenthesis "thing" that supposedly forces the parameter into either ByVal or ByRef, I can't remember, that was yesterday.
Thanks.
This line:
tempC.A = A
means "assing to A property of tempC object the value of the default property of the A object."
Your A object apparently doesn't have a default property.
What you actually meant was probably:
Set tempC.A = A
But even then, you can't access a private field A of C class from D class. Make the field public or create a public SetA() method on C class and call it from D.

Dictionary Property in VBA Class

I have been asked to modify an Excel sheet with some arcaic programming. I have decided to rewrite it rather then modify all of the many GOTO statments and static arrays. My background is in C# so it has been a bit of a challenge (note: I am sure the naming convention is bad, I am used to being able to use underscore to define private variables)
I am having trouble inializing an attribute of the type dictionary within a class that I have in a VBA application.
The shortened version of the class looks like this
Private pTerminalCode As String
Private pTerminalName As String
...... other attributes
Private pPayRoll As Dictionary
'Propeties
Public Property Get terminalCode() As String
terminalCode = pTerminalCode
End Property
Public Property Let terminalCode(Value As String)
pTerminalCode = Value
End Property
....... more properties
Public Property Get headCount() As Dictionary
headCount = pHeadCount
End Property
Public Property Let headCount(Value As Dictionary)
pHeadCount = Value
End Property
When I try to use the following I get the error "Argument not optional" within the Get property of the headCount() attribute.
Private Function PopulateTerminal()
Dim terminal As clsTerminal
Set terminal = New clsTerminal
terminal.terminalCode = "Wil"
terminal.headCount.Add "Company", 100
End Function
I assume somewhere I need to inialize the dictionary (i.e. = New Dictionary) however I am strugling with where to place it. In C# I do this in the constructor without issue, not sure what to do here.
Thanks
You can do it in the constructor of the VBA class, like so:-
Public Sub Class_Initialize()
Set myDictionary = New Dictionary
End Sub
Don't forget to always use the Set keyword when assigning an object reference, e.g.:-
Public Property Get Foo() As Dictionary
Set Foo = myDictionary
End Sub

Resources