Link to home
Start Free TrialLog in
Avatar of Mark
Mark

asked on

VBA Autolist members not working. Can't find form objects.

I just created a new form/subform in Access and created an event button. When I go to add code and attempt to reference any form object using Me!objectname, I get no list of obljects. Yes, I have "autolist members" option checked. Furthermore, when I reference any object at all such as MsgBox Me!objectname I get "cant file the field objectname refered to in your expression." What's up?
Avatar of Leigh Purvis
Leigh Purvis
Flag of United Kingdom of Great Britain and Northern Ireland image

You mean you've lost intellisense - *and* your valid objects aren't being found at runtime?

(Boring bit over with first... roll on the FAQ ;-)
Have you compacted/repaired, decompiled and if need be imported everything into a new mdb?

After all that - are you 100% sure that Me!objectname refers to an object on your form (and not a field in the underlying recordsource)?
Avatar of thenelson
thenelson

The Me keyword only has meaning in the object module of the form, report or page it refers to. Are you in a global or class module perhaps?
What happens when you enter DoCmd. for example? Do you get a combobox then?
ASKER CERTIFIED SOLUTION
Avatar of Markus Fischer
Markus Fischer
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Another advantage of using Me.Object instead of Me!Object is that you get the error at compile time, not at run time!
Cheers!
(°v°)
lol the questioner should try using me("controlname") and see how much intellisense you get *then* ;-)
Not a sausage.

But by 'eck it makes you remember.
Avatar of Mark

ASKER

Thanks for all the feedback. Maybe I need some clarification. harfang  is right, I get the list using Me., but not Me! So, first question - what the heck is the difference between Me. and Me! ? It seems that VB has about 80 ways to accomplish the same thing. Very confusing. btw I do use  e.g. rs("name") for reference recordSource columns. Are there times when it is appropriate to use these various styles? If there's really no difference, then I'll just stick to the Me. notation and keep my life simple.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Leigh and Nelson are of course correct (especially about laptops ;)

<technical background = ON>

As Leigh explained, the '!' syntax is used _only_ as a shortcut for a member in a collection. As many objects have a collection as default value, you can often leave out the name of the collection.
To add to Leigh's examples, you can also refer to members of a collection by number. Thus:

    ? DBEngine(0)(0)(0)(0).Type

Is the type of the first field of first table of the first (current) database of the first (default) workspace... Shorter than either of:

? DBEngine.Workspaces(0).Databases(0).Tabledefs(0).Fields(0).Type   ' or
? DBEngine![#Default Workspace#]![C:\Test\db1.mdb]!Customers!CustomerID.Type

Let alone the full version:  ;)

? DBEngine _
    .Workspaces("#Default Workspace#") _
    .Databases("C:\Test\db1.mdb") _
    .TableDefs("Customers") _
    .Fields("CustomerID").Type

But that is not the end of the story.

Access.Form
¯¯¯¯¯¯¯¯¯¯¯
The Form Object is a curious beast. Normally, if a form (frmCompanies) has 7 controls, the first being CompanyID, I can get the value with any of: Form!CompanyID, Form.Controls(0), etc. But the funny thing is that I can also get the city using Form!City, even if there is no control named City.

In other words, the .Controls() collection of forms has hidden members, of type "AccessField", containing all the fields not bound to another control. They provide a handy shortcut to

    Form.Recordset.Fields!City.Value   ' equivalent to Form!City.Value

However, these hidden controls do not register in Form.Controls.Count or in the this control structure "For Each ctl In Form.Contols".

To make things even a little more complex, when you work from VB, the "Form" object isn't only an Access.Form, but also a generic class for Form class modules. In other words, VB knows that each Form object you use will at run-time be instanciated as a "Form_frmCompanies" sub-class, for example.

And, as it happens, all controls (including the hidden AccessField controls) are predeclared as independant properties of that class. This is why you can use Form.City as well. It's just as if you had a declaration section before your own with things like:

    Public CompanyName As TextBox
    Public Label1 As Label
    Public City As AccessField
    ' etc.

Me Keyword
¯¯¯¯¯¯¯¯¯¯¯
Now finally we come the the Me keyword. This is different from the Form keyword, because Form refers to a generic form (during design and compilation), while Me already refers to the exact subclass, e.g. Form_frmCompanies. But of course, the default property of Me is Me.Form ;)

So when you type "Me." (and Ctrl+J if needed) you will see all available properties, methods, and events of the module (including your own public variables and functions) _and_ all those of the form, in a single combined list. When you type "Form." (or "Me.Form."), you will see only the default properties (e.g. .CurrentRecord) and methods (e.g. .Requery) of a generic form. However, the '.' is still accepted for controls -- although they do not appear in the list, because at run-time, the form will no longer be generic.

It should be noted that this "predeclaration" of collection items is not a unique case. The same is true for all built-in properties of a form:

    Me.AllowAdditions   ' predeclared for:
    Me.Form.Properties("AllowAdditions")   ' or, of course
    Me.Properties!AllowAdditions   ' but NOT:
    Me!AllowAdditions   ' ** error **, will look for a control named "AllowAdditions"...

<technical background: OFF>


Let's get back down to earth ;)

Use the '!' syntax only for what it was meant to be: a shortcut to get a member of a collection by name.
E.g. CurrentDb.TableDefs!Customers or CurrentDb!Customers.

Use the '.' to get any built-in property, method, event, or sub-object from an object.
E.g. Me.CompanyName, DoCmd.OpenForm, Form.NavigationButtons, etc.

If you use '!' instead of '.' you will generally get an error. E.g. Me!Caption isn't the caption of the form but could be a control named "Caption".

Special cases:
¯¯¯¯¯¯¯¯¯¯¯¯
All built-in properties are predeclared. Instead of looking for them in the properties collection, just use the property name. E.g. Me.Caption is the property Me.Properties!Caption. This should be rather intuitive.

All controls of a form are also predeclared on the form's module. Use Me.City instead of Me!City. This will instruct the compiler to actually bind to a TextBox, ComboBox, AccessField, etc, and not just to a generic control. What's more, this syntax will correctly show the properties available for each type of object, e.g. Me.CompanyName.Format

When a control has the same name as a built in property, the property takes precedence (i.e. the control is then _not_ predeclared).

    Me.Caption = "This always works"   ' setting the title of the window
    Me!Caption.ForeColor = vbRed   ' changing a property of the label called "Caption"

When referring to another form, the dot syntax is still accepted, but will not allow early binding (and will not show any list of properties at design time).

    Me.CompanyName.Format   ' on the form itself: uses early binding, shows properties
    Forms!frmCompanies.CompanyName.Format   ' from another form (dot accepted)...
    Forms!frmCompanies!CompanyName.Format   ' ... but late binding occurs (as here)

I like to use the bang in that case (last example), as a form of documentation: This shows clearly that "CompanyName" will be evaluated at run-time only.


Hmm. This has gotten longer than I intended. I hope some of it is useful ;)
Cheers!
(°v°)
sounds good