I am new to MsAccess looking through the code and noticed that some lines of code use Ме.btn_X.SetFocus and some Ме!formA ? What is the difference?

    2 answers 2

    An exclamation point is used to separate the collection name and the collection element name.

    A dot is used to separate the name of an object and the name of its property or method.

    Since the collection is an object, for those collections in which the element name is a key, it is permissible to refer to the collection element using as a separator both a dot and an exclamation mark.

    That is, the CollectionName! MemberName and CollectionName.ItemsProperty ("MemberName") entries are equivalent.

    Although it is better to try to use strict syntax.

    From the original message - the following options are equivalent (provided that btn_X is the name of the class instance, and not the name of the class):

     Ме.btn_X.SetFocus Ме!btn_X.SetFocus Ме.Controls("btn_X").SetFocus 

    However, if btn_X is the name of a class, then calling its method does not make sense (provided that SetFocus is the name of the method, and not a strangely named property, of course).

    • Something is doubtful ... - Qwertiy
    • Hmmm ... and for what reason, let me ask? - Akina
    • Understand why it is doubtful. Because the form (and Me is a link to the form) is not a collection, probably. But here there are features of the implementation from Microsoft - a link to the object at the same time there is a link to the property of this object by default, and for the Default Value form this is its Controls collection. - Akina
    • No, it is doubtful due to the fact that your answer does not say that ! and - these are fundamentally different concepts. Rather, he says the opposite. - Qwertiy
    • Added to your answer about the form. - Qwertiy

    In VB there is such a thing as a default property. It cannot be added to the VBA editor, but you can import the class in which it is written. This property is remarkable in that it is implicitly called when using an object not as an object (that is, in assignments without a Set , or in circulation through parentheses). The exclamation mark serves as syntactic sugar to pass a string argument to this property.


    Import the following class:

     VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "Magic" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Public Property Get Value() As String Value = "`Value` is accessed via dot" End Property Public Property Get Smth(Optional Key As String = "none") As String Attribute Smth.VB_UserMemId = 0 Smth = "`Smth` is accessed with `" & Key & "` argument" End Property Public Function Go() Debug.Print Me.Value Debug.Print Me.Smth("Any") Debug.Print Me!Any Debug.Print Me("Any") Debug.Print Me!Value Debug.Print Me("Value") Debug.Print Me.Smth Debug.Print Me!Smth Debug.Print Me("Smth") Debug.Print Me End Function 

    and use it from the macro:

     Public Sub Test() Dim Obj As Magic Set Obj = New Magic Obj.Go Dim Var As String Var = Obj ' No `Set` here Debug.Print Var Debug.Print Obj![With a space] Debug.Print Obj("With a space") End Sub 

    And that's what happens:

     `Value` is accessed via dot `Smth` is accessed with `Any` argument `Smth` is accessed with `Any` argument `Smth` is accessed with `Any` argument `Smth` is accessed with `Value` argument `Smth` is accessed with `Value` argument `Smth` is accessed with `none` argument `Smth` is accessed with `Smth` argument `Smth` is accessed with `Smth` argument `Smth` is accessed with `none` argument `Smth` is accessed with `none` argument `Smth` is accessed with `With a space` argument `Smth` is accessed with `With a space` argument 

    Or, if to sort in the lines:

     Debug.Print Me.Value ' `Value` is accessed via dot Debug.Print Me.Smth("Any") ' `Smth` is accessed with `Any` argument Debug.Print Me!Any ' `Smth` is accessed with `Any` argument Debug.Print Me("Any") ' `Smth` is accessed with `Any` argument Debug.Print Me!Value ' `Smth` is accessed with `Value` argument Debug.Print Me("Value") ' `Smth` is accessed with `Value` argument Debug.Print Me.Smth ' `Smth` is accessed with `none` argument Debug.Print Me!Smth ' `Smth` is accessed with `Smth` argument Debug.Print Me("Smth") ' `Smth` is accessed with `Smth` argument Debug.Print Me ' `Smth` is accessed with `none` argument 

    none used because the Optional Key As String = "none" argument is Optional Key As String = "none" when referring to the Smth property.

    In the last example, we use Me not as an object, therefore, Smth also Smth without passing a parameter. The same situation occurs in

     Var = Obj ' No `Set` here ' `Smth` is accessed with `none` argument Debug.Print Var 

    that is, we can access the default property not only from inside the object, but also simply having the corresponding object in the variable. Here it would be possible to do everything that was done in Go only with Obj instead of Me , but I did not copy and paste.

    As I said ! It serves as syntactic sugar for passing a string argument to a differential property. At the same time, a restriction is imposed that the string being passed must be a valid identifier. However, square brackets deserve special mention, allowing you to use anything you like as an identifier:

     Debug.Print Obj![With a space] `Smth` is accessed with `With a space` argument Debug.Print Obj("With a space") `Smth` is accessed with `With a space` argument 

    Most built-in collections have a default property that allows access to the elements of the collection by key.

    In the case of the form, there is another feature - all controls created in the designer are declared WithEvents properties, which allows you to access them through a dot (well, or just by name). But at the same time, its default value is Controls , which, by the key, namely the name of the control, is provided by the control itself. So in the case of controls, it turns out that they can be accessed in two ways (more precisely, only to those that are created in the form designer; to the dynamic one, only through ! ). I note that addressing through a dot is more efficient.


    PS: It will be similar to assignment if you write the corresponding code.