让 VBA 类模块的属性 - 是不是可以有多个参数? [复制]

Posted

技术标签:

【中文标题】让 VBA 类模块的属性 - 是不是可以有多个参数? [复制]【英文标题】:Let property of VBA class modules - is it possible to have multiple arguments? [duplicate]让 VBA 类模块的属性 - 是否可以有多个参数? [复制] 【发布时间】:2012-11-29 04:33:00 【问题描述】:

到目前为止,我对在类模块中使用 Let 属性的理解是,您可以像这样在类模块中设置它:

Dim pName as String
Public Property Let Name(Value As String)
    pName = Value
End Property

然后你在你创建了这个类的一个对象之后你可以像这样设置这个属性:

MyObject.Name = "Larry"

问题:是否有可能以某种方式将多个参数输入到类属性中?例如:

Dim pFirstName as String, pLastName as String
Public Property Let Name(FirstName As String, LastName As String)
    pFirstName = FirstName
    pLastName = LastName
End Property

然后您将如何在课堂外设置此属性?

MyObject.Name = ??

或者这根本不可能做到?

【问题讨论】:

单个属性不能有两个参数,但可以使用数组。在这种情况下,最好使用像 SetName(first,last) 这样的常规 Sub 谢谢。您确定可以使用数组吗?尝试时,我不断收到“无法分配给数组”错误。 @mattboy - 我已经添加到我的答案中,向您展示如何使用您需要的数据返回或更复杂的对象。 @TimWilliams take your comment back ;) @vba4all - 总是乐于学习新事物... 【参考方案1】:

根据您的评论,如果您希望封装此逻辑,则可以使用类似于以下内容的内容。

下面包括子和函数。该函数返回一个 Person 对象:

Public Sub testing()

    Dim t As Person

    Set t = PersonData("John", "Smith")

End Sub


Public Function PersonData(firstName As String, lastName As String) As Person

    Dim p As New Person

    p.firstName = firstName
    p.lastName = lastName

    Set PersonData = p

End Function

人物类:

Dim pFirstName As String, pLastName As String

Public Property Let FirstName(FirstName As String)
    pFirstName = FirstName
End Property

Public Property Get FirstName() As String
    FirstName = pFirstName
End Property

Public Property Let LastName(LastName As String)
    pLastName = LastName
End Property

Public Property Get LastName() As String
    LastName = pLastName
End Property

【讨论】:

谢谢,但我希望有一种方法可以在创建对象时将所有内容设置在一行中,而不是将一行用于名字,一行用于姓氏,其他行用于可能需要的任何其他内容。但我想你只需要创建一个 Sub 而不是 Property 就可以做到这一点。 查看我的编辑。我认为调用返回 Person 类而不是子类的函数更好。您对字段及其强类型具有智能感知。【参考方案2】:

在类中用作 Public Sub 过程来执行此操作:

Public Sub testing()
Dim myPerson As New Person
myPerson.SetName "KaciRee", "Software"

End Sub

人物类:

Dim pFirstName As String, pLastName As String

Public Property Let FirstName(FirstName As String)
    pFirstName = FirstName
End Property

Public Property Get FirstName() As String
    FirstName = pFirstName
End Property

Public Property Let LastName(LastName As String)
    pLastName = LastName
End Property

Public Property Get LastName() As String
    LastName = pLastName
End Property

Public Sub SetName(FirstName As String, LastName As String)
pFirstName = FirstName
pLastName = LastName
End Sub

【讨论】:

【参考方案3】:

我意识到已经有 2 种解决方法,但我认为回答您的原始问题值得一试,因为该问题收到的浏览量很大。

答案

VBA 的 Let 属性中是否可以有多个参数?

是的!这是可能的。

首先让我们谈谈 GET 属性。考虑这是Class1

Private firstName as String
Private lastName as String

Public Property Get Name() As String
    Name = firstName & " " & lastName
End Property

Name 属性将返回 全名,这很好,但是如何使用 Let 属性将 firstNamelastName 分配到一个去吗?

旁注:您可以传递一个用特殊字符分隔的单个字符串,并将其拆分到 Let 的正文中,并分配 firstlast 名称 但是忘记那个,让我们把它做好......

好的,在 VBA 中,当前设置的默认 Let 属性将采用 1 个参数并将其分配给名字或姓氏...

