Free Lessons
Courses
Seminars
TechHelp
Fast Tips
Templates
Topic Index
Forum
ABCD
 
Home   Courses   Index   Templates   Seminars   TechHelp   Forums   Help   Contact   Join   Order   Logon  
 
Home > TechHelp > Directory > Access > Invoicing > < Switch Function | Templates >
Back to Invoicing    Comments List
Custom events make it better Upload Images   Link   Email  
Gary James       
10 months ago
Richard, over the past year Ive been absorbing your Access classes and Tech Help videos, and I want to thank you for making my journey into the world of database programming and design such a delight.

Coming from 40 years of programming in various languages such as C, C++, C#, PDP-11 Basic, Microsoft Basic, VB6, Visual Basic, Fortran 77, Forth, and Excel VBA, Ive come to appreciate the benefits that Object-Oriented languages have over the others.   With the OO design principles I leaned using C++ and C# Ive tried to apply as many of these I can to programs written in VB6 and VBA.    One of these principles is to try to encapsulate objects and the code that modifies them into the same code module.   In VBA this means that Forms and any program code that modifies their displays, all must exist in the Forms associated code modules.   By encapsulating the forms display and code into the same form module, form changes and code maintenance and upkeep becomes simpler and less error prone.   Which brings me to the point of this comment.

If my programs are designed so all the code that modifies a Forms display resides in the Forms associated code module, how do other elements of an Access program make changes to one or more open forms when their displays need to be updated?

Using object-oriented design principles this can be done in a couple different ways.   My forms could be designed with a programming API that provides Properties and Methods that other forms could access, or I could create a Custom Event system that every form attaches to upon loading, and detaches upon closure.  Of these two different techniques I believe the application specific Custom Event system is the better approach.    Using this method, forms that change table data or item selections can send a unique Event, to all other open forms sharing the same data or selections, to update their displays.   Open forms that recognize the event will act on it, while others will ignore it.   And the sender of the event can do this without any knowledge of what, if any, other forms are currently open and displayed on screen.
With this in mind I took your Order Entry and Invoicing free template and modified it to implement a custom event messaging system that updates all open forms that share similar data, if any make changes, additions or deletions to the data.   I also made the Order form track the currently selected Customer in the Customer form.

The following screenshots show the new Signals class module I added to the project, along with the addition of a couple of new global variables in the existing GloblMod module.   Other screen shots show how forms utilize the global Signals class object to send and receive the custom events.

Anyone who wants a copy of the modified template can simply make a request, and Ill be happy to email it.

Enjoy,
Gary James
Gary James       
10 months ago

Gary James       
10 months ago

Gary James       
10 months ago

Gary James       
10 months ago

Gary James       
10 months ago

Kevin Yip       
10 months ago
Class modules are for creating custom objects, such as plug-ins and such.  So a lot of Access third-party plug-in developers do that.  But for regular Access users, the built-in objects usually suffice.  They are users of an object-oriented system, but aren't object-oriented programmers themselves.  I used Access for decades in my old job and never had to create any custom objects.  And the objects I wished Access would have (such as the "Screen" object in VB.net, which controls multi-monitor setups) were beyond my capability to create.  Users of other general-purpose tools like Visual Studio may see a bigger need for OOP.
Gary James       
10 months ago
I think you missed the point of my Comment.   OOP isn't the point, what I'm primarily pointing out is that Access allows VBA programmers to take advantage of creating their own custom Events.   My example creates a Custom Event Class that Forms and Reports can take advantage of to route custom Events to all open Forms or Reports that have hooked themselves into the Event chain of the custom global event object.    Using this method of sending events to all hooked in listeners, a form can update every other open form or report that uses the forms data, when a change is made to the data.   The sending form knows nothing about who else is open, nor does it care.
Kevin Yip       
10 months ago
You don't go into class modules because Access "allows" them; you do it only if you must.  Adding class modules to create custom objects is complicated business, and I would only do it if existing Access objects can absolutely not do the job.  Even then, you still have to consider whether the time and effort you spend in creating and managing class modules commensurate with the advantages they give you.  If you are really in this position, and really find built-in objects lacking, then good for you.  But if I were working alongside you, I would be all over the worthiness of going into class modules; that was my point.

