When creating applications in a language that's pure code (such as C++), you want to design your code so that you can reuse it for a number of reasons, including the following:
These two points are also true when you create reusable code in Access. In Access, you also can create reusable objects. The following example looks at a reusable form and VBA code. The form allows the user to search for customers or movie titles, depending on where the search form was called.
Note
The database for the rest of this chapter can be found on the accompanying CD-ROM in Chap09.mdb, located in the ExamplesChap09 folder.
Three forms—StandardSearch, CustomersSearchSubform, and MovieTitlesSearchSubform—make up the standard search form routines. The number of SearchSubform-named forms will grow as more areas need to have a search form used. In this case, let's stick with the two, Customers and Movie Titles. To see what you want to accomplish, look at Figure 9.7. You'll start off by working with the Customers form.
By using the same form for different subjects, as in looking for customers or movie titles, you're also providing a consistent interface for your user. This is always desirable.
To look at the calling form side (the form that's initiating the opening of another form), look at two properties that Access provides for your purposes: OpenArgs and Tag.
The first property, OpenArgs, can't be accessed from Design mode. The OpenArgs property is set when a form is opened at runtime with the OpenForm method, off the DoCmd object.
Note
Before Access 95, DoCmd was a statement that you used for calling macro actions from Access Basic. As of Access 95, you can call the DoCmd object to perform the same actions as in prior versions. The DoCmd statement is changed to the DoCmd object when existing applications are converted to Access 97 and 2000.
The call to open the search form from the Customers form can be found in the event procedure attached to the OnClick event on the Search button. The routine in Listing 9.3 performs this call.
Private Sub Search_Click() On Error GoTo Error_Search_Click DoCmd.OpenForm "StandardSearch", acNormal, , , acNormal, _ acDialog, Me.Name Exit_Search_Click: Exit Sub Error_Search_Click: MsgBox Err.Description Resume Exit_Search_Click End Sub |
This routine will be the same whether it's called from the Customers or Movie Titles form. The portion of the code that makes it so versatile is the last parameter, Me.Name, found on the line containing DoCmd, where Name is the name property of the current form (Me). This parameter is the OpenArgs property and can be accessed from the form object that's being opened. Figure 9.8 shows the syntax for the OpenForm method off the DoCmd object, using the Object Browser.
Follow these steps to view a complete list of methods of the DoCmd object in the Object Browser:
1. |
While in any module in the VBE, press F2, click the Object Browser toolbar button, or open the View menu and choose Object Browser. |
2. |
Select Access from the Project/Libraries combo box. |
3. |
Select DoCmd from the objects in the Classes list. |
You now see the complete list of methods for the DoCmd object in the Object Browser. (For complete information about the Object Browser, see Chapter 2, “Coding in Access 2000 with VBA.”)
By placing Me.Name in OpenArgs, you can copy and paste the Search control and its OnClick event procedure into other forms with no changes. The only other item you need to worry about setting up on the calling form side is the Tag property.
The Tag property is user-definable, which means that Access pays no attention to it whatsoever, and you get to use it however you want. What you'll use it for in this example is to keep track of the field on which you want the standard search routine to perform the lookup in the calling form's recordset. In the Customers form, the routine is called CustomerID. You can see how the Tag property is set in Figure 9.9.
You're now done setting up the calling form. Next, let's look at what makes up the standard search form, StandardSearch. In looking at the standard search form, you are brought back to the OpenArgs property, which the code in Listing 9.4 uses. In the OnLoad event of the StandardSearch form, set the Caption property to reflect the calling form, and set the SourceObject property for the subSearch subform control.
Private Sub Form_Load() On Error GoTo Error_Form_Load Me.Caption = Forms(Me.OpenArgs).Caption & " " & Me.Caption Me!subSearch.SourceObject = Me.OpenArgs & "SearchSubform" Exit_Form_Load: Exit Sub Error_Form_Load: MsgBox Err.Description Resume Exit_Form_Load End Sub |
The Me.Caption line concatenates the caption of the calling form (Customers) with a space and the caption of the standard search form.
In the next line of code, the OpenArgs property of the calling form—in this case, Customers—is concatenated to the literal SearchSubform. This creates the complete name of the search subform, CustomersSearchSubform. It then assigns that to the SourceObject property of the SearchSubform subform control. You can see this subform control in Figure 9.10.
Note
The properties Link Child Fields and Link Master Fields aren't used. This means that you have a lot of power because the RecordSource property of the form is used as the subform—in this case, CustomerSearchSubform—linked to whatever control you want, if at all. This also allows you to be able to modify this link at any time during runtime. The Link Child Fields and Link Master Fields properties are two of the only ones that are limited to update only at the OnOpen event of a form.
This form has two other interesting procedures. The first one is attached to the OnClick event for each of the Letter command buttons and the AfterUpdate event of the SearchText text box. You can see the SearchText text box in Figure 9.10 (the Unbound control above the property sheet). The function attached to the OnClick event, ap_Requery_SearchSub(), is shown in Listing 9.5 and is in the StandardSearch form's code behind form.
This routine assigns a value to the StandardSearch form's Tag property based on which control was used, in the following order:
The txtSearchText control
The All button
One of the Letter controls
The routine then requeries the subform control, subSearch. The value in the Tag property is used in the RecordSource property of the subform's SourceObject—in this case, CustomerSearchSubform.
The other routine mentioned is called from the subform as well. There are three main points of interest concerning the form used as the customer search subform. By using the CustomerSearchSubform form (see Figure 9.11), let's look at these points of interest in order:
The CustomerSearchSubform's RecordSource is set to the following SQL statement:
Select CustomerID, FirstName, LastName from Customers where Customers.LastName like Forms!StandardSearch.Tag & "*" Order by LastName, FirstName;
As you can see, this query refers to the Tag property on the StandardSearch main form. This statement will change to reflect the current subform recordset, but needs to compare the recordset's fields to the standard search form's Tag property. If used by the Movie Titles form, the statement looks like this:
Select TitleNo, Title from MovieTitles where MovieTitles.Title like Forms!StandardSearch.Tag & "*" Order by Title;
The key fields are included in the SQL statements, even though they aren't displayed.
The Control Source property of the ChoiceDisplay text box, also shown in Figure 9.11, is set to the expression
=" " & [LastName] & ", " & [FirstName]
The OnDblClick event of the ChoiceDisplay text box and the OnClick event of the Choose command button both call the same subroutine from StandardSearch. Here's the event procedure for OnDblClick:
Private Sub ChoiceDisplay_DblClick(Cancel As Integer) dummy = Me.Parent.ap_StandardSearchChoice() End Sub
Note
You can now call subroutines located in one form from other forms. The preceding code calls the ap_StandardSearchChoice() function, which is located in the StandardSearch form's module. You can find this form on the CD-ROM in ExamplesChap09Chap09.mdb. For more information about calling routines in other forms, see Chapter 2.
Listing 9.6 shows the code for ap_StandardSearchChoice(). This routine clones the calling form's recordset, looks up the key value of the chosen value in the clone, and then sets the bookmark of the calling form to that record.
Now that all the code has been created, if you want to have the search routine work for the Movie Titles form, you only have to do the following:
1. |
Click the Forms tab in the database container. |
2. |
Select CustomersSearchSubform. |
3. |
Open the Edit menu and choose Copy. |
4. |
Open the Edit menu and choose Paste. |
5. |
Type MovieTitlesSearchSubform for the new form name. |
6. |
Open the new form (MovieTitlesSearchSubform) in Design mode by highlighting it and clicking the Design button. |
7. |
Change the RecordSource property of MovieTitlesSearchSubform to reflect the desired data: Select TitleNo, Title from MovieTitles where MovieTitles.Title like Forms!StandardSearch.Tag & "*" Order by Title; |
8. |
Change the DisplayChoice control's Control Source property to reflect the new display: =" " & [Title] |
9. | |
10. |
Copy the Search command button and the code attached to the OnClick event procedure over to the Movie Title form. |
Caution
Code isn't copied automatically when you only copy a control from one form to another. You must copy and paste the code in the modules themselves. This can also be a problem if you rename controls after you have event procedures attached to them. You can re-attach event procedures by finding the code and renaming the procedure to match the new name of the object.
One technique demonstrated in this section was swapping in a form name into the SourceObject property of a subform. In this case, it was used to substitute the version of the search subform that was necessary for the subject being sought—Customers or Movie Titles. This technique is also used for swapping in pages used with the Tab control. The following section further discusses this technique.
18.191.205.214