Convenience Function for Passing Values Between Forms via a Hidden Global Form

I don't always use a global form to stash user-provided values, but when I do, I use this GetInfo() function.

Convenience Function for Passing Values Between Forms via a Hidden Global Form

One technique for passing values back and forth between forms and reports in Microsoft Access is to stash them temporarily on a hidden "Global" form.

To be honest, I rarely use this technique in new development.  I work very hard to avoid global state of any kind.  My current rule of thumb is that global variables should be limited to those values that must be set at runtime, but do not change throughout the life of the application.  

That said, I maintain dozens of Access applications that are over 20 years old.  Many of those applications use this technique.  One pattern in particular showed up again and again:

'Calling Code
Forms!Global!Message = "Enter Report Date"
DoCmd.OpenForm "GetDate", , , , , A_DIALOG
If Forms!Global!OK Then
    'User entered data and clicked OK; we can do stuff now
End If

'Form_GetDate code behind
Private Sub Cancel_Click()
    Forms![Global]![OK] = False
End Sub

Private Sub OK_Click()
    Forms![Global]![StartDate] = Me![ReportDate]
    Forms![Global]![OK] = True
End Sub
The A_DIALOG constant is a dead giveaway to veteran Access developers that this is old code.

The pattern was very consistent:

  1. Set a prompt for the dialog to the Message control on the Global form
  2. Open the form (GetDate, in this example) in dialog mode
  3. Each GetXxxx form had a text box bound to Forms!Global!Message to display the prompt
  4. If user clicks [Cancel], set the Global OK control to False and close form
  5. If user clicks [OK], transfer values from GetXxxx text boxes to equivalent fields on the Global form, set Global OK control to True, and close form
  6. In the calling code, check the value of the Global OK control to see what user did

These same four lines of calling code appeared everywhere in many of these older applications.

There was nothing inherently wrong with the approach, it was just inefficient.  Those four lines of code could be replaced with one line by introducing a convenience function: GetInfo().

The Code

' Procedure : GetInfo
' DateTime  : 7/28/2008 16:22
' Author    : Mike Wolfe
' Purpose   : Simplifies the process of getting user input via custom input forms.
' Source    :
' Usage     : If GetInfo("Get2Dates","Please enter report dates:") Then
'                 'If we make it in here, we know the user hit OK
'             End If
' 12/16/10  : Added optional parameter OpenArgs.
Function GetInfo(GetDataFormName As String, _
                 Optional Message As String = vbNullString, _
                 Optional OpenArgs As String = vbNullString) As Boolean
    With Forms!Global
        !Message = Message
        !OK = False
        DoCmd.OpenForm GetDataFormName, , , , , acDialog, OpenArgs
        GetInfo = !OK
    End With
End Function


The introduction of this function required no changes to the GetXxxx forms themselves.  This made it very easy to refactor the calling code without having to make additional changes.

When refactoring to introduce the GetInfo() function, I also "inverted" the If...Then statement to make it a guard clause, as shown below:

If Not GetInfo("GetDate", "Enter Report Date") Then Exit Sub

A Better Way

I'll cover my preferred approach for doing this in a future article.  Stay tuned.

UPDATE [2023-10-27]: The following articles document my preferred approach:

Pass Values Between Forms in Access Without Using a Hidden Global Form
Using a hidden “global” form is a common way to return user-entered data to your program, but there is a better way.
GetInfoForm(): Get User Input Without Needing a Global Form
The GetInfoForm() function simplifies the task of returning user input from an unbound form without stashing values in a hidden global form.

All original code samples by Mike Wolfe are licensed under CC BY 4.0