I would like to iterate through members of any class in a referenced library much like is done using the Object Browser. How can this be done using VBA?
-
And, why would you want to do that? – shahkalpesh Dec 12 '09 at 04:35
-
Reflection See http://en.wikipedia.org/wiki/Reflection_(computer_science) – Curtis Inderwiesche Dec 12 '09 at 06:08
-
Self-modifying VBA is going to be unstable because of the nature of the way the VBA project is stored and linked in memory. Perhaps it could be done with an add-in library, but add-ins fail to work when the current project is broken, too, so I can't see how this could be reliably implemented. I have even more difficulty figuring out why anyone would consider it useful at runtime (as opposed to during the development project). This looks like yet another mis-application to Access of inappropriate programming practices that come from other environments. – David-W-Fenton Dec 12 '09 at 22:19
-
What about its storage and linking would make it prone to be unstable? – Curtis Inderwiesche Dec 13 '09 at 21:02
-
The VBA project is all stored in a single BLOB field in a single record in a system table. Trying to modify that data while you're running it is, to say the least, fraught with danger. – David-W-Fenton Dec 14 '09 at 22:55
-
I Guess I just don't understand why that would be an issue. If the project is stored in a table as a BLOB or any other location or format, accounting for proper logic and syntax should circumvent instability. I would really like to know why this is an issue? It seems to me this is just a matter of interpreting code as data and evaluating it upon execution. Any additional thoughts? – Curtis Inderwiesche Dec 15 '09 at 03:29
-
The problem is that you're executing code in the same memory space as the code you are updating. VBA code can corrupt without doing something as exotic as that without aggravating the situation with self-modifying code. Now, if you're doing the modifications with SaveAsText/LoadFromText, that could be less of an issue. I don't see the point either way. – David-W-Fenton Dec 15 '09 at 23:09
-
@David you wouldn't happen to be a DBA would you? :) – tbone Jul 17 '15 at 19:56
5 Answers
Actually, how to do this is undocumented, but is possible. If your looking to implement a for..Each syntax for a collection, then you can do the following:
Option Compare Database
Option Explicit
Public colT As New Collection
Public Function NewEnum() As IUnknown
Set NewEnum = colT.[_NewEnum]
End Function
Public Property Get NextItem() As IUnknown
Attribute NextItem.VB_UserMemId = -4
Attribute NextItem.VB_MemberFlags = "40"
Set NextItem = colT.[_NewEnum]
End Property
Note the Attribute settings in the above. You have to use the SaveAsText and edit code as above in notepad. You then re-import the code using loadfromText in the debug command line. Once you do the above, then you can go:
Dim n As clstest1
Dim v As Variant
Set n = New clstest1
[ code here that adds to collection]
For Each v In n
Debug.Print v
Next
And, if you not looking to use for...each for a collection, you could/can also setup a default property of the class by going:
Public Property Get Item(Optional ndx As Integer = 1) As Variant
Attribute Item.VB_UserMemId = 0
Select Case ndx
Case 1: Item = Me.s1
Case 2: Item = Me.s2
Case 3: Item = Me.s3
End Select
End Property
Public Property Get count() As Integer
count = 3
End Property
Then, you can go:
Dim n As clstest1
Dim i As Integer
Set n = New clstest1
For i = 1 To n.count
Debug.Print n(i)
Next
However, I not aware how you can automatic add each method/member of the class to a built-in object collection automatic (there is no way to serialize this with compiler options, but I have seen code with each procedure having Attribute Item.VB_UserMemId = 1, then 2 then 3). Perhaps someone with more knowledge can jump in).
However, as the above shows, you can implement a for..each for collections. And you can implement an index for each of the properties/methods if you create a custom item property. And, as the above shows, you can even set that item property you create as the default. I put in the "optional", and thus even:
debug.print n
Will work, or
debug.print n.Item(1)

- 42,205
- 3
- 34
- 51
-
"I not aware how you can automatic add each method/member of the class to a collection automatic" -- I'm willing to jump in but, with respect, your sentence does not scan correctly. Can you correct this, please? – onedaywhen Dec 14 '09 at 08:54
-
I changed the text to "built-in object collection". Many languages (compilers) allow a methods of an object to be added to some type of built-in object collection (that can be then iterated or inspected in code without knowing the names of the methods). Same thing when you serialize an object. In both cases it is common to have some compiler directive that placed in each method will thus determine if the method will be included in that built-in object list (or will be serialized) . Attribute Item.VB_UserMemId = N suggests that there is a possibility of inspecting this collection of methods. – Albert D. Kallal Dec 15 '09 at 14:02
-
+1 for an illuminating answer, but I still cannot see the point of the endeavor outlined in the original question. – David-W-Fenton Dec 15 '09 at 23:11
I found a KB from Microsoft which allowed me to do just that. It also covers iteration over Member details as well.
Private Sub ListClassesInAccess()
Dim TypeLibrary As TypeLibInfo
Dim ClassList As CoClasses
Dim i As Integer
Dim Path As String
Path = "C:\Program Files\Microsoft Office\OFFICE11\MSACC.OLB"
Set TypeLibrary = TypeLibInfoFromFile(Path)
Set ClassList = TypeLibrary.CoClasses
For i = 1 To ClassList.Count
MsgBox ClassList.Item(i).Name
Next
Set TypeLibrary = Nothing
Set ClassList = Nothing
End Sub

- 4,940
- 19
- 60
- 82
Unfortunately, Access VBA doesn't support reflection. You could try creating your own abstraction of the object hierarchy that will inspect property values, etc. for you. You might start with something like this:
http://msdn.microsoft.com/en-us/library/aa663065%28office.11%29.aspx

- 12,302
- 4
- 34
- 52
If you have VB6 installed - then you can try tlbinf32.dll. AFAIR - if has number of classes to get info of any typelibrary See http://support.microsoft.com/kb/224331

- 510
- 1
- 4
- 11