类似:

Public Property Let Name(value As String)
    firstName = value
End Property

规则:Get 不带参数,Let 带一个。这是非常合乎逻辑的,因为 Get 返回基础值,但 Let 需要从 somewhere 获取一个值,以便将其分配给它所代表的数据。此时值得记住的是,Let 属性是通过= 符号分配的,即。 myObject.Name = "IdOnKnuu"

我们知道,如果我们与上述规则保持一致,理论上我们应该可以add one parameter to the Get和one more to the Let

让我们忘记Let - 现在将其注释掉 - 并为Get 属性添加一个参数。

Private firstName As String
Private lastName As String

Public Property Get Name(first As String) As String
    Name = firstName & " " & lastName
End Property

'Public Property Let Name(value As String)
'    firstName = value
'End Property

回到Module1 创建Class1 的实例并输入c.Name(

哦,智能感知期待什么?太棒了!

此时值得理解的是,我们的 Get 属性返回 first + last 此时它们都是空的,所以你将传递给 @987654353 并不重要@ 它会返回一个空字符串。

好的,我们现在取消注释并调整 Let 属性...

侧节点:如果您跳回Module1 并输入c. 并且没有得到智能感知,这几乎意味着Class1 中的某些东西被破坏了......我们已经知道 - 它是导致它的 Let 属性

我们已经为Get 属性添加了一个参数,让我们对Let 属性做同样的事情...

Public Property Let Name(first As String, value As String)
    firstName = value
End Property

让我们回到Module1 并尝试使用Let 属性:

记住,您之前是如何使用Let 属性的?你需要给它赋值

c.Name = "John"

但是现在,您的 Let 属性需要一个额外的参数 first as String

我们为什么不试试这个:

c.Name("John") = "Smith"

嘿!编译和运行(快速 F5

太好了,让我们检查一下结果!

Debug.print c.Name("John")

嗯...仅在即时窗口中显示Smith (Ctrl+G)...不完全是我们想要的...。

回到Let 属性,我们注意到我们通过参数获取了2 个值,但我们只使用了其中一个?我们有两个不同的值进入函数,对吧?让我们将第一个视为firstName,将第二个视为lastName

Public Property Let Name(first As String, last As String)
    firstName = first
    lastName = last
End Property

回到Module1

Sub Main()

    Dim c As New Class1
    
    c.Name("John") = "Smith"

    Debug.Print c.Name("John")
    
End Sub

并重新运行当前代码为我们提供了我们需要的东西......它会打印 John Smith等待!!!为什么我们必须传递名字才能检索全名

哈!这样做的诀窍是使两个属性的第一个参数Optional

总结一下,代码:

Class1.cls

Private firstName As String
Private lastName As String

Public Property Get Name(Optional first As String) As String
    Name = firstName & " " & lastName
End Property

Public Property Let Name(Optional first As String, last As String)
    firstName = first
    lastName = last
End Property

Module1.bas

Sub Main()

    Dim c As New Class1
    
    c.Name("John") = "Smith"

    Debug.Print c.Name ' prints John Smith
    
End Sub

所以基本上可以在 VBA 中通过 Let 属性分配两个(或更多)值。可能会让你有点失望的是它的语法,但我希望我在这个答案中的解释能帮助你理解事情的来源和原因。

Get 属性带有一个可选参数 - 它实际上只是一个虚拟参数...它没有在Get 属性中的任何地方使用,但它允许我们获得所需的Let 签名并允许我们向其传递两个参数。它还提供易于记忆的c.Name 语法。

电话

Debug.Print c.Name("first")

仍然是可能的,但是"first" 参数就像一个假人,对实际的基础数据没有影响。这是一个假数据,对实际数据没有影响 - 转储它并使用:

Debug.print c.Name

肯定更方便:)

【讨论】:

对于暴露数组也很有用。

以上是关于让 VBA 类模块的属性 - 是不是可以有多个参数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

VBA:是不是可以创建一个行为类似于集合的类模块?

VBA的基础知识

请问,编程语言中,(VB或者说VBA,),宏是啥概念啊?宏做出来一个是类模块,但是类模块

通过模块 [VBA] 获取表单字段值

VBA 中的动态属性名称

如何在VBA中确定选择上方的标题-X样式标题?