VBA 中的动态属性名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4804947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamic property names in VBA
提问by poke
I have a custom class module in VBA (Access) that is supposed to handle a large amount of external data. Currently I have two functions Read(name)
and Write(name, value)
that allows to read and set dynamic properties.
我在 VBA (Access) 中有一个自定义类模块,它应该处理大量外部数据。目前我有两个功能Read(name)
,并Write(name, value)
允许读取和设置动态特性。
Is there a way to define a more syntactic way to read and write those data? I know that some objects in VBA have a special way of accessing data, for example the RecordSet
, which allows to read and set data using myRS!property_name
. Is there a way to do exactly the same for custom class modules?
有没有办法定义一种更语法的方式来读取和写入这些数据?我知道 VBA 中的某些对象具有访问数据的特殊方式,例如RecordSet
,它允许使用myRS!property_name
. 有没有办法对自定义类模块做完全相同的事情?
采纳答案by poke
Okay, thanks to Alain and KyleNZ I have now found a working way to do this, without having a collection or enumerable object below.
好的,多亏了 Alain 和 KyleNZ,我现在找到了一种可行的方法来做到这一点,而无需下面的集合或可枚举对象。
Basically, thanks to the name of the ! operator, I found out, that access via the bang/pling operator is equivalent to accessing the default member of an object. If the property Value
is the default member of my class module, then there are three equivalent statements to access that property:
基本上,这要归功于 ! 我发现,通过 bang/pling 操作符访问相当于访问对象的默认成员。如果属性Value
是我的类模块的默认成员,那么有三个等效的语句来访问该属性:
obj.Value("param")
obj("param")
obj!param
So to make a short syntax working for a custom class module, all one has to do is to define a default member. For example, I now used the following Value
property:
因此,要为自定义类模块创建一个简短的语法,您所要做的就是定义一个默认成员。例如,我现在使用了以下Value
属性:
Property Get Value(name As String) As String
Value = SomeLookupInMyXMLDocument(name)
End Property
Property Let Value(name As String, val As String) As String
SetSomeNodeValueInMyXMLDocument(name, val)
End Property
Normally, you could now access that like this:
通常,您现在可以像这样访问它:
obj.Value("foo") = "New value"
MsgBox obj.Value("foo")
Now to make that property the default member, you have to add a line to the Property definition:
现在要使该属性成为默认成员,您必须在属性定义中添加一行:
Attribute Value.VB_UserMemId = 0
So, I end up with this:
所以,我最终得到了这个:
Property Get Value(name As String) As String
Attribute Value.VB_UserMemId = 0
Value = SomeLookupInMyXMLDocument(name)
End Property
Property Let Value(name As String, val As String) As String
Attribute Value.VB_UserMemId = 0
SetSomeNodeValueInMyXMLDocument(name, val)
End Property
And after that, this works and equivalent to the code shown above:
之后,这将起作用并等效于上面显示的代码:
obj("foo") = "New value"
MsgBox obj("foo")
' As well as
obj!foo = "New value"
MsgBox obj!foo
' Or for more complex `name` entries (i.e. with invalid identifier symbols)
obj![foo] = "New value"
MsgBox obj![foo]
Note that you have to add the Attribute Value.VB_UserMemId = 0
in some other editor than the VBA editor that ships with Microsoft Office, as that one hides Attribute
directives for some reason.. You can easily export the module, open it in notepad, add the directives, and import it back in the VBA editor. As long as you don't change too much with the default member, the directive should not be removed (just make sure you check from time to time in an external editor).
请注意,您必须Attribute Value.VB_UserMemId = 0
在 Microsoft Office 附带的 VBA 编辑器之外的其他编辑器中Attribute
添加回到 VBA 编辑器。只要您不对默认成员进行太多更改,就不应删除该指令(只需确保不时在外部编辑器中进行检查)。
回答by KyleNZ
The exclamation mark syntax is used to access members of a Scripting.Dictionary
instance(you'll need to add a reference to Microsoft Scripting Runtime
through Tools > References first). To use this syntaxyou'll need to be storing the information internally in a dictionary.
感叹号语法用于访问Scripting.Dictionary
实例的成员(您需要先Microsoft Scripting Runtime
通过 Tools > References添加一个引用)。要使用此语法,您需要将信息内部存储在字典中。
The quickest way to use it in a class is to give your class an object variable of type Scripting.Dictionary
and set it up as follows:
在类中使用它的最快方法是为您的类提供一个类型为对象的变量Scripting.Dictionary
并将其设置如下:
Option Explicit
Dim d As Scripting.Dictionary
Private Sub Class_Initialize()
Set d = New Scripting.Dictionary
End Sub
Private Sub Class_Terminate()
Set d = Nothing
End Sub
Public Property Get IntData() As Scripting.Dictionary
Set IntData = d
End Property
Now you can access properties using myinstance.IntData!MyProperty = 1
... but to get to where you want to be you need to use Charlie Pearson's techniquefor making IntData
the default member for your class.
现在您可以使用myinstance.IntData!MyProperty = 1
...访问属性,但要到达您想要的位置,您需要使用Charlie Pearson 的技术IntData
为您的类创建默认成员。
Once that's done, you can use the following syntax:
完成后,您可以使用以下语法:
Dim m As MyClass
Set m = New MyClass
Debug.Print "Age = " & m!Age ' prints: Age =
m!Age = 27
Debug.Print "Age = " & m!Age ' prints: Age = 27
Set m = Nothing
回答by Alain
See this other question: Bang Notation and Dot Notation in VBA and MS-Access
看到另一个问题:Bang Notation and Dot Notation in VBA and MS-Access
The bang operator (!) is shorthand for accessing members of a Collection or other enumerable object
bang 运算符 (!) 是访问 Collection 成员或其他可枚举对象的简写
If you make your class extend the Collection class in VBA then you should be able to take advantage of those operators. In the following question is an example of a user who extended the collection class: Extend Collections Class VBA
如果您让您的类扩展 VBA 中的 Collection 类,那么您应该能够利用这些运算符。下面的问题是一个用户扩展集合类的例子: 扩展集合类 VBA