Microsoft Access Tips and Tricks
What Object Has the Focus?
Most often when you are writing code for an Access application, you know what object -- control, form, report, etc. -- that code is concerned with. For example, if you are writing an event procedure, you know what object raised the event. But sometimes this is not the case. If you are writing a general-purpose routine, you may not know in what context that routine will be called, what form or control triggered it, or what the user was doing when it happened. Nevertheless, there are various ways to find out. This article will list a variety of them.
There are some properties of the Screen object that return object references to active objects:
- Screen.ActiveControl - returns a reference to the control that has the focus (if there is one)
- Screen.ActiveForm - returns a reference to the form that has the focus (if there is one and it's not a popup form)
- Screen.ActiveReport - returns a reference to the report that has the focus (if there is one and it's not a popup report)
- Screen.ActiveDatasheet - returns a reference to the table or query datasheet that has the focus (if there is one)
In addition, the Screen object provides a means to refer to the object that *previously* had the focus:
- Screen.PreviousControl - returns a reference to the control that last had the focus, before Screen.ActiveControl received the focus
All of those properties will raise an error if there is no such object. There's a difficulty with the ActiveDatasheet property, in that it's not easy to tell whether the datasheet is a query datasheet or a table datasheet (though you can figure it out from the TypeName of the object). Also, ActiveDatasheet won't tell you about a query or table that is open in design view.
There are also a couple of properties of the Application object that can come in handy. I believe they have existed since at least Access 97. These properties are:
- Application.CurrentObjectName - the name of the currently active object, whether it's open or not, even if it's just selected in the database window
- Application.CurrentObjectType - the type (numeric, from the AcObjectType enumeration; e.g., acTable = 0, acQuery = 1, acForm = 2, etc.) of the current object.
These properties will give you the name and type of the object that Access thinks is active. However, they don't tell you whether the current object is open, or what view it's in. For that, you can use SysCmd acSysCmdGetObjectState, or check the IsLoaded property of the appropriate AccessObject via CurrentProject.AllXXXXX (AllForms, AllReports, and others)) or CurrentData.AllXXXXX (AllTables, AllQueries, and others).
The example below appears in the help file for Access 2003. You can see how it uses CurrentObjectName and SysCmd to check the state of a particular form:
The following example uses the CurrentObjectType and CurrentObjectName properties with the SysCmd function to determine if the active object is the Products form and if this form is open and has been changed but not saved. If these conditions are true, the form is saved and then closed.Public Sub CheckProducts() Dim intState As Integer Dim intCurrentType As Integer Dim strCurrentName As String intCurrentType = Application.CurrentObjectType strCurrentName = Application.CurrentObjectName If intCurrentType = acForm And strCurrentName = "Products" Then intState = SysCmd(acSysCmdGetObjectState, intCurrentType, _ strCurrentName) ' Products form changed but not saved. If intState = acObjStateDirty + acObjStateOpen Then ' Close Products form and save changes. DoCmd.Close intCurrentType, strCurrentName, acSaveYes End If End If End Sub
Another useful property, especially in error-logging, the CodeContextObject property of the Application object. This property returns a reference to the object from which the currently executing macro or VBA procedure was called. This may or may not be the active object. For example, for code running in the Timer event of a hidden form, CodeContextObject would return a reference to that form, even though some other object has the focus.
CodeContextObject becomes very useful for debugging a utility procedure that may be called from a variety of objects, because it allows you to determine exactly which object called the procedure.
Versions: Access 97 to 2007
Categories: VBA, How To, Forms
Date: 14 October 2008