2014-04-29 65 views
3

我需要列出一個類的所有私有變量。是這樣的:如何通過VBA中的類屬性循環

變量的類:

Dim varOne as String 
Dim varTwo as Integer 
Dim varThree as Date 
Dim varFour as String 

子是retruns所有的變量名:

For Each classVariable In clsMyClass 
    Msgbox classVariable.Name 
Next 

結果:

varOne 
varTwo 
varThree 
varFour 

我發現在這個論壇的解決方案但只適用於VB.NET,不適用於VBA。無論如何,我可以在VBA中做到這一點?

在此先感謝。


什麼用下面的代碼的問題:

Private Sub btnTest_Click() 
    Dim obj_Utilitario As cls_Utilitario 
    Dim objColecao As Collection 
    Dim item As Variant 

    Set obj_Utilitario = New cls_Utilitario 
    Set objColecao = obj_Utilitario.ColecaoForm(Me.Form) 

    For Each item In objColecao 
     MsgBox item.Name 
    Next item 

    Set objColecao = Nothing 
End Sub 

這是cls_Utilitario類代碼:

Public Function ColecaoForm(arg_form As Object) As Collection 
    Dim colecao As Collection 
    Dim campo As Control 

    For Each campo In arg_form.Controls 
     With campo 
      Select Case .ControlType 
       Case acComboBox, acTextBox 
        colecao.Add (.Object) 
      End Select 
     End With 
    Next campo 

    Set ColecaoForm = colecao 

    Set colecao = Nothing 
    Set campo = Nothing 
    Set arg_form = Nothing 
End Function 

當我刪除括號中的代碼如下因素在Me.Form參數:

Set objColecao = obj_Utilitario.ColecaoForm(Me.Form) 

它讓我繼續運行代碼,但它顯示運行時錯誤2455(無效的引用...) 什麼現在?任何想法?

在此先感謝。


這是迄今爲止cls_Ativo類代碼:

Option Compare Database 
Option Explicit 

Private obj_Utilitario As New cls_Utilitario 
Private col_Ativo As Collection 

Private Const SQL As String = "SELECT tbl_Ativos.codigo_ativo, tbl_Ativos.especificacao FROM tbl_Ativos ORDER BY tbl_Ativos.codigo_ativo;" 

Private Sub Class_Initialize() 
    Dim registro As Recordset 
    Dim campoRegistro As Field 
    Dim i As Integer 

    Set col_Ativo = New Collection 

    Set registro = CurrentDb.OpenRecordset(SQL) 

    If (Not (IsNull(registro)) And (registro.RecordCount > 0)) Then 
     registro.MoveLast 
     registro.MoveFirst 

     For i = 0 To registro.Fields.Count - 1 
      Set campoRegistro = registro.Fields(i) 
      col_Ativo.Add campoRegistro, campoRegistro.SourceField 
     Next i 
    Else 
     Set col_Ativo = Nothing 
    End If 

    Set registro = Nothing 
    Set campoRegistro = Nothing 
End Sub 

Private Sub Class_Terminate() 
    Set col_Ativo = Nothing 
    Set obj_Utilitario = Nothing 
End Sub 

Public Property Get Campo(arg_Item As Variant) As Variant 
    Campo = col_Ativo.item(arg_Item) 
End Property 

Public Property Let Campo(arg_Item As Variant, arg_Valor As Variant) 
    Select Case arg_Item 
     Case "codigo_ativo" 
      If VarType(arg_Valor) = vbString Then 
       If ValidaCodigoAtivo(arg_Valor) Then 
        col_Ativo.item(arg_Item) = arg_Valor 
       Else 
        MsgBox "O código inserido não é válido." 
       End If 
      Else 
       MsgBox "O código inserido não é um texto." 
      End If 

     Case "especificacao" 
      If VarType(arg_Valor) = vbString Then 
       col_Ativo.item(arg_Item) = arg_Valor 
      Else 
       MsgBox "A especificação inserida não é um texto válido." 
      End If 
    End Select 
