【问题标题】:vba Class Property Values, setting default values, storing values to stringvba 类属性值,设置默认值,将值存储到字符串
【发布时间】:2023-03-17 16:22:01
【问题描述】:

这里是另一个难过的新手,试图解决一个问题。

我正在尝试使用具有属性获取和设置的类模块,而不是公共变量。 我想在带有文本框的用户窗体中设置这些值,并在输入时更新用户窗体中的列表框,最好是在文本框事件_afterupdate上, 当用户点击保存按钮时,我希望将配置文件属性存储到一个范围内。 毫无疑问,这将是一个可笑的烂摊子,但我已经被难住了好几天了,我要带着帽子来到这里。我就是想不通。

类 Mod 示例:


Private mProfileName As String
Private mStartDate As Date
Private mEndDate As Date
Private mOngoing As Boolean


Sub Class_Initialise()
'Set default values for properties
             
 mLastName = "Enter Last Name"
 mStartDate = "Enter Date"
 mEndDate = Date
 mOngoing = True
End Sub
'********************************
'The relevant property procedures:
'********************************
Property Get ProfileName() As String
    ProfileName = mProfileName
End Property

Property Let ProfileName(Value As String)   
    mProfileName = Value
End Property

Property Get EndDate() As Date
    EndDate = mEndDate
End Property

Property Let EndDate (Value As Date)    
        mEndDate = Value    
End Property 

Property Get Ongoing() As Boolean
       Ongoing = mOngoing
End Property

Property Let Ongoing(Value As Boolean)

    If mEndDate = Date Then
    mOngoing = True    
    End If

End Property

在我目前拥有的用户表单中:

Option Explicit
'hopefully not needed:
'Private mTextBoxUpdated As Boolean
'Private mListBoxUpdated As Boolean
'Private mEnteredText As String
'Private mIndexText As String

Private DictThisForm As Dictionary
Private ProfileData As clsProfileData
Private Sub UserForm_Initialize()


    Debug.Print "UserForm Intialised"
    Set DictThisForm = New Dictionary
    Debug.Print "DictThisForm Created"
    Set ProfileData = New clsProfileData
   
    Call UserForm_UpdateListBox

还有这个可笑的烂摊子:(甚至还没有接近工作)

Sub UserForm_UpdateListBox()
 
    With lbxListBox1
        .Clear
        .ColumnCount = 2
        
        .AddItem
        '.List(0, 1) = "Profile Name",ProfileData.ProfileName ' 
         'another attempt
        'the below throws a Type Mismatch Error
        .AddItem ProfileData.ProfileName, "Profile Name"
        .AddItem ProfileData.StartDate, "Start Date"
        .AddItem ProfileData.EndDate, "End Date"
        .AddItem ProfileData.OnGoing, "Ongoing?"
  

And(带有私有声明的模块级变量)

Private Sub tbxProfileName_AfterUpdate()
 
    ProfileData.FirstName = tbxProfileName.Text
    enter code here
    Call UserForm_UpdateListBox

End Sub

目前我只是在尝试测试类模块,看看我是否可以将属性值放入变量中,或者更好的是,将这些属性值放入隐藏页面上的范围中,可能是通过字典,并且从那里更新列表?将属性值放入列表框似乎很麻烦......

Sub testClassProfile()

    Dim getPropertyAsStringVar As String
    Dim NewProfile As clsProfileData

    Set NewProfile = New clsProfileData
    getPropertyAsStringVar = NewProfile.FirstName
    Debug.Print getPropertyAsStringVar

End Sub

当前 Debug.Print 输出为“”,即 zip。没有默认值。

非常感谢任何建议。 如果我一次问太多,请告诉我,我会尝试将问题的范围缩小到我当前的问题,我认为上下文可能会有所帮助......

