vbaexcelvbide

Iterate over Methods defined in a Module


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?


Solution

  • 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.