3

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?

Community
  • 1
  • 1
sgp667
  • 1,797
  • 2
  • 20
  • 38
  • If you haven't already looked at Chip Pearson's site, it's got the information you need: http://www.cpearson.com/excel/vbe.aspx – Doug Glancy May 18 '15 at 16:24
  • @DougGlancy Thanks! I actaully saw this before found my answer there but missed the answer(part of) untill you brought it up! I'll update the question accordingly to what I found. – sgp667 May 18 '15 at 16:35
  • Possible duplicate of [this](http://stackoverflow.com/a/28883607/3198973) and [this](http://stackoverflow.com/questions/23736498/import-lines-of-code/23738721#23738721). – RubberDuck May 18 '15 at 17:00
  • @RubberDuck thanks for the input. I may have missed something but I wasn't able to find anything in neither of these question that would solve my problem [this](http://stackoverflow.com/questions/28870454/excel-vba-store-functions-or-subroutines-in-an-array/28883607#28883607) question was about the closest except for the fact that `CallByName` requires for you to have an already instantiated object. My issue now is how do I instantiate that object in first place. – sgp667 May 18 '15 at 17:15
  • Yeah.. your question seems to be shifting under my feet as I type.... – RubberDuck May 18 '15 at 17:15
  • 1
    Beware, writing and executing code on the fly is a great way to crash the VBE... just so you know ;-) – Mathieu Guindon May 18 '15 at 17:44
  • Ya know, the more I think about it, the more I think you have an XY problem. Why not create a new question that explicitly states *what* you're trying to achieve instead of how you're trying to achieve it? – RubberDuck May 18 '15 at 17:47
  • [This](https://github.com/ptwales/VBEX/blob/master/src/Lambda.cls) could give you a few ideas – Mathieu Guindon May 18 '15 at 18:00

1 Answers1

2

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.

Community
  • 1
  • 1
RubberDuck
  • 11,933
  • 4
  • 50
  • 95