3 回答

TA貢獻1875條經驗 獲得超5個贊
盡管已(以前)接受了該問題的答案,但該爆炸實際上并不是成員或集合訪問運算符。它做了一件簡單而又具體的事情:bang運算符通過將bang運算符后的文字名稱作為字符串參數傳遞給該默認成員,從而提供對對象默認成員的后期綁定訪問。
而已。該對象不必是集合。它不必具有稱為的方法或屬性Item。它所需要的只是一個Property Get或Function可以接受字符串作為第一個參數的參數。
有關更多詳細信息和證明,請參閱我的博客文章討論:爆炸!VBA中的(感嘆號運算符)

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呢?
盡管未在問題中明確提及,但以上評論中提到了該主題。字段對象和大多數“可數據綁定”1控件對象的默認屬性是.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僅在情況需要增加詳細程度時才明確包括(例如,詞典鍵)
1 什么是“數據可綁定”控件?
基本上是具有ControlSource屬性的控件,例如TextBox或ComboBox。不可綁定的控件將類似于Label或CommandButton。TextBox和ComboBox的默認屬性為.Value; 標簽和命令按鈕沒有默認屬性。
添加回答
舉報