Most Access users think built-in objects already suffice.  That's why Richard doesn't have too many courses on class modules.  Also, his site focuses more on practical matters like invoicing, order entry, customer records, things of that nature, which have very few needs for class modules.  If this site were like Devhut, or about app creation, game creation, etc., areas that actually rely much on OOP, then I would think differently.  But then, we also likely wouldn't be talking about Access.
Gary James       
10 months ago
I completely disagree.   You use whatever tools are available to you to provide the user with the best application possible.   Saying that class modules are somehow spooky black magic that should be avoided at all cost shows a lack of understanding of advantages they offer.   In my example I took Rich's ORDER ENTRY template and through the use of an extremely simple class module, enhanced the program so that every form that's open is automatically updated to show changes to its data, made from any other open form.   No need for any refresh buttons to update form components, they are updated automatically.   That is a tremendous feature to omit because of fear of using VBA's support for classes that can provide custom events.
Gary James       
10 months ago
Take another look at my screenshots above.   The first two images show the entire class module, and the four functions and events it provides.   That's all there is.   No smoke and mirrors, yet the class provides a custom even system that allows forms to send events that can be processed or ignored in other forms, and allows a form to tell other listeners to refresh or requery their displays.
Kevin Yip       
10 months ago
The size of the code doesn't often commensurate with the time and effort put into it.  And the code in your pictures is NOT "all there is", because you have to reference your custom object in all your other code -- the same way we use Recordset object, Forms object, Me object, etc, *everywhere* in our VBA code.  That is why using an custom object (even a single one) complicates matters.  Once you created it, you have to deploy it all over your database.  If it's not something truly worthwhile, don't do it.

Creating and coding for custom objects takes more time and effort than using ready-made built-in objects.  That is just an mathematical certainty that is objectively true.  Extra time and effort mean extra money, and that matters to the people who sign the checks.  The people who visit this site are mostly professionals (or even business owners) who have jobs that rely on Access to do mission-critical tasks in economically feasible ways, and that's why I need to make this important point clear.  Again, use class modules only if you must, not if you just want to.
Gary James       
10 months ago
Kevin, it seems obvious to me that you've not even looked at the source code screenshots I've provided.   Your insistence that I've added complexity to the program is blatantly false.  Anything YOU would code in a program that updates all other open forms so they immediately show changes to table data, would be far more complex and require far more coding.   The event system is simple, elegant, and consistent with the way Windows and Access components source events indicating changes to their data.

The last two screenshots for the ProductF form show what's involved using the custom events.   A public Signals class object variable is declared  In the Form Load event the object is set to the global Signals class object in the GlobalMod module therefore hooking it into the event chain of that object.  In the form unload event the public class object is destroyed unhooking it from the event chain.  The rest of the code processes normal change events from the ProductF form to the Product Table data'  The code in these events make calls the the Signals object ForceRequery subroutine to broadcast an event telling any listeners that Product Table data has changed and to update their displays.   The  code also shows the form processing the Signals object ForceRequery event where it updates its own display in case another form had made changes to the Product Table data.

This entire process couldn't be simpler to get the job done of updating the displays of all open forms when any of them make changes to data shared by one or more forms.   I simply can't fathom your reluctance to use a programming tool that is built on the foundation of how all windows interface components interact with program code; through events (messages)
Kevin Yip       
10 months ago
I do understand what you're trying to do, as you already explained it in your first post.  Please stop saying I don't understand, because if that's your defense of your code's usefulness, then you don't have a defense.  Your defense should be actually regarding how USEFUL your creation is, instead of saying, oh, other people just don't get it.  From what I see and what you've posted, your custom object's usefulness doesn't seem to justify the work of creating custom objects -- the whole point of my previous posts.  

First of all, your code works on one PC only.  Wouldn't looping through the Forms collection accomplish the same thing?  The Forms collection already gives you access to all the controls on all the forms, so what exactly does a custom object add to here?  

Is requerying all the forms really needed here?  What if you update record 1 to 20, and other forms are browsing record 100 to 120, or 200 to 220, do they really need a requery?  Requerying them won't change the forms' content because records 100-120 and 200-220 haven't changed!  But it will degrade system performance if you requery N forms all at once, that's for sure.

And wouldn't it be more useful if your form updates could also refresh *remote* users' forms too, if all users share the same back end?  I'm sure that wouldn't need custom objects either.

And on and on.  There are many other what-ifs that I can think of, and I don't see your code doing any of that.  You need a really good reason to go into custom objects, that's all I'm saying.  Otherwise you would just add to the burden instead of lightening it.
Gary James       
10 months ago
Kevin, first off, I'm not providing a defense for anything.  I'm trying my best to help you understand just exactly what I'm doing.   This is probably my fault for not making my modified template file available from the start.    Without actually running the program and looking at the code, you can't see first hand what's going on.   From your reply I can see that the subtlety of what I'm trying to explain hasn't been made clear.

You said:

'Wouldn't looping through the Forms collection accomplish the same thing?  The Forms collection already gives you access to all the controls on all the forms, so what exactly does a custom object add to here?'  

