You are correct that in most cases, your form code does NOT need the me.
So, you can use
msgbox "last name = " & lastName
Or
msgbox "last name = " & lastName.value
Note that in VBA/ms-access we do not USE THE .TEXT property of a control
UNLESS THE CONTROL HAS THE FOCUS. So, use .value in place of .text when
moving from VB to VBA/ms-access.
The .text property of a control is certainly most useful in those events
that fire and the data has NOT been updated. For example, if you use the
keydown event, the control is not yet updated, and to get use/see the
current value of the control, you MUST use the .text, as the .value is NOT
YET updated. Thus, for general controls, and referencing their values, you
will as a habit use .value. However, for events and when the control has the
focus, you will use .text. However, for even before update, and after
update, you can use the value. So, .text use is quite rare, and generally
only for keypress type stuff.
Now, lets get back to our example:
msgbox "last name = " & me.LastName
The only reason why the above is more useful is that intel-sense popped up
the lastname field for you, and thus you will have much less of a chance
miss-spelling the field name.
Note that "me." simply refers to the current form, and thus if our form was
frmCustomer, then we could use:
msgbox "last name = " Forms!FrmCustomer.LastName
Now, when does use the me. come in handy? Well, lets assume we have some
button code where you press a button, but CALL SOME CODE in a library. (ie:
we want to re-use the code in a module for each time we use the button). You
thus can go:
Call MyCode(me)
At run time, "me" will be replaced with forms!frmCustomer.
Further, if you cut and paste the code into a DIFFERENT form, or even copy
the whole form, and continue to use the above code, then you DO NOT have to
re-write or change any code. So, the me. does refer to the current form code
that you are running. For stuff like field names etc you most certainly CAN
leave out the me. (but, it is quite handy as mentioned). And, if you need to
pass the current form name to another routine as in my above example, then
the form reference is NOT hard coded.
Having said all of the above, the real question here should be:
What kind of problems and differences will I experience as a developer when
using me. vs me!
Well, as others have mentioned, the me. syntax denotes properties and
methods of the form. These properties and methods of the form MUST BE
RESOLVED AT COMPILE TIME!
Thus, if you have a un-bound form (or a form where you set the record source
at run time), then the following will generate a compile time error
msgbox "last name = " & me.LastName
Why? Because we have NOT YET set the record source of the form, and thus
me.LastName will generate a compile time error if NO recordsource is set
(and we don't have a text box on the screen called LastName). Your solution
to this problem is either:
a) place a control on the form with the SAME NAME as the field(note that you
in general DO NOT need to place a control/text box on a form to
get/grab/use/update/reference a field name from the form underlying
recordset. However, if you SET THE FORMS REOCRDSOUCE AT RUNTIME, then you
MUST use me!LastName, as me.LastName does NOT yet exist!).
You can't use me.lastName, since it will NOT exist as a member of the form.
You cannot even use msgbox "last name = " & LastName. Ms-access will not
resolve the lastname field if the record source of the form is NOT set, and
a textbox called lastname does not exist on the form. If you try and compile
your code, you will see a compile error (again, this assume the form does
NOT have a datasouce yet set).
I have a considerable amount of code that actually sets the sql source of a
form at runtime. You can do this VERY EASY in code, and so I often do the
following:
me.RecordSouce = "select * from tblCustomers where city = 'Edmonton'"
Also, note how I use "me." RecordSouce, and thus you can instantly
assume/understand that the above code is running in a form! (you can't use
me outside of forms module). So, often, use of "me" does give you a hint as
to where the code is being run. So, this again supports that using me. often
conveys to you the reader "where" and in what context the code is being run.
Anyway, the above simply allows you to set/stuff sql into a form at runtime.
This means the forms datasouce is blank, and thus you CAN NOT use all the
fields of the reocrdsouce via the me.SomeField notation. It will NOT work!
You can only use the dot notation for fields that have the same name of a
text box on the form. Often, if not most of the time I DO NOT want to user
to see fields like the key id (autonumber). So, I do NOT place the
keyid(autonumber) field on the screen. With a normal bound form, you are
free to use me.ID, or me!id (both work despite the id NOT being placed on
the form). However, for un-bound forms (or forms with reocrdsouce set at
runtime) to use/grab the key id YOU CAN NOT USE me.ID. You MUST use me!ID
So, me!FieldName will NOT break in code, but it will ALWAYS compile. It is
certainly now a very good debate, since using me. will be ALWAYS be caught
at compile time, where as me! errors are ONLY going to be realized at
runtime. You can put in code me!SomeField even in the case where the
fieldname does not exist! Thus, me. represents built in and *existing*
properties of the form, where as me! is for user defined stuff.
The fact that we get all the fields as a property of a form via me. when it
is bound is a bonus.
So, in fact, me!Fieldname is more correct, as it means the value we are
using is NOT a ms-access defined property of the form, but is in fact a
programmer/developer defined property. So, you might consider coding to this
standard, as then you will instantly see when you are using a ms-access
defined property (.) or a user defined value(!).
So, really, one probably should use me! for your field names, and stick to
only using me. for ms-access defined stuff. However, since me. gives compile
time checking for your field names, and you also get inteli-sense, then a
good deal of us continue to use me., but in fact we should be using the more
correct me! for field names.
So, here is my rule of late:
For forms that set the reocrdsouce at runtime, then I use me!
For the rest, I continue to use me.
However, over time, I am now starting to learn towards the me!, as then if I
take a existing form, and start changing the record source, I will NOT get
errors if I decide to remove a text box from the form, but still need to use
the field in the underlying recordsource. And, also, if I change the sql
then I can safely delete textboxes on the form, and not have code break when
changing the recordsouce, or trying to reference fields that don't necessary
have a corresponding text box control. I stress again, this problem only
applies to forms where you set the datasouce at runtime, and they are blank
at design time). So, with more skill, the fact of catching at compile time a
bad field references like me.WrongFieldName is less of a bonus then having
code break, or being forced to place text controls on a screen to grab
underlying field values.
This whole issue is going to come down to how you code and design, and what
you find breaks, or does not break in code. So, your choice of me. really
comes down to your habits as a developer, but I am learning towards the me!,
as it is technically more correct.