Access JumpStart 2.0 | Blog

A Rapid Development Framework for Microsoft Access

I have discovered another source of documentation from the RubberDuck git repository which contains some descriptions of the refactoring options. Here is the link:

Refactorings · rubberduck-vba/Rubberduck Wiki · GitHub

According to this page, the Encapsulate Field Refactoring entry is:

Select a module variable (aka “field”) to make Private and expose a Property Get and Property Let/Set accessors for.

I am going to setup a public variable in some code so I can try it out. Here is my module before the refactor with a single public variable I called EncryptionType as a string:

Option Compare Database
Option Explicit

Implements IHAL_Encryption

Public EncryptionType As String

Private Function IHAL_Encryption_decrypt(sEncryption As String, sKey As String) As String
    Debug.Print TestFunction("Two", "One", "Four")
End Function

Private Function IHAL_Encryption_encrypt(sInput As String, sKey As String) As String
    Debug.Print TestFunction("Second", "First", "Four", "Three")
End Function

Private Function TestFunction(Param2 As String, Param1 As String, Optional Param4, Optional Param3) As String
End Function

I will first re-run the RubberDuck parser as always to refresh the RubberDuck Refactoring capabilities. Then I can Right click on the line with the declaration and get this menu:

And when I click on Encapsulate Field I get this dialog box:

This is nice. I like that it shows me what it’s about to do and that gives me some additional ideas. What if I have a block of public variables in the class? It looks like I could do more than 1 at a time, which is pretty cool. And I want to use them in a function to see how it will handle existing references to the public variable. Let’s try this and see what it does:

Option Compare Database
Option Explicit

Implements IHAL_Encryption

Public EncryptionType As String
Public EncryptionID As Long
Public FileManager As Object

Private Function IHAL_Encryption_decrypt(sEncryption As String, sKey As String) As String
    Debug.Print TestFunction("Two", "One", "Four")
End Function

Private Function IHAL_Encryption_encrypt(sInput As String, sKey As String) As String
    Debug.Print TestFunction("Second", "First", "Four", "Three")
End Function

Private Function TestFunction(Param2 As String, Param1 As String, Optional Param4, Optional Param3) As String
    Set FileManager = CreateObject("Scripting.FileSystemObject")
    EncryptionType = "MyType"
    Debug.Print EncryptionType
    EncryptionID = EncryptionType
End Function

I found that by clicking on either a reference to the variable in the function or the declaration of the variable, the Encapsulate Field becomes active. When you select any variable, that variable will be auto-selected in the dialog, with the opportunity to choose other variables also:

Just selecting the single variable, I get the resulting code:

Option Compare Database
Option Explicit

Implements IHAL_Encryption

Private encryptionType1 As String
Public EncryptionID As Long
Public FileManager As Object

Public Property Get EncryptionType() As String
    EncryptionType = encryptionType1
End Property

Public Property Let EncryptionType(ByVal RHS As String)
    encryptionType1 = RHS
End Property

Private Function IHAL_Encryption_decrypt(sEncryption As String, sKey As String) As String
    Debug.Print TestFunction("Two", "One", "Four")
End Function

Private Function IHAL_Encryption_encrypt(sInput As String, sKey As String) As String
    Debug.Print TestFunction("Second", "First", "Four", "Three")
End Function

Private Function TestFunction(Param2 As String, Param1 As String, Optional Param4, Optional Param3) As String
    Set FileManager = CreateObject("Scripting.FileSystemObject")
    EncryptionType = "MyType"
    Debug.Print EncryptionType
    EncryptionID = EncryptionType
End Function

The reference to the public variable in “TestFunction” remains as is, but that is fine, it will use the public property instead.

It’s nice that you can choose multiple Public variables in the dialog and do many at once.

Using the “Wrap Fields in Private Type” option will group all selected Public options and convert them to an internal user defined type and sets the private variable “this” to an instance of the new type.

This allows you to reference your private variables as this.VariableName. I like that option. It’s similar to what Alessandro Grimaldi does in his VBA code to allow usage of autocomplete for all variables within the private internal scope of the class.

When you select each individual Member line, you can also change the name of the Public facing property for the class and if you check “Read Only” then it will only create a public getter and not a setter. If you choose to do this and you are setting the Public variable in your code inside the class, it will change the reference to set the internal private variable.

I suppose that this refactoring will also change any references to your object in external code, although I haven’t specifically tested for that in what I’m doing here.