【问题讨论】:

  • 发布一个完整(但可能更小)的示例类可能会更好 - 即。一些我们可以运行的代码。只需要完整的课程和最后一个测试子。
  • 欢迎来到 StackOverflow。作为猜测,这可能是一个实例问题。在您的Sub TestClassProfile 中,您创建一个clsProfileData 的实例。但我怀疑你没有将它传递给你要填充的用户窗体。在那里,您正在创建该类的单独实例。尝试将外部创建的实例传递给用户表单。
  • 嘿伙计们,感谢您的意见...@TimWilliams 如果将上面的两个粘贴到一个类 mod 中,它们应该运行吗?我应该把它们做成一个单元吗?
  • @ainwood 我实际上是在尝试尽可能多地从另一个模块运行用户窗体,这只是暂时的,看看我是否可以将属性值添加到列表框中,但我没有t认为代码甚至是正确的,或者列表框不接受这样的类属性值?但是我对如何传递“clsProfileData”的实例非常感兴趣——不过,这掩盖了我的无知,我认为一个类实例及其属性最终将是全局可用的?但我调暗新的部分原因也是为了让我可以访问智能感知......
  • 自定义类不会“自动实例化”——您需要先创建一个实例才能使用它。没有仅通过存在类模块而创建的全局可访问实例。可能值得略读其中涵盖在 VBA 中使用自定义类的众多指南。

标签: vba class variables userform listboxitem


【解决方案1】:

不是真正的“答案”,但用另一个评论来回应你的评论太难了!

这是一个如何将类传递给用户窗体的示例。可能有帮助!

TestModule 代码

Option Explicit
Public Sub test()
'//Basic declaration of a UserForm
Dim testUF As UserForm1
Set testUF = New UserForm1

'//Now we create a test class - see the Property Get/Set for the string.
Dim testC1 As Class1
Set testC1 = New Class1
testC1.TestString = "Hello"

'//In the UserForm, I've created a property that accepts a class.  Assign the 
"TestClass" instance tothe UserForm Instance
testUF.Class1 = testC1
testUF.Show
End Sub

...这是用户表单。请注意我添加的用于接受类实例的属性。

Option Explicit

Private classInstance As Class1
Public Property Get Class1() As Variant
    Set Class1 = classInstance
End Property

Public Property Let Class1(ByVal vNewValue As Variant)
    Set classInstance = vNewValue
End Property

Private Sub UserForm_Click()
    Me.Caption = classInstance.TestString
End Sub

还有班级:

Option Explicit
Private mtest As String
Public Property Get TestString() As String
    TestString = mtest
End Property

Public Property Let TestString(ByVal vNewValue As String)
    mtest = vNewValue
End Property

当您运行“测试”代码时,您将看到创建了一个类和一个用户窗体(实际上也只是一个“类”)的实例,并将一个实例传递给另一个实例。它(在幕后)“通过引用”传递,因此对用户窗体中的 TestCl 所做的任何更改都将保留在类之外,允许用户窗体对其进行修改,然后返回控制代码以供以后使用.

【讨论】:

  • 哇,谢谢。我会将所有这些放在一个新的工作簿中,并观察它如何运行以尝试更好地掌握......看起来你只是将它传递给用户表单中的一个属性......我不知道类实例可以有其他类实例作为属性!那是一些初始类型的疯狂!我只是抓住它。非常感谢您的帮助。
【解决方案2】:

Initialize 方法的签名是

Private Sub Class_Initialize()

...这不是您所拥有的,因此在创建基于类的对象时它不会运行。为了确保它是正确的,在你的类代码模块中,从顶部的左侧下拉列表中选择“类”,然后从右侧选择中选择所需的方法。

编辑:这看起来不对 -

Property Get Ongoing() As Boolean
       Ongoing = mOngoing
End Property

Property Let Ongoing(Value As Boolean)
    If mEndDate = Date Then
        mOngoing = True    
    End If
End Property

Ongoing 属性实际上并不依赖于支持字段或需要设置(因为它的值仅取决于 mEndDate,因此您可以删除 Let 并使用 Get 之类的东西这-

Property Get Ongoing() As Boolean
       Ongoing = (mEndDate  <= Date)
End Property

【讨论】:

  • 是的,可以修复它.... 太棒了,我可以使用类实例来更新列表框吗?比如:.AddItem: NewProfileData.Property, "property" 或者我需要先将它传递给一个变量吗?
猜你喜欢
  • 2011-07-06
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
相关资源
最近更新 更多