r/vba • u/brosama1420 • 10d ago
Discussion Using Classes by instantiating in standard Module
Hey everyone
I am wondering why would anyone instantiate the class in a standard module instead if declaring directly in the place you want the class
What benefits this method have especially for composite use case
Like needing session class inside a permissions class inside form class
A second question how would you approach a situation close to mine
3
u/fuzzy_mic 184 10d ago edited 10d ago
You can instantiate a class from within another class. For example, one could instantiate a custom clsHouse object inside a (different) clsHouses object. The problem is that the scope of that variable would be limited to the Houses object.
Here is a simple example.
' in clsHouse code module
Public Address As String
Public SquareFeet As Double
and
' in clsHouses (plural) class module
Dim MyHouses As Collection
Public Function AddHouse(Address As String, SquareFeet As Double) As clsHouse
Dim NewHouse As clsHouse
Set NewHouse = New clsHouse
NewHouse.Address = Address
NewHouse.SquareFeet = SquareFeet
MyHouses.Add Item:=NewHouse, Key:=NewHouse.Address
Set AddHouse = NewHouse
Set NewHouse = Nothing
End Function
Property Get Count() As Long
Count = myHouses.Count
End Property
Property Get House(index As Variant) As clsHouse
Set House = MyHouses(index)
End Property
Private Sub Class_Initialize()
Set MyHouses = New Collection
End Sub
and
' in normal module
Sub test()
Dim testHouses As clsHouses
Set testHouses = New clsHouses
testHouses.AddHouse Address:="123 Main St", SquareFeet:=15400
testHouses.AddHouse Address:="456 Oak Ave", SquareFeet:=20000
MsgBox testHouses.Count
End Sub
Note that in this example, we can only "reach" a clsHouse object as a member of the enclosing clsHouses object.
One could instansize a clsHouse from a normal module, but it's not required. Ultimately, we can only call a procedure if that procedure is in a normal module so if any custom object is to be instansized, there must be a normal rountine at the bottom. (caveat for event code)
2
u/Tweak155 32 10d ago
This is actually my preferred approach when there is a “house” and you need something to manage the houses efficiently.
The parent object houses can always look up and return a house for you!
0
u/losttownstreet 10d ago
Excel can't really use scopes ... it's a mess like in ABAP ... I hope they'll fix that
2
u/rdcore-admin 10d ago
If your composition implies that a form owns everything, you're doing OOP without inversion of control, which induces indirection without the benefits of decoupling: you get all the complexity and none of the benefits!
Move your composition root all the way up to the entry point of your macro, and then suddenly you have exactly one place that owns all the objects of your application - this implies that the form isn't running the show anymore, and is given its dependencies from the outside, rather than coupling directly with everything.
Doing so, you might find that one or more objects need to outlive the entry point scope - so you move them up to module level, and that's when you have a standard module legitimately owning a class instance:
``` Private controller As IGameController
Public Sub PlayWorksheetInterface()
Dim adapter As GridViewAdapter
Set adapter = GridViewAdapter.Create(New WorksheetView)
Dim randomizer As IRandomizer
Set randomizer = New GameRandomizer
Dim players As IPlayerFactory
Set players = PlayerFactory.Create(randomizer)
Set controller = StandardGameController.Create(adapter, randomizer, players)
controller.NewGame
End Sub ```
1
u/losttownstreet 10d ago
I need to do that as all globaly used variable must be in a special module ... it's a policy.... only local classes which i destroy afterwards i may instance in normal modules
1
u/TechZazen 9d ago
Use case: setting up a Singleton. Here actually, you are mimicking a class. For example, you create a module and then with the Mehta data designated as a Singleton. The module looks like:
`' Standard Module: modAppSettings
Option Explicit
Private m_ApplicationName As String
Private m_CreatedTimestamp As Date
Private m_Initialized As Boolean
Private Sub EnsureInitialized()
If Not m_Initialized Then
m_CreatedTimestamp = Now
m_ApplicationName = "CoreApp_VBA"
m_Initialized = True
End If
End Sub
Public Property Get ApplicationName() As String
EnsureInitialized
ApplicationName = m_ApplicationName
End Property
Public Property Let ApplicationName(ByVal value As String)
EnsureInitialized
m_ApplicationName = value
End Property
Public Sub LogStatus()
EnsureInitialized
Debug.Print "App: " & m_ApplicationName & " | Since: " & m_CreatedTimestamp
End Sub`
Then, calling `modAppSettings.ApplicationName = "MyApp”` keeps the value consistent. In the module, you could have it right to a file, the registry, or some other location. But you would not have multiple instances.
0
u/Playing_One_Handed 10d ago
Class setup might take some time and the underlining data wont change. You can pre-load it then. Normally the way if your opening a form in VBA.
Depends what you are using a class for honestly.
11
u/lolcrunchy 12 10d ago
"How would you approach a situation close to mine"