[AccessD] Doing some thing the class way... was Toolbar

Bill Benson bensonforums at gmail.com
Sat Jan 29 06:38:39 CST 2022


John - I need to ask for clarification on a few definitions and procedures
in your explanation.

1. What does CBF stand for?
2. Where and how do you create instances of the class module you are
assigning forms to?

I have a new database with only one form named Form1, which has no code in
its code module, and which has had added to it, in design view before I
closed and saved it, a single control (command button) named Command0. I
will next write some code in a class module I named clsForm, and a
procedure named LoadForms in a standard module named Module1; I will single
step through LoadForms and report on intermediary results. As I will hit a
runtime error very quickly, I will ask you some questions.

'clsForm
Option Compare Database
Option Explicit
Public WithEvents MyForm As Form
   Private Sub MyForm_Load()
       g_i_IncrementForms = g_i_IncrementForms + 1
       MsgBox "Instance " & g_i_IncrementForms & " of Form_" &
Me.MyForm.Name & " was unloaded"
   End Sub

   Private Sub MyForm_Unload(Cancel As Integer)
       MsgBox "Instance " & g_i_IncrementForms & " of Form_" &
Me.MyForm.Name & " was unloaded"
   End Sub

'Module1
Option Compare Database
Option Explicit
Public g_i_IncrementForms   As Long
Public g_col_Forms          As Collection
Sub LoadForms()
   Dim clsForm     As clsForm
   Dim Form        As Object
   Dim Forms       As Object

   Set Forms = Application.CurrentProject.AllForms
   For Each Form In Forms
      Set clsForm = New clsForm
      g_i_IncrementForms = 0
      Set clsForm.MyForm = Form
      If g_col_Forms Is Nothing Then
        Set g_col_Forms = New Collection
      End If
      g_col_Forms.Add clsForm
   Next
End Sub

Single-Stepping through Module1.LoadForms: Before the line Set
clsForm.MyForm = Form, the immediate window can give me these results:
   ?TypeName(Forms)
     AllObjects
   ?TypeOf Forms is AllForms
     True
   ?TypeOf Form is Object
     True
   ?TypeOf Form is Form
     False
   ?Forms(0).name
     Form1

Some things to note:
    In the construction above, Form is declared as Object.
    The line Set clsForm.MyForm = Form, will throw a runtime error.

If instead this declaration had been used
   Dim Form        As Form

then this line would have produced a runtime error:
   For Each Form In Forms

Therefore, in order to have some kind of collection to loop *prior* to
opening any forms, I have to deal with the AllObjects class with members of
type Object. Declaring the MyForm object in the clsForm class module is
what causes the assignment  Set clsForm.MyForm = Form to result in a type
mismatch error.

So given my results, I concluded - you will apparently tell me WRONGLY -
that using class modules to house a Form's events was not possible until
the Form itself has been opened.

So in order for me to understand what you are implying by stating the class
module approach can be used to hold the Form's events, I need you to show
me some code that will create an instance of clsForm for each Form type
access object. That will enable me to apply your methods. Your explanation
so far confuses me, since you talk about declaring things "in the Form
header". What Form header, in the code module of the Form? If that is so,
then the Form has to be opened in order for those objects to get assigned
something in memory. Until them, I assume they are either allocated some
memory, or are in fact nothing at all, prior to a particular Form opening.


On Fri, Jan 28, 2022 at 9:44 PM John Colby <jwcolby at gmail.com> wrote:

> Bill, I am in no way dissing your answer, your experience, or point of view
> - in fact I highly respect all of the above.
>
> The original author asked if it could be done in a class called from each
> form that wanted to do this.  Seems like that is worthy of asking, worthy
> of consideration.
>
> There are more ways to kill a cat than choking it to death on butter as my
> mamma used to say.  Sometimes quick is good or even best.  I wasn't even
> really addressing the original thread since I wasn't following it closely.
> I was addressing the concepts.
>
> I understand quite well that to the majority of Access developers what I do
> with classes is, shall we say, not understood well, if even at all.  I try
> occasionally to poke ideas into conversations just to stimulate thinking
> about how we do things. So...
>
> Frameworks are everywhere.  In the 80s I learned to program in Turbo
> Pascal, whereupon I stumbled on their database framework.  It was a SYSTEM
> of code which allowed me to use a database for Turbo Pascal.  From that
> experience and others a little later grew my passion for creating my own
> framework for Access, office and VBA.
>
> Using a class to wrap a form is the foundation for a framework.  Using a
> class to wrap each control is another piece of that framework.  I wrote
> every single piece of my framework as code behind form, calling functions
> in a library of functions, because where else does code go?
>
> It didn't take long to discover that I was coding a concept over and over
> in many of my forms.  And my CBF was looooonnnnnnngggggg.  Out the door and
> down the hall loooonnnnnnnggggg..... because I was sinking events in each
> form, doing exactly the same thing in form A as in form B.  Except I was
> embedding the event sinks to do that in each form.  Identical code,
> everywhere.  A maintenance nightmare.  And I ran square into that
> maintenance nightmare myself.
>
> When I discovered classes and the fact that I could write a clsFrm, wrap my
> form with my clsFrom and then sink form events into that clsFrm, all of a
> sudden all of those event sinks in all those CBF modules doing exactly the
> same thing went away.  Any code that was used everywhere went into my
> clsFrm and those events that used to be sunk in the CBF of all those forms
> was now sunk in my clsFrm.  Except that I was still sinking events for
> other objects directly in my clsFrm.  IOW modeling more than one thing in
> my class.
>
> CAUTION... In OOP, one of the foundational ideas is that an object models
> one thing (or a system).  A clsFrm models a form, a clsCbo models a combo
> box etc.  If I think about the CBF module behind a form, it is instantly
> obvious that I am writing a class which models a form, AND EVERY combo,
> text box, radio button etc placed onto that form.  NOT GOOD!!!
>
> Convenient yes.  It allows us as nube programmers to get our feet wet
> writing event sinks, to learn event driven programming, to learn about the
> dozens of events for the dozens of controls, but hey... what a friggin mess
> we make as a result.  Microsoft did us all a favor with the CBF module
> behind forms, making all that "event sinking" stuff easy precisely so that
> we would learn it.  But... MSFT expects us to learn that stuff and then
> think about moving on.
>
> It isn't like I never did that CBF thing, I did!  For the first 10 years,
> the entire decade of the nineties I did exactly that.  Forms with dozens of
> controls embedded in them, with any events for any of those controls sunk
> directly in the CBF class module.  Code out the door and down the hall in
> every form.  There is a better way.
>
> Not a faster way, not more convenient in any given situation, not even
> appropriate in every given situation, but fundamentally better from an OOP
> perspective.   If the same code is in events in many forms, move those
> events into a clsFrm and have them written in one place.  Reference the
> class in the CBF and pass in a pointer to the form.  Sink those events in
> clsFrm now.  Voila, all that repetitive code in all those CBF modules is
> gone.  Which makes my code much more readable, much more maintainable.
>
> We can have a conversation about frameworks if we want.  We can discuss how
> it is done, why it is good, when it is and isn't useful.  What we can't do
> is discuss is how doing xyz is always better, because that isn't true.
>
> In this specific case, the toolbar thingie, it may not even work to try and
> do it from a class.  TBH I didn't even look or think about it.  I was
> addressing "can it be done" not "is that the best way".
>
> --
> John W. Colby
> Colby Consulting
> --
> AccessD mailing list
> AccessD at databaseadvisors.com
> https://databaseadvisors.com/mailman/listinfo/accessd
> Website: http://www.databaseadvisors.com
>


More information about the AccessD mailing list