End Property 

,這就是我想要的窗體模塊中要做到:

Private Sub btnTeste_Click() 
    Dim obj_Ativo As cls_Ativo 

    Set obj_Ativo = New cls_Ativo 

    'Save a text into the collection item "especificacao" using Let property 
    obj_Ativo.Campo ("especificacao","texto de exemplo, texto de exemplo...") 

    'Return the collection item using Get property 
    Msgbox obj_Ativo.Campo ("especificacao") 

    Set obj_Ativo = Nothing 
End Sub 

當我打電話obj_Ativo.Campo,它只是允許我通過arg_Item作爲參數,並表明它不會返回任何值,就好像它是一個Let pro perty。但如果它確實是一個Let屬性,它應該允許我將第二個參數作爲參數傳遞。

我想要的是在類中的所有變量與不同類型的變量而不是私有變量的集合對象。

在此先感謝。

+1

thouse操作的要點是什麼?也許它會更好地存儲你的值[字典](http://stackoverflow.com/questions/915317/does-vba-have-dictionary-structure)(而不是單獨的變量)與'鍵=變量名稱'和' item = varaible value'? –

+2

VBA不提供該類型的「反射」功能。要做到這一點,唯一的方法就是解析類的源代碼。 –

+0

嗨Simoco和蒂姆。我打算將類變量與比較名稱的表單域相鏈接。表單中的每個字段(文本和組合框)將在類中具有相同名稱的變量。我想要的是將存儲在類變量中的值直接關聯到表單域(文本/組合框)。 –

回答

2

對於第二個問題,我認爲你不必傳遞整個表單。只有通過控件纔可以。

Set objColecao = obj_Utilitario.ColecaoForm(Me.Controls) 

然後在函數中不要忘記用'New'關鍵字初始化Collection對象。

Public Function ColecaoForm(arg_form_controls As Controls) As Collection 
    Dim campo As Control 

    Set ColecaoForm = New Collection 

    For Each campo In arg_form_controls 
     If campo.ControlType = acComboBox Or _ 
      campo.ControlType = acTextBox Then 
      ColecaoForm.Add campo 
     End If 
    Next campo 
End Function 
+0

hi Dee。我做了你告訴我要做的所有更改,但是當我運行代碼時,會顯示運行時錯誤否424,表示在「For Each item In objColecao」行中需要一個對象。 「obj_Utilitario.ColecaoForm(Me.Controls)」不會按預期的方式返回「Set objColecao = obj_Utilitario.ColecaoForm(Me.Controls)」行中的任何集合。爲什麼?請儘可能在代碼中再看一下代碼?乾杯。 –

+0

hi Dee。在進入ColecaoForm函數代碼後,我發現一個沒有用的集合對象。我刪除它,並... bazinga!非常感謝你的幫助。 –

+0

我很樂意提供幫助。 – dee

5

除了大衛的建議,你也可以看看using CallByName

Sub Tester() 

Dim c As New clsTest 

    c.one = 1 
    c.two = "two" 
    c.three = True 

    Debug.Print "Before-----------" 
    Debug.Print CallByName(c, "one", VbGet) 
    Debug.Print CallByName(c, "two", VbGet) 
    Debug.Print CallByName(c, "three", VbGet) 

    CallByName c, "one", VbLet, 10 
    CallByName c, "two", VbLet, "changed" 
    CallByName c, "three", VbLet, False 

    Debug.Print "After-----------" 
    Debug.Print CallByName(c, "one", VbGet) 
    Debug.Print CallByName(c, "two", VbGet) 
    Debug.Print CallByName(c, "three", VbGet) 

End Sub 

另clsTest:

Public one As Long 
Public two As String 
Public three As Boolean 

唯一要注意的是,你仍然不能檢查的直接成員clsTest的實例 - 它必須由表單上的控件名稱驅動。