Iterando através do navegador de objeto em VBA
Pergunta
Eu gostaria de iterar através de membros de qualquer classe em uma biblioteca referenciada como é feita usando o navegador de objetos. Como isso pode ser feito usando VBA?
Solução 2
Achei um KB da Microsoft O que me permitiu fazer exatamente isso. Também abrange a iteração sobre os detalhes dos membros.
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
Outras dicas
Na verdade, como fazer isso não é documentado, mas é possível. Se você deseja implementar um para ... cada sintaxe para uma coleção, você pode fazer o seguinte:
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
Observe as configurações de atributo no acima. Você deve usar o código SAVETETEXT e editar como acima no bloco de notas. Em seguida, você reimporta o código usando o LoadFromText na linha de comando Debug. Depois de fazer o acima, você pode ir:
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
E, se você não quer usar para ... cada uma de uma coleção, você pode/também pode configurar uma propriedade padrão da classe: indo:
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
Então, você pode ir:
Dim n As clstest1
Dim i As Integer
Set n = New clstest1
For i = 1 To n.count
Debug.Print n(i)
Next
No entanto, não tenho consciência de como você pode adicionar automático cada método/membro da classe a uma coleção de objetos embutida automática (não há como serializar isso com as opções do compilador, mas vi código com cada procedimento com item de atributo.vb_usermemid = 1, então 2 então 3). Talvez alguém com mais conhecimento possa entrar).
No entanto, como mostra o acima, você pode implementar um para ... cada uma para coleções. E você pode implementar um índice para cada uma das propriedades/métodos se criar uma propriedade de item personalizado. E, como mostra o acima, você pode definir a propriedade de item que você cria como o padrão. Eu coloquei o "opcional" e, portanto, até:
debug.print n
Vai funcionar, ou
debug.print n.Item(1)
Infelizmente, o Access VBA não suporta a reflexão. Você pode tentar criar sua própria abstração da hierarquia de objetos que inspecionará os valores das propriedades etc. para você. Você pode começar com algo assim:
http://msdn.microsoft.com/en-us/library/aa663065%28office.11%29.aspx
Se você tiver o VB6 instalado - você pode experimentar o TLBINF32.DLL. AFAIR - Se tiver número de classes para obter informações de qualquer typelibrary ver http://support.microsoft.com/kb/224331
Isso pode ser útil http://msdn.microsoft.com/en-us/magazine/bb985086.aspx