How can we store information:
- Settings
- Preferences
- Object States and positions
- …
for a VBA solution, whether that be an Access database, Excel workbook, Word Document …?
What about storing the information in the registry!
That’s the subject I would like to broach in this article.
Yes, as developers, we have several options available to use to store such information, things like:
- in tables (in Access)
- in hidden worksheets
- in external files
- …
each presents PROs and CONs, no doubt, but the reason I wanted to cover using the registry is because it is:
- built-in to VBA, so available throughout the Office suite and thus universal
- easy to use
- fast
- reliable
- Isn’t tied to a specific application, can be shared amongst multiple application if needed
The Code
As mentioned above, VBA natively has built-in the necessary code to work with an isolate section of Registry in a safe manner. So we don’t even need to get into advanced APIs (and deal with bitness issues) or ActiveX approaches… Instead, we need only call upon 4 functions/statements:
- DeleteSetting
- GetAllSettings
- GetSetting
- SaveSetting
I thinks their names are self-explanatory!
To facilitate usage slightly, I created and use a series of wrapper functions and thus below is a sample of the code I use:
Private Const sAPPNAME = "YourApplicationName"
Function SaveRegistrySetting(sSectionName As String, sKeyName As String, sSettingValue As String) As Boolean
On Error GoTo Error_Handler
Call SaveSetting(sAPPNAME, sSectionName, sKeyName, sSettingValue)
SaveRegistrySetting = True
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: SaveRegistrySetting" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
Function GetRegistrySetting(sSectionName As String, sKeyName As String) As String
'Returns "" if app, section or key are not found
'Always returns a VarType = vbString / TypeName = String (stored as REG_SZ), so use conversion function after retrieving as req'd
On Error GoTo Error_Handler
GetRegistrySetting = GetSetting(sAPPNAME, sSectionName, sKeyName)
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: GetRegistrySetting" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
Function GetAllRegistrySettings(sSectionName As String) As Variant
On Error GoTo Error_Handler
Dim aSectionSettings As Variant
Dim iCounter As Long
aSectionSettings = GetAllSettings(sAPPNAME, sSectionName)
GetAllRegistrySettings = aSectionSettings
If IsEmpty(aSectionSettings) = True Then
GetAllRegistrySettings = Null
Else
For iCounter = LBound(GetAllRegistrySettings, 1) To UBound(GetAllRegistrySettings, 1)
Debug.Print aSectionSettings(iCounter, 0), aSectionSettings(iCounter, 1)
Next iCounter
End If
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: GetAllRegistrySettings" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
Function DeleteRegistrySetting(sSectionName As String, Optional sKeyName As String) As Boolean
On Error GoTo Error_Handler
If sKeyName = "" Then
'Delete the entire section and all its keys
Call DeleteSetting(sAPPNAME, sSectionName)
Else
'Delete a specific section/key
Call DeleteSetting(sAPPNAME, sSectionName, sKeyName)
End If
DeleteRegistrySetting = True
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
If Err.Number <> 5 Then
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: DeleteRegistrySetting" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
End If
Resume Error_Handler_Exit
End Function
Using such an approach, simplifies usage, simplifies updating the ‘YourApplicationName’ and adds error handling throughout.
Usage Examples
Save A ‘Setting’
To save a value to the Registry, we can simply do:
? SaveRegistrySetting("Application Settings", "DefaultSortOrder", "DESC")
Or
? SaveRegistrySetting("Application Settings", "EnablePreview", True)
OR
? SaveRegistrySetting("Application Settings", "NumberDecimals", 3)
which will return True/False to indicate whether the Save was successful or not.
Retrieving A ‘Setting’
To read back, retrieve, a setting value from the Registry, we can simply do:
? GetRegistrySetting("Application Settings", "DefaultSortOrder")
which will return
DESC
Retrieving All The ‘Settings’
If we want to review the current setting in one shot, perhaps build a collection/array/… the can use the GetAllRegistrySettings().
GetAllRegistrySettings("Application Settings")
which then returns
DefaultSortOrder DESC EnablePreview True NumberDecimals 3
Deleting A Single ‘Setting’
To delete a setting from the Registry entirely, we can simply do:
? DeleteRegistrySetting("Application Settings", "DefaultSortOrder")
which will return True/False to indicate whether the Deletion was successful or not.
Deleting An Entire Section
To delete all the Settings within a Section and delete the section itself, we can simply do:
? DeleteRegistrySetting("Application Settings")
which will return True/False to indicate whether the Deletion was successful or not.
Things To Be Aware Of
The Importance Of YourApplicationName!
The important thing here is to use an ‘YourApplicationName’ that is unique, so it can never be accidentally used by someone else in their program. Using a name like Access, ContactDb, … are probably poor choices. Instead, try prefixing with a corporate name, or even random strings that will never be duplicated: CARDA_ContactDb, gjh324_ContactDb
Strings Everywhere
One thing to note is that everything gets stored and thus retrieved as Strings. So you, as the developer, will need to be aware of the data you are retrieving and use the appropriate conversion function
- CBool
- CDate
- CInt
- CLng
- …
to convert the String into the appropriate variable type for further use within your VBA code.
Where Is It Stored
As you can see by my functions, in their usage, we never supply a root Registry Key where we store this information. So where exactly is it stored? That’s the beauty here, behind the scenes, all these procs work and Read/Update/Delete your values to the Root Key of:
Computer\HKEY_CURRENT_USER\Software\VB and VBA Program Settings\YourApplicationName
and store all the information there under different sections, as you define them when you call the various procs.
So you can launch the Registry Editor anytime you want, navigate to that section of the registry, and you can then review exactly how these interact and make changes.
Useful Resources


