Lets Kill the Me. vs Me! sticky or lets rewrite it

Get Rid or Replace Current Me. vs ME! Sticky

  • Yes

    Votes: 8 100.0%
  • No

    Votes: 0 0.0%

  • Total voters
    8

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:15
Joined
May 21, 2018
Messages
9,012
This discussion moved to clean thread
 
Last edited:
This should be good... I cant vote because I cannot argue on way or the other. I use the "spaghetti" method with the bang and dot. If it works, then I guessed right...if it doesn't I use the other.
 
Not sure a sticky is needed at all but if it is as bad as you indicate, then misinformation is worse than no information at all and it should be taken down. I personally refer to this when I need to direct someone else to an explanation. What that page seems to lack is that the use of ! will also 'disable' intellisense, otherwise it seems to be pretty much what you're saying. The wording of your summation statement is slightly different but I think it means the same thing.
 
[QUOTE I use the "spaghetti" method with the bang and dot. If it works, then I guessed right...if it doesn't I use the other. ][/QUOTE]
@NauticalGent You are hurting my feelings. I was hoping my explanation was simple and clear so you would not have to guess.

But bottom line.
There is no reason to ever use bang in a Form or report. There is no shorthand gained and no advantages.
me.SomeControl is as easy to write as Me!SomeControl
But the first one gains the advantage of, if you messed up and SomeControl and it is really SomeCntrl it will fail at compile time vice run time.

The only place in Access VBA where I think using bang makes sense is in a recordset
RS!FieldName
is easier to write than
RS.Fields("FieldName")

In expressions and queries you need bang and bang only.
 
Well, I tried to read the sticky but there's so much crap and posturing in it that it should be deleted.
 
I need to direct someone else to an explanation
I personally would never direct anyone to that. There are disputes and both parties are just wrong. Nothing on the first page is correct. However, if you dig through the garbage there are posts that correctly describe the intellisense. So that is good.
 
There is nothing on the page that is correct? What is wrong with this statement?
The bang operator provides late-bound access to the default member of an object, by passing the literal name following the bang operator as a string argument to that default member.
Seems pretty much the same as your statement to me.
 
Well, I tried to read the sticky but there's so much crap and posturing in it that it should be deleted
Yeah but the part that bothers me is that both parties are completely wrong. It is like watching my wife and daughter argue, and both make no sense. Then they try to get me involved, and I am like Ugh.....
 
There is nothing on the page that is correct? What is wrong with this statement?
Let me rephrase that. There are in fact correct statements, but not complete statements. But definitely nothing is wrong with that statement because I said it.

An example is there are quotes
Me! works with objects
That is true but not complete. Leads you to believe you can use ! with all object references. Works only with some objects.
Those objects have to be the default property and that property has to be a collection
 
FWIW, I voted in favor of replacement, MajP
 
@MajP: Thank you for compiling this info. You're doing some really great work off lately!

3. Do I need to use Me! in vba: In vba absolutely never. There is not place where it is required, it can be used in vba because it is short hand.
You need to use it if you refer to the control of a field that is only added at runtime to prevent compile errors. (see below for further explanation.)
- I discourage this approach and would rather add an explicit, "real" control for that purpose.

6. The one Exception: As stated the bang only works with the default member of a class. However if I have a field on a form that is not a control I can do
Me!FieldName
This is not an exception.
The special situation is: Access automatically adds a control of type AccessField to the Controls collection of a form for each field in the current data source that does not have a "real" control of the same name already. (- This is done whenever the Recordsource of the Form changes. However, historically this did not work reliably in older Access Versions. In current versions (Access 2016+) I haven't found a situation where this would fail reproducibly.)

These "auto-controls" are not included in Controls.Count, but you can also reference them using Me.Controls("FieldName").

Conclusion: Your statement in this regard is correct. However, I would not label it as an exception because, regarding Bang vs. Dot, it just works exactly the same as all the other scenarios and is not an exception at all.
Nevertheless, it is worth mentioning this particular situation because it is contributing to the many misconceptions about Bang vs. Dot.


PS: Sorry, for many edits after posting. I accidentally hit some keyboard shortcut that instantly posted this before it was complete.
 
Last edited:
@sonic8. I added your information about the fields on the form. Can you better explain adding a control at runtime? Are you talking opening a form in design view via code and editing?
 
Off topic, but MajP, I actually thought that was a real pic of you. My first thought was that I would never post a pic of myself if I looked like that!

But then I realized it was Les Grossman (Tom Cruise) from Tropic Thunder! Too funny...
 
Off topic, but MajP, I actually thought that was a real pic of you. My first thought was that I would never post a pic of myself if I looked like that!
But then I realized it was Les Grossman (Tom Cruise) from Tropic Thunder! Too funny...
Someone else thought the same, and I just cracked up. Tom Cruise is a genius in that role. Vulgar and politically incorrect, but damn funny.
" I don't know what kind of pan-pacific bs power play you're trying to pull here, but Asia Jack is my territory. So whatever you're thinking, you'd better think again"
 
Can you better explain adding a control at runtime?
Well, not sure.

Whenever you change the Recordsource of a form, Access will automatically add an AccessField-Control for each field in the new recordsource and remove all fields from the old recordsource, if any.
You just change the Recordsource of a form. If done in design view or any other view and also if done manually or by code does not matter.

Here is a small example:
Create a new form, put a button on that form but do nothing else.
Create a button click event procedure and paste the following code into it (adjust table-/field- name to match an existing table/field!)
Open the form in Form View
Click the button / run the code
Look at the immediate pane for the output.

Code:
Private Sub Command0_Click()

    Dim autoControl As Object
    
    On Error Resume Next
    Set autoControl = Me!AnyTableField
    Debug.Print "No Recordsource, Error: " & Err.Number & " " & Err.Description
    ' Will print: No Recordsource; Error: 2465 Microsoft Access can't find the field 'AnyTableField' referred to in your expression.
    On Error GoTo 0
    
    Me.RecordSource = "SELECT * FROM AnyTable"
    Set autoControl = Me!AnyTableField
    Debug.Print "autoControl is of type: " & TypeName(autoControl) & " value is: " & autoControl.Value
    ' Will print: autoControl is of type: AccessField value is: Whatever

    Me.RecordSource = ""

    On Error Resume Next
    Set autoControl = Me!AnyTableField
    Debug.Print "No Recordsource, Error: " & Err.Number & " " & Err.Description
    ' Will print: No Recordsource; Error: 2465 Microsoft Access can't find the field 'AnyTableField' referred to in your expression.
    On Error GoTo 0

End Sub
 
I get it now. I have a form with no controls on it and change the recordsource. I have to use Me! to refer to the AccessField because the field is not a property.
Code:
Private Sub cmd1_Click()
  If Me.RecordSource = "" Then
    Me.RecordSource = "Accounts"
    MsgBox Me!TypeAccount 'works
    'MsgBox Me.TypeAccount ' fails not a property of the form yet
    MsgBox Me.Recordset.Fields("TypeAccount") 'works
  End If
End Sub

I can add this discussion, but it is so niche it might cause more confusion. Do not think I ever needed to do this, and if I did would probably gone the recordset route.
 
Regarding the sticky, I will cut her loose. The poll says it all.
 
I want to cut down the number of stickies in the General forum to 3. Open to suggestions on how to consolidate, which should go, keep, and so on. I've often thought even a single sticky that acts like an index of important topics or threads, with both text and links, is a better solution. Lots of stickies pushes fresh content below the fold and makes people scroll just to get to the "stuff".
 
Me! or Me. Bang or Dot

There is a lot of confusion about Me. vs Me! (Bang vs Dot) usage, and often what is posted on the Internet is wrong or incomplete. The following attempts to clarify this.

VBA provides two coding constructs Bang and Dot. Bang uses a "!" and Dot uses a "." Bang notation can be used in a very limited context. Bang notation does one and only one thing.

It causes the runtime to invoke the default member of an object and pass the name following the bang as a string argument.


So what does that mean?

1. Default Member: Microsoft classes have default properties. Assume you use a collection. The default property is "Item", and because it is a default you do not have to write it.

someCollection.item(2)
can be written
someCollection(2)

Most controls have a default value property so

x = txtboxA.value
is the same as
x = textboxA



The default for a form is the Controls collection, the default for a recordset is the fields collection.

So I can write

Me!ControlName
or
RS!FieldName

Only because they are default properties.

A form also has other collections that are not the default property. Example the "Properties" collection

Me!SomeProperty
does not work because it is not the default property

Me.Properties("SomeProperty")
Does work

The first point is Me! works only with DEFAULT Properties.

2. Pass the name following the bang as a string argument: This is probably the whole reason for even having Bang. It passes that at runtime and not compiled. So at runtime

Me!SomeControlName

gets passed to the DEFAULT property as a string "SomeControlName" an that DEFAULT collection returns the correct member. This can be proved that this happens at runtime and not compile time. If you type

Me!someWrongControlName
It will compile, but at run time when it passes "someWrongControlName" it will fail.

3. Do I need to use Me! in vba: In vba almost never. It is not required in vba (except in an rare circumstance listed in 4), but it can be used in vba as short hand.

RS.Fields("fieldName")
Can be shortened in Bang
RS!FieldName

(The fields collection is the default property of a recordset)
However since Fields is the default property you can drop it in dot notation so
RS.Fields("fieldName") can be shortened in Dot as well to RS("fieldName")
So the Bang really only saves you 3 characters (" ") vs !

Drawbacks of Bang
One problem with bang is that since it is run time you will lack intellisense.
Me.SomeControl pops up in intellisense and you get the correct name
Me!SomeCntrol does not come up in intellisense and this will fail at runtime since the name is incorrect

Another problem with bang is you can not use variable references

dim cntrlName as string
cntrlName = "txtOne"
msgbox me.controls(cntrlName) '
msgbox me!ctrlName

4. When do I need to Use ! Bang: As explained this passes the name following the ! at runtime. This is my guess why this exists at all. In queries and expressions you have to use !. That is because those are not compiled. In a query and expression you can not write vba only use functions and default methods.

(There is actually one use in vba where you would have to use !. If at run time you set the recordsource of a form or report and do not have a control bound to a field then Me.FieldName will not work, but Me!FieldName will work. This is not something normally done IMO. See not 6 for further discussion on why this is. The reason Me.FieldName does not work in this case is because since the control was never added to the form in design time there is no dedicated property for that Field. It does exist in the collection. The other way in this situation using Bang would be Me.controls("FieldName")

5. What is Me: Unless you are building custom classes or multiple instance of a form/report in VBA this is kind of hard to see. Most of the time in vba you are using a single instance of a form or report class. But classes are like cookie cutters where you can build multiple instantiations. Also 99% of the time you do not even need Me in either form. Again this is because within a class Me is the default

Me.SomeControlName
is the same as simply
SomeControlName

or

Me.SomeProcedure
Same as simply
SomeProcedure

Most of the time people use Me simply for clarity because most of the time it is not needed.

If using bang you cannot drop the Me or the object qualifier in front of it
Me!txtBox1
you cannot do
!txtBox1

Lets assume we can open two instance of the same form (which we can). A forms module is a class module. Assume in the class there is a method

Public Sub MyCaption()
msgbox me.Caption
end sub

If I opened two instances of the same form then changed their caption and called the MyCaption method.

dim frm1 as New Form_SomeForm
dim frm2 as new Form_SomeForm

frm1.caption = "frm1"
frm2.caption = "frm2"

frm1.myCaption ' message box with "frm1"
frm2.myCaption ' message box with "frm2"

In other words ME refers to the current instantion of the object. This is hard to in Access because most of the time we work with just a single instantiation of form or report objects.

6. An apparent exception: As stated the bang only works with the default member of a class and for a form or report the Controls collection is the Default. However if there isa field in a forms recordsource, it can be referenced like:

Me!FieldName

As stated the default of a form is the controls collection and there is not even a fields collection so this seemingly should not work.

(Below information provided by @sonic8 )
However, what appears as an exception is not. These fields are actually added as "pseudo" controls in the controls collection.
Access automatically adds a control of type AccessField to the Controls collection of a form for each field in the current data source that does not have a "real" control of the same name already. (- This is done whenever the Recordsource of the Form changes. However, historically this did not work reliably in older Access Versions. In current versions (Access 2016+) it appears to be reliable. These "auto-controls" are not included in Controls.Count, but you can also reference them using Me.Controls("FieldName").
 
Last edited:
If a sticky is warranted I would like to use what is posted above. I removed discussion about the old thread and fixed several mistakes.
 

Users who are viewing this thread

Back
Top Bottom