How to Simplify MS Access Form Searches Using Class Modules and Collections to Pair Text Boxes and Option Groups for Efficient SQL Query Generation (1 Viewer)

Deleted

New member
Local time
Today, 22:33
Joined
Dec 1, 2025
Messages
131

Rediscovering the Joy of Programming​

I haven’t been this absorbed in programming since my early days—back when I first discovered the magic of assigning objects to object variables and unlocking all kinds of possibilities in code.

For years I dabbled with class modules, but I never found a truly practical use for them… until now.

I almost said I couldn’t have done it without ChatGPT, but the truth is I probably could have—it just would have taken me a week instead of a couple of evenings.

One of the things I enjoy most is walking through objects with a For…Next loop and operating on a set of them simultaneously. Recently, I had a situation on a form involving a pair of controls: a TextBox and an OptionGroup.

  • The TextBox provides the search term.
  • The OptionGroup defines the type of search:
    • Option 1: Ends with → LIKE 'abc*'
    • Option 2: Contains → LIKE '*abc*'
    • Option 3: Starts with → LIKE '*abc'
    • Option 4: Null → [Field] IS NULL
    • Option 5: Exact match → = 'abc'

Naming Convention Evolution​

Originally, I relied on a custom naming convention to match controls. Later, I realized it was far more logical to use the Tag property. By storing the field name in both the TextBox and OptionGroup tags, I could easily link each pair together.

The code to walk through collections of objects is straightforward once you get the hang of it, but it often meant reusing the same boilerplate logic—lots of copy and paste.

Then came the breakthrough: ChatGPT suggested putting them into a collection. That reminded me of a thread I’d read years ago where Mark mentioned how often he used collections. Digging deeper, I realized I could go one step further: build a class module to hold the details of each object, store them in a collection, and expose a custom property to manage them.


Why the Class Module Works​

  • Encapsulation: The class module bundles the TextBox and OptionGroup into a single entity.
  • Simplicity: I no longer have to handle them separately.
  • Maintainability: The code becomes cleaner, shorter, and easier to reuse.

Old Code (Verbose)​

Code:
Dim ctlTxt As Control
Dim ctlOpt As Control
Dim intTxtPrefixLen As Integer
Dim intOptPrefixLen As Integer

intTxtPrefixLen = Len(conTxtPrefix)
intOptPrefixLen = Len(conOptPreFix)

For Each ctlTxt In Me.Controls
    If ctlTxt.ControlType = acTextBox Then
        If Left(ctlTxt.Name, intTxtPrefixLen) = conTxtPrefix Then
            ctlTxt.Value = ""
        End If
    End If
    For Each ctlOpt In Me.Controls
        If ctlOpt.ControlType = acOptionGroup Then
            If Right(ctlOpt.Name, Len(ctlOpt.Name) - intOptPrefixLen) = ctlTxt.Name Then
                ctlOpt.Value = 1
            End If
        End If
    Next ctlOpt
Next ctlTxt

New Code (Elegant)​

Code:
Dim ctrlCriteria As clsSearchCriteria

For Each ctrlCriteria In Me.SearchCriteriaCollection
    ctrlCriteria.TextBox.Value = ""        ' Clear the TextBox
    ctrlCriteria.OptionGroup.Value = 1     ' Reset to first option
Next ctrlCriteria

The Payoff​

  • Code is shorter, tidier, and easier to read.
  • Reuse is effortless across multiple TextBox/OptionGroup pairs.
  • Encapsulation means I can treat each pair as a single object.
This experience reminded me why I fell in love with programming in the first place: the thrill of discovering a smarter, cleaner way to solve a problem.
 
Last edited by a moderator:
I know how you feel Tony.
I am even looking at refreshing myself in COBOL, but on a PC and not a mainframe, just to keep my brain working. :)
 
I’m playing with html/css/javascript
 
No, at 70 years of age, I am now retired. Plus GCOS7 COBOL is different from IBM/ICL COBOL :-)
I know, as I had to teach ICL people. :)
Mind you, I did love GCOS7. :)

I did a fair bit in financial systems for banks and building societies as you say.
 
Well TBH I was looking at doing a free course with Rocket (which used to be MicroFocus apparently), but having a devil fo a job getting the visual studio that is mentioned in the course. :-( So much so, I am thinking 'stuff it' . :)
 
Yes. I have a version on my laptop, which is nothing like the version in the course.
I am going to go looking again when I have time.
 
Do you mean visual studio code, the Microsoft IDE?
Just being pedantic: Visual Studio != Visual Studio Code

Visual Studio - grossly bloated IDE that is Windows only

Visual Studio Code - text editor on steroids that can be used as a basic IDE with appropriate plugins, and is cross-platform.
 
If you are starting out working with custom classes, note this debugger setting...

s0.png


If this is not set, the debugger will not break at the error in your custom class, it will break at the line making the call in the consumer.
 
Now I remember a thread a while back where Mark said that he often uses collections (If I recall correctly)... Further interrogation of ChatGPT led to the idea of building a class module to hold details of the object and a collection to retain the objects, and a custom property to fill the collection.
Can you or @MarkK share a simple file (or a link to the thread) to show how you did it?

I normally use a property in my forms instead of a collection.

Thanks.
 
If you are starting out working with custom classes, note this debugger setting...

View attachment 116654

If this is not set, the debugger will not break at the error in your custom class, it will break at the line making the call in the consumer.
Thank you Mark. ATM, an error stops me even closing the form with @cheekybuddha's code, so I have to kill Access in task manager.
 
One thing I do recall arguing in favour of a few times...
• Rather than manage a subset of controls by setting the Tag property in design view, and then enumerating the form's entire controls collection to work with them, do something like...
Code:
Private cts_ As VBA.Collection

Property Get MyCtlSubset() As VBA.Collection
    If cts_ Is Nothing Then Set cts_ = GetCollection(Me.cmdButton, Me.Text0, Me.Text2, Me.Text4)
    Set MyCtlSubset = cts_
End Property

Private Function GetCollection(ParamArray stuff()) As VBA.Collection
    Dim var
    Set GetCollection = New VBA.Collection
    For Each var In stuff
        GetCollection.Add var
    Next
End Function
• I prefer to list the subset's member controls in code so I can see them--and add and remove them immediately.
• Don't have to navigate design view, back and forth, find the control, open a property sheet, select the "Other" tab, and dig around.
• Just type "Me." and select the control by name from intellisense, and stuff it into some kind of enumerable.
I've even just done it like this...
Code:
Property Get MyCtrlArray() As Variant
    MyCtrlArray = Array(Me.cmdButton, Me.Text0, Me.Text2, Me.Text4)
End Property
Makes it easy to do stuff like...
Code:
Private Sub Form_Load()
    SetCtlSubset_Visible Me.MyAdminButtonSet, Sys.User.IsAdmin
End Sub

Private Sub Form_Current()
    SetCtrlSubset_Enabled Me.MyEditOrderButtonSet, IsNull(Me.OrderShipDate)
End Sub

Sub SetCtlSubset_Enabled(vEnumerable As Variant, State As Boolean)
    Dim var
    For Each var In vEnumerable
        var.enabled = State
    Next
End Sub

Sub SetCtlSubset_Visible(vEnumerable As Variant, State As Boolean)
    Dim var
    For Each var In vEnumerable
        var.visible = State
    Next
End Sub
And more than half this code (doesn't have to be) (shouldn't be) on every form
 
Let me learn to crawl first, before even attempting to walk. :)
TBH, if I get this simple class excercise working, I think I will leave it at that. It is already hurting. :)
 

Users who are viewing this thread

Back
Top Bottom