Home » excel » vba – Iterate over Methods defined in a Module

vba – Iterate over Methods defined in a Module

Posted by: admin April 23, 2020 Leave a comment

Questions:

I have recently found out about VBIDE library, but I don’t quite grap all of it’s capabilities yet. I want to make a method that will instantiate correct Class based on classes found in my Project. Classes that fit as candidates to be instantiated Implement InterfaceA, and the exact class that I want to instantiate has property MType and it returns Enumerated Value Correct.

So to sumarize how do I iterate over classes defined in my project in order to find Class that returns Correct for Property MType, and Instantiate that Class.

Thus far I know that I can Iterate over my modules with following code:

Dim Part As VBComponent
For Each Part In Application.VBE.ActiveVBProject.VBComponents
    Debug.Print Part.Name
Next Part

What I am missing now how do I iterate over methods/properties of each class to find out what these mehods return?

Here is method I need to find, it varies from class to class by value it returns:

Public Property Get InterfaceA_MType() As Model_Types
    IModel_MType = Severity
End Property

So as you can see this Property is pretty simple I am to assume that it will return same value all the time.

UPDATE: Per Dough Gancy’s observation part of the answer is located in here
I can use ProcBodyLine(InterfaceA_MType) and ProcCountLines(InterfaceA_MType) to iterate over the procedure lines, match those lines witch one that has IModel_MType = Correct.

This leaves out only instantiating the Class based on the Code Module. how do I do that?

How to&Answers:

First off, this doesn’t iterate over your classes, it iterates over all modules in your file.

Dim Part As VBComponent
For Each Part In Application.VBE.ActiveVBProject.VBComponents
    Debug.Print Part.Name
Next Part

If you want to iterate over just the class modules, you’ll need to check the component type.

Dim Part As VBComponent
For Each Part In Application.VBE.ActiveVBProject.VBComponents
    If Part.Type = vbext_ct_ClassModule Then
        Debug.Print Part.Name
    End If
End If

Now, to find any particular method in a code module, you’ll need to use the Find method of the CodeModule object.

Of special note, is the fact that startline, endline, startcol, and endcol are all passed by reference and are effectively “out” parameters.

So, that code would look something like this.

Dim startLine As Long
Dim endLine As Long
Dim startCol As Long
Dim endCol As Long

startLine = 1
startCol = 1
endLine = -1
endCol = -1

If Part.Find("Public Property Get InterfaceA_MType()", startLine, startCol, endLine, endCol) Then
    ' do something
End If

Finally, in order to create an instance of a class, it’s going to necessarily be a global instance… which kind of smells, but whatever. You’ve not really given us your end goal. I have a feeling that your problem is better solved via some good OOP programming, but that’s not the question you asked.

To get an instance of the class to work with, you’ll need to dynamically create a module and procedure that instantiates an instance of that class. Perhaps even re-writes the calling code on the fly.

So, in this dynamically generated module, you’ll need to write something like this.

Public dynamic As ClassType

Public Sub InitalizeDynamic()
     Set dynamic = new ClassType
End Sub

Then, somewhere else, you would call the plain jane module sub with Application.Run.

Public Sub Test1()
    Application.Run "VBAProject.Module1.IntializeDynamic"
End Sub

So, that finally you could use the instance of dynamic.

foo = dynamic.InterfaceA_MType()

If you carefully read the questions I linked to with other answers of mine, you should be able to work out a solution. Everything you need to know is in the combination of those two answers.