11

下面是一个我自己回答的问题,但是它给我带来了很大的挫败感,我在网上搜索它时遇到了很多麻烦,所以我在这里发帖希望为其他人节省一些时间和精力,如果我将来忘记这一点,也许对我自己来说:

对于 VBA(在我的情况下,MS Excel),Public声明应该使该模块中的其他函数或子例程以及在任何其他模块。

事实证明这不是真的,在 , 的情况下Forms
,我也怀疑在Sheets,但我没有验证后者。

简而言之,以下内容在创建时不会创建公共的、可访问的变量Form,因此会崩溃,说 bYesNo 和 dRate 变量在 mModule1 中未定义:

(inside fMyForm)
Public bYesNo As Boolean`
Public dRate As Double

Private Sub SetVals()
    bYesNo = Me.cbShouldIHaveADrink.value
    dRate = CDec(Me.tbHowManyPerHour.value)
End Sub
(Presume the textbox & checkbox are defined in the form)

(inside mModule1)
Private Sub PrintVals()
    Debug.Print CStr(bYesNo)
    Debug.Print CStr(dRate)
End Sub


但是,如果您在下面进行轻微更改,一切都会正常工作:

(inside fMyForm)

Private Sub SetVals()
    bYesNo = Me.cbShouldIHaveADrink.value
    dRate = CDec(Me.tbHowManyPerHour.value)
End Sub
(Presume the textbox & checkbox are defined in the form)

(inside mModule1)
Public bYesNo As Boolean`
Public dRate As Double
Private Sub PrintVals()
    Debug.Print CStr(bYesNo)
    Debug.Print CStr(dRate)
End Sub


mModule1将工作得很好,并且假设总是首先调用 fMyForm,然后在PrintVals运行例程时,将正确捕获表单中文本框和复选框的值。

老实说,我无法理解 MS 对这种变化的想法,但缺乏一致性会极大地降低效率,学习这样的特质,这些特质的记录非常差,以至于 2013 年的谷歌搜索可能已经存在一段时间了十年或更长时间的搜索是如此具有挑战性。

4

2 回答 2

4

第一条评论:

Userform 和 Sheet 模块是 Object 模块:它们的行为方式与常规模块不同。但是,您可以以与引用类属性类似的方式引用用户窗体中的变量。在您提到 fMyForm.bYesNo 的示例中可以正常工作。如果您没有将bYesNo 声明为Public,那么表单外部的代码将看不到它,因此当您将其设为Public 时,它确实与非Public 不同。——蒂姆·威廉姆斯 2013 年 4 月 11 日 21:39

其实是正确答案...

于 2015-11-30T15:03:19.380 回答
1

作为社区答案的快速附加答案,仅供参考:

当您实例化您的表单时,您可以使用表单对象本身,或者您可以通过使用 New 并将其放入变量中来创建表单对象的新实例。后一种方法更清洁 IMO,因为这使得使用更少单例。

但是,当您在用户窗体中调用 Unload(Me) 时,所有公共成员都将被清除。所以,如果你的代码是这样的:

  Dim oForm as frmWhatever
  Set oForm = New frmWhatever
  Call oForm.Show(vbModal)
  If Not oForm.bCancelled Then  ' <- poof - bCancelled is wiped clean at this point

我用来防止这种情况的解决方案,它也是 OP 的一个很好的替代解决方案,是将所有带有表单的 IO(即所有公共成员)捕获到一个单独的类中,并使用该类的实例与表格。所以,例如

  Dim oFormResult As CWhateverResult
  Set oFormResult = New CWhateverResult
  Dim oForm as frmWhatever
  Set oForm = New frmWhatever
  Call oForm.Initialize(oFormResult)
  Call oForm.Show(vbModal)
  If Not oFormResult.bCancelled Then  ' <- safe
于 2016-01-18T10:03:09.773 回答