让VBA类模块的属性 - 是否可以有多个参数?

mat*_*boy 11 oop vba properties class excel-vba

到目前为止,我对在类模块中使用Let属性的理解是你在类模块中设置它,如下所示:

Dim pName as String
Public Property Let Name(Value As String)
    pName = Value
End Property
Run Code Online (Sandbox Code Playgroud)

然后,在您创建了此类的对象之后,您可以像这样设置此属性:

MyObject.Name = "Larry"
Run Code Online (Sandbox Code Playgroud)



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

Dim pFirstName as String, pLastName as String
Public Property Let Name(FirstName As String, LastName As String)
    pFirstName = FirstName
    pLastName = LastName
End Property
Run Code Online (Sandbox Code Playgroud)

那你怎么去在课外设置这个属性呢?

MyObject.Name = ??
Run Code Online (Sandbox Code Playgroud)

或者这是不可能做到的?

小智 14

我意识到已经有2个解决方法,但我认为回答你原来的问题是值得的,因为这个问题收到了大量的意见.

答案

是否可以在VBA中的Let属性中包含多个参数?

是!这是可能的.

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

Private firstName as String
Private lastName as String

Public Property Get Name() As String
    Name = firstName & " " & lastName
End Property
Run Code Online (Sandbox Code Playgroud)

Name属性将返回全名,这很好,但如何使用该Let属性分配firstName&lastName一次性?

旁注:你可以传递一个用特殊字符分隔的单个字符串,然后将其拆分到正文中,Let并分配firstlast名称, 但忘记了,让我们正确地完成它...

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

就像是:

Public Property Let Name(value As String)
    firstName = value
End Property
Run Code Online (Sandbox Code Playgroud)

规则:Get没有参数,Let需要一个参数.这是非常合乎逻辑的,因为Get返回基础值但Let需要从某处获取值以便将其分配给它所代表的数据.值得记住的是,该Let物业是通过=标志分配的.myObject.Name = "IdOnKnuu"

我们知道,如果我们留在上面的一致规律,从理论上我们应该能够一个参数添加到Get一个多向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
Run Code Online (Sandbox Code Playgroud)

回到Module1创建Class1和键入的实例c.Name(

在此输入图像描述

哦,智能期待什么?真棒!

在这一点上,值得理解的是我们的Get属性返回first + last 目前都是空的,所以无论你要传递给c.Name()它的是什么都将返回一个空字符串.

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

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

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

Public Property Let Name(first As String, value As String)
    firstName = value
End Property
Run Code Online (Sandbox Code Playgroud)

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

请记住,您以前如何使用该Let物业?你需要为它分配一个值

c.Name = "John"
Run Code Online (Sandbox Code Playgroud)

但是现在,你的Let财产正在期待一个额外的参数first as String.

我们为什么不这样做:

c.Name("John") = "Smith"
Run Code Online (Sandbox Code Playgroud)

嘿! 编译和运行(快速F5)

太好了,我们来看看结果吧!

Debug.print c.Name("John")
Run Code Online (Sandbox Code Playgroud)

嗯...只Smith在立即窗口显示(Ctrl+ G)......不完全是我们要找的......

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

Public Property Let Name(first As String, last As String)
    firstName = first
    lastName = last
End Property
Run Code Online (Sandbox Code Playgroud)

回去吧 Module1

Sub Main()

    Dim c As New Class1

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

    Debug.Print c.Name("John")

End Sub
Run Code Online (Sandbox Code Playgroud)

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

哈!这样做的诀窍是制作两个属性的第一个参数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
Run Code Online (Sandbox Code Playgroud)

Module1.bas

Sub Main()

    Dim c As New Class1

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

    Debug.Print c.Name ' prints John Smith

End Sub
Run Code Online (Sandbox Code Playgroud)

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

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

电话

Debug.Print c.Name("first")
Run Code Online (Sandbox Code Playgroud)

仍然可能,但"first"参数只是像假的一样,对实际的底层数据没有影响.它是一个虚拟对实际数据没有影响 - 转储并使用:

Debug.print c.Name
Run Code Online (Sandbox Code Playgroud)

绝对更方便:)


InC*_*ext 8

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

下面包括子和功能.该函数返回一个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
Run Code Online (Sandbox Code Playgroud)

人员类:

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
Run Code Online (Sandbox Code Playgroud)