> ## Content Index
> Fetch the complete content index at: https://nolongerset.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Create Standalone Functions to Return User Input Values in Microsoft Access
- URL: https://nolongerset.com/standalone-functions-with-getinfoform/
- Published: 2023-10-05T01:54:33.000Z
- Updated: 2026-05-08T12:35:59.000Z
- Description: A combination of the GetInfoForm() function, custom VBA types, and "Extract Method" refactoring helps reduce our Access application's complexity.
- Author: Mike Wolfe
- Tags: VBA, Intermediate, #Import 2026-05-20 02:59

In a previous article, I introduced the **GetInfoForm**() function, which can be used to prompt a user for data using a custom dialog form and retrieve the user-entered values directly from the form–without having to temporarily stash them on a hidden global form:

[GetInfoForm(): Get User Input Without Needing a Global FormThe GetInfoForm() function simplifies the task of returning user input from an unbound form without stashing values in a hidden global form.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/10/GetInfoForm---Get-User-Input-Without-Needing-a-Global-Form--2-.png)](https://nolongerset.com/getinfoform/)

I concluded that article with the following sample code:

```vba
Sub TestGetDeedInfo()
    Dim Frm As Form_GetDeedInfo
    Set Frm = GetInfoForm("GetDeedInfo")
    If Frm Is Nothing Then Exit Sub
    
    Dim RecBook As String
    RecBook = Frm.tbRecordBook.Value
    
    Dim RecPage As String
    RecPage = Frm.tbRecordPage
    
    CloseForm Frm.Name
    
    Debug.Print RecBook, RecPage
End Sub
```

While this is an improvement over using a hidden global form to pass values around, we still end up mixing user interaction code with business logic. To reduce complexity and make our code easier to debug and test, we should strive to keep as much business logic as we can isolated within [pure functions](https://nolongerset.com/what-are-pure-functions/).

Thus, we need to extract the user interaction code into a separate procedure.

## "Extract Method"

Modern development environments (read: pretty much any besides VBA) include an "extract method" refactoring tool.

The idea is simple. Select a portion of a long routine and extract it out into a standalone method (e.g., a Function or Sub).

This type of refactoring has many benefits:

- Condenses many lines of code into a [single chunk of information](https://nolongerset.com/code-that-fits-in-your-head/#hex-flowers) which occupies less room in our brain (which is [important](https://nolongerset.com/rule-of-seven/)).
- Makes it easier to replace the call to the user dialog with hard-coded values during testing (whether that be automated or ad hoc testing).
- Creates a reusable piece of code that can be called from multiple places in the application (i.e., Don't Repeat Yourself).
- The result of the function can be passed around as an argument to other procedures.
- It supports the "[Functional Core, Imperative Shell](https://nolongerset.com/code-that-fits-in-your-head/#functional-core-imperative-shell)" approach to software design.

While the VBA IDE may lack an "Extract Method" tool, the underlying concept is just as important in VBA as it is in other programming languages.

Let's rewrite our **TestGetDeedInfo()** function by extracting a method from the inline code.

## GetDeedInfoFromUser() Function

Since the GetDeedInfo form returns two pieces of information (`RecordBook` and `RecordPage`), we can't return a simple value from our function.

Instead, we declare a custom type in VBA:

```vba
Type typDeedInfo
    UserCanceled As Boolean
    RecordBook As String
    RecordPage As String
End Type
```

We can then use the above custom type as our return type in our extracted function, **GetDeedInfoFromUser()**:

```vba
Function GetDeedInfoFromUser() As typDeedInfo
    Dim Frm As Form_GetDeedInfo
    Set Frm = GetInfoForm("GetDeedInfo")
    
    If Frm Is Nothing Then
        GetDeedInfoFromUser.UserCanceled = True
        Exit Function
    End If
    
    With GetDeedInfoFromUser
        .RecordBook = Frm.tbRecordBook.Value
        .RecordPage = Frm.tbRecordPage.Value
    End With
    CloseForm Frm.Name
End Function
```

We can now rewrite our test function as follows:

```vba
Sub TestGetDeedInfo()
    Dim DeedInfo As typDeedInfo
    DeedInfo = GetDeedInfoFromUser()
    If DeedInfo.UserCanceled Then Exit Sub
   
    Debug.Print DeedInfo.RecordBook, DeedInfo.RecordPage
End Sub
```