The answer here is a resounding NO.  It is not the same thing.  It isn't even close.   Each form that's displaying table data may have several components that display data from different tables.  The form itself showing one type from Table A, a list box on that form another from Table B, and a combo box a third type from Table C.  Depending on the data table that's been updated, it would be wasteful to Requery the entire form, when a simple Refresh or Requery of a single component on the form would suffice.   So how would Form A know what unique components reside on Form B, and what their data types are, or whether they should be Refreshed or Requeried?   Only Form B knows this, so isn't it best to let Form B make the decision on what needs to be updated?   A single event with associated parameters can tell the form what needs updating and how to do it.

You also said:

'Is requerying all the forms really needed here?  What if you update record 1 to 20, and other forms are browsing record 100 to 120, or 200 to 220, do they really need a requery?  Requerying them won't change the forms' content because records 100-120 and 200-220 haven't changed!  But it will degrade system performance if you requery N forms all at once, that's for sure.'

My design doesn't Requery ALL THE FORMS.  It allows a form to broadcast an event that is only received by other Forms that have chosen to link into the event chain and sink that event.  No other forms ever get called.   And those forms that choose to sink the event have the choice of either Refreshing or Requerying the entire form or just one or more components of their display.   Also, Forms that are not displaying a record that's been modified, but are displaying others from the same table, still must be refreshed to pick up the changes made to the table when the modified record comes into view; for example a customer's address field has changed.   It's when the table has had a record added or deleted that the higher overhead Requery is needed.   Having the Form itself choose to Refresh or Requery will achieve the desired result with minimum overhead.

Lastly you said:

'First of all, your code works on one PC only.  '  And wouldn't it be more useful if your form updates could also refresh *remote* users' forms too, if all users share the same back end?  I'm sure that wouldn't need custom objects either.'
Regarding these statements, I'm not at all sure what you're referring to.   I wasn't aware that Access supported the ability of a Front-End application running on Machine A in the sales department could talk to a similar Front End application running on Machine B in marketing, or Machine C or whatever.   If that's not possible, then its not a problem or limitation when using an event class.

My modified template can be downloaded by pasting the following link into your web browser.   This is stored on my Microsoft OneDrive account.

https://1drv.ms/u/s!All2i2Lo--gxg2wRKRDNy1ktlZXZ

In addition to updating form displays when table data is changed, I've also made the Orders form track the Customer selection in the Customer form.   This could be further controlled with a checkbox to enable or disable the feature.
Kevin Yip       
10 months ago
You're free to do what you want, of course.  And I've already given my opinion, so I'm not going say any more on that.  But just to re-iterate to emphasize its importance: you don't mess with class modules unless it's really needed.  Custom objects force you code a certain way, and that's primarily what I don't like.  Unless it's really indispensable, I'm not going to restrict the way I code.  An indispensable object is usually sprawling, with tons of properties, methods, etc., that actually justify the object's existence.  Such an object is so important that the whole application wouldn't work without it -- such as the Recordset object, without which Access wouldn't work at all.
Gary James       
10 months ago
Kevin, as a prolific active and valuable contributor to Rich's Access Learning Zone I respect your opinion, but when it comes to the subject of VBA classes, and classes with events, I believe you're completely wrong.

You say that custom objects force you to code in a certain way and that you don't like that, but then you express enthusiasm for the Access Recordset objects.   Does that mean you dislike the powerful File System Object, or any of the other object libraries that can be Referenced in the VBA tools menu such as Microsoft Office, Word or Excel?   Main stream high level programming languages have all moved towards Object Oriented design methodology.  Any of today's DOT NET languages like Visual Basic and C# are totally built on class libraries.  Ever since VB6 was introduced I've written programs that make use of custom objects and objects with events.    Classes don't RESTRICT my code, they enhance it, and they can be as simple or complex as needed.    In VBA, Classes with Events are fundamentally no different that any visual input component you can place on a form; such as a textbox.   The only difference is a textbox gets its input from the user, and a class object with events gets its inputs programmatically from Properties or Methods.

Kevin, I'm not telling you that you're wrong in what you believe.  I'm telling you that you're wrong to tell me I'm wrong.
Richard Rost             
10 months ago
Oh boy... I'm too drugged up from my surgery to read all of that. LOL

As I've said in a few of my videos, Classes in VBA are possible, but in my near 30 years of working with Access, I've never NEEDED one. Granted most of the projects I build are for small businesses and don't need to be that complex. Yes, I too am a former C/C++ programmer before my days of VBA. I understand the value of classes, but I've always found ways to work without them using Access.

I'm sure you know this already, but you can refer to an open form's fields like this: Forms!CustomerF!FirstName - and you can execute public code on those forms like this: Forms!CustomerF.MarkActive - and that's generally been good enough for the projects I've built without needing to build custom event handlers and listeners.

HOWEVER, with that being said, I am very intrigued by what you've built, and after I am recuperated, I would love to take a look at it in more detail.

Gary James       
10 months ago
I wish you a speedy recover from your oral surgery.   I had both uppers and my right lower wisdom tooth removed; fortunately all at different times over several years.   The worst part is the amount of time it takes for the empty socket to heal shut.  You'll be drinking a lot of meals in the next couple of weeks.

I'd be more than happy to talk about the changes I made to your template whenever you feel up to it.   This is a technique I came up with for other programs that needed to update multiple windows when changes were made to data.   It's entirely based on the Windows messaging (Event) system that's the foundation of all windows programs.   You have my email address if you want to contact me directly.   Or if you want to talk details, I'll provide my phone number.   I'm retired now so I'm available almost any time of the day.   Good luck with the surgery.
Kevin Yip       
10 months ago
Hi Gary, when you use a custom object, you have to code in a syntax and nomenclature (custom properties, custom methods, etc.) that only work for that object and nothing else.  The more you code that way, the more your code will look like alien language:

   If MyStash.Weight > 1400 Then MyStash.JunkItems.DeleteAll Else ...

So I often ask myself how much alien language do I want to put in my code, and the answer is often none at all.  Even if someone else made a custom object, I still have to consider such implications before deploying it in my database.  That's why creating my own custom object has been a rare occurrence for me.

If I worked in the third-party Access plug-in market, I would definitely use custom objects, which would allow easy distribution of my work and easy deployment of my code for other users.


Gary James       
10 months ago
Rich, when you're feeling better after your surgery, this may be a simpler introduction to what I did, rather than the more complex code I added to the Order Entry template.    This is a basic Access project with two forms and no tables.   Each form has a textbox that you can type into.   Typing into either form's textbox updates the other forms textbox to the same text string.   Any number of similar forms could be easily added and they would automatically behave the same, updating all the other textboxes without any knowledge of who else is open and listening.   I've uploaded the project to my Microsoft OneDrive account, and can be downloaded by pasting the following link into your web browser.

https://1drv.ms/u/s!All2i2Lo--gxg208hge4o-7YUIHp?e=ugbyfP

Cheers,
Gary James       
10 months ago
I've updated the example database to better demonstrate that it makes no difference how many senders or listeners are hooked into the event chain.   This new example allows the user to dynamically create additional target forms that all behave the same way as the original TargetFormF form.   Use the same download link that I provided above.

'We've done the impossible, and that makes us mighty.' - Malcolm Reynolds
Gary James       
9 months ago
Rich, just curious, have you had a chance to look at my simple custom event example in the link above?    This has to be the easiest possible way to synchronize multiple open forms in a project without any of the forms needing to know anything about which other forms are currently open.    A simple subroutine call passing appropriate parameters will be automatically routed to each open form, or instantiated class object, where the arguments can tell the forms and objects what to do.
Richard Rost             
9 months ago
I have not yet. Sorry. It is on my to do list.
Gary James       
9 months ago
Ok thanks.  It's good to see by all your recent activity, that your oral surgery hasn't been holding you back.   By now the gums should be healing up nicely.
Richard Rost             
9 months ago
Yeah, I'm doing much better than I anticipated up front. I was able to talk and record video the next day. I still have to irrigate my "holes" after eating to keep food out of them, but they're closing up. :)

This thread is now CLOSED. If you wish to comment, start a NEW discussion in Invoicing.
 

 
 
 

The following is a paid advertisement
Computer Learning Zone is not responsible for any content shown or offers made by these ads.
 

Learn
 
Access - index
Excel - index
Word - index
Windows - index
PowerPoint - index
Photoshop - index
Visual Basic - index
ASP - index
Seminars
More...
Customers
 
Login
My Account
My Courses
Lost Password
Memberships
Student Databases
Change Email
Info
 
Latest News
New Releases
User Forums
Topic Glossary
Tips & Tricks
Search The Site
Code Vault
Collapse Menus
Help
 
Customer Support
Web Site Tour
FAQs
TechHelp
Consulting Services
About
 
Background
Testimonials
Jobs
Affiliate Program
Richard Rost
Free Lessons
Mailing List
PCResale.NET
Order
 
Video Tutorials
Handbooks
Memberships
Learning Connection
Idiot's Guide to Excel
Volume Discounts
Payment Info
Shipping
Terms of Sale
Contact
 
Contact Info
Support Policy
Mailing Address
Phone Number
Fax Number
Course Survey
Email Richard
[email protected]
Blog RSS Feed    YouTube Channel

LinkedIn
Copyright 2024 by Computer Learning Zone, Amicron, and Richard Rost. All Rights Reserved. Current Time: 5/21/2024 6:04:10 AM. PLT: 1s