为了账号安全,请及时绑定邮箱和手机立即绑定

VBA和MS-Access中的Bang表示法和点表示法

VBA和MS-Access中的Bang表示法和点表示法

在仔细阅读我正在记录的应用程序时,我在访问对象属性/方法等过程中遇到了一些爆炸符号示例,在其他地方,它们使用点符号来实现相同的目的。使用一种或另一种有区别或偏好吗?一些简单的谷歌搜索只能显示有关该主题的有限信息,而有些人实际上是在相反的情况下使用它的。也许在某个地方有来自MS的编码标准部分指出了疯狂的方法?
查看完整描述

3 回答

?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

尽管已(以前)接受了该问题的答案,但该爆炸实际上并不是成员或集合访问运算符。它做了一件简单而又具体的事情:bang运算符通过将bang运算符后的文字名称作为字符串参数传递给该默认成员,从而提供对对象默认成员的后期绑定访问。


而已。该对象不必是集合。它不必具有称为的方法或属性Item。它所需要的只是一个Property Get或Function可以接受字符串作为第一个参数的参数。


有关更多详细信息和证明,请参阅我的博客文章讨论:爆炸!VBA中的(感叹号运算符)


查看完整回答
反对 回复 2019-11-02
?
慕的地6264312

TA贡献1817条经验 获得超6个赞

一对陷阱可作为已发布的两个出色答案的补充:


访问表单与报表中

的记录集字段 Access中Form对象的默认项是表单的Controls集合和表单记录集的Fields集合的并集。如果控件的名称与字段的名称冲突,则不确定实际返回哪个对象。由于字段和控件的默认属性都是它们的.Value,因此通常是“无区别的区分”。换句话说,通常不关心它是因为字段和控件的值通常是相同的。


当心命名冲突!

Access的“表单和报表”设计器默认将绑定控件的命名与绑定到的记录集字段的命名相同,从而加剧了这种情况。我个人采用了使用控件类型前缀重命名控件的约定(例如,tbLastName绑定到LastName字段的文本框)。


报表记录集字段不存在!

我之前说过Form对象的默认项是Controls和Fields的集合。但是,报表对象的默认项目只是其控件集合。因此,如果要使用bang运算符引用记录集字段,则需要将该字段包括为绑定控件(如果需要的话)的源。


当心与显式表单/报表属性发生冲突

当将控件添加到表单或报表中时,Access会自动创建引用这些控件的属性。例如,tbLastName通过引用可以从表单的代码模块中获得名为的控件Me.tbLastName。但是,如果Access与现有表单或报表属性冲突,它将不会创建此类属性。例如,假设添加了一个名为Pages的控件。Me.Pages在窗体的代码模块中引用将返回窗体的Pages属性,而不是名为“ Pages”的控件。


在此示例中,可以Me.Controls("Pages")使用bang运算符显式或隐式访问“ Pages”控件Me!Pages。但是请注意,使用bang运算符意味着,如果表单的记录集中存在一个Access字段,则它可能会返回一个名为“ Pages”的字段。


那.Value呢?

尽管未在问题中明确提及,但以上评论中提到了该主题。字段对象和大多数“可数据绑定”¹控件对象的默认属性是.Value。由于这是默认属性,因此通常总是明确地将其包括在内不必要地冗长。因此,这是标准做法:


Dim EmployeeLastName As String

EmployeeLastName = Me.tbLastName

代替:


EmployeeLastName = Me.tbLastName.Value

键入字典时,请注意细微的.Value错误。在

某些情况下,此约定可能会导致细微的错误。我实际上在实践中碰到的最引人注目的(如果只有内存可用的话)是在将“字段/控件”的值用作“字典”键时使用的。


Set EmployeePhoneNums = CreateObject("Scripting.Dictionary")

Me.tbLastName.Value = "Jones"

EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-1234"

Me.tbLastName.Value = "Smith"

EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-6789"

人们可能希望上面的代码在EmployeePhoneNums字典中创建两个条目。而是在最后一行抛出错误,因为我们正在尝试添加重复键。即,tbLastName控件对象本身是键,而不是控件的值。在这种情况下,控件的值甚至无关紧要。


实际上,我希望对象的内存地址(ObjPtr(Me.tbLastName))可能是幕后用来索引字典的内容。我做了一个快速测试,似乎证实了这一点。


'Standard module:

Public testDict As New Scripting.Dictionary

Sub QuickTest()

    Dim key As Variant

    For Each key In testDict.Keys

        Debug.Print ObjPtr(key), testDict.Item(key)

    Next key

End Sub


'Form module:

Private Sub Form_Current()

    testDict(Me.tbLastName) = Me.tbLastName.Value

    Debug.Print ObjPtr(Me.tbLastName); "..."; Me.tbLastName

End Sub

运行上面的代码时,每次关闭并重新打开表单时,都会添加一个词典项。从一个记录移到另一个记录(并因此导致对Form_Current例程的多次调用)不会添加新的词典项,因为它是Control对象本身索引该词典,而不是Control的值。


我的个人建议/编码约定

多年来,我采用了以下做法,即YMMV:


与控制型指标前缀窗体/报表控件名称(如tbTextBox,lblLabel等)

使用Me.符号(例如Me.tbLastName)引用代码中的表单/报表控件

避免创建与表/查询字段有问题的名字摆在首位

Me!发生冲突时(例如,与旧版应用程序(例如Me!Pages))使用符号

包括隐藏的报表控件以访问报表Recordset字段值

.Value仅在情况需要增加详细程度时才明确包括(例如,词典键)

¹ 什么是“数据可绑定”控件?

基本上是具有ControlSource属性的控件,例如TextBox或ComboBox。不可绑定的控件将类似于Label或CommandButton。TextBox和ComboBox的默认属性为.Value; 标签和命令按钮没有默认属性。


查看完整回答
反对 回复 2019-11-02
  • 3 回答
  • 0 关注
  • 563 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信