UtterAccess.com
X   Site Message
(Message will auto close in 2 seconds)

Welcome to UtterAccess! Please ( Login   or   Register )

Custom Search
 
   Reply to this topicStart new topic
> Custom Events, Any Version    
 
   
pdanes
post Dec 24 2017, 07:27 PM
Post#1



Posts: 81
Joined: 19-June 10



I'm trying to get a grip on custom events in VBA. I've scoured endless sources on the net, studied my manuals, experimented with everything I can think of, and success is still somewhat tenuous.

Exactly what I hope to accomplish is not all that complicated, and seems like it should be ideal for custom event routines. I have main forms with comboboxes and listboxes fed from tables or queries. The user can open various dialog boxes and do things to modify the tables. When that activity is done, I would like to requery the box(es) affected by any such activity. The way I have done it in the past was to set a global 'SourceHasChanged' Boolean variable and check its status upon returning from the dialog. It works, but is a bit unwieldy, so I decided to try replacing this with custom events.

Hours of studying and endless dead-end tries and repeats have finally produced the following bits of code. They do nothing spectacular. There is a table called T. The dialog form adds records on each click of the Add button. The main form has another button that deletes all but the first record in the table. Each set of code is supposed to fire an event indicating that the listbox is to be requeried. The code in the main form does okay, but the code in the dialog refuses to activate the StalaSeZmena event. Obviously (I think, anyway), that's because the dialog from creates a new instance of the class module. But I have to have a WithEvents variable in the dialog form. If I don't, I would have to make a reference to the WithEvents variable in the main form. Requiring forms to know that much about each other is exactly back-asswards from what I thought the custom event route was going to accomplish. It would be easier and less confusing to just stay with a global status variable.

Class Module [Zmena]
CODE
Public WithEvents Udalost As HlaseniZmeny
Private Sub Udalost_StalaSeZmena()
Form_Mane.lstS.Requery
Debug.Print "Requery via class module"
End Sub


Class Module [HlaseniZmeny]
CODE
Public Event StalaSeZmena()
Public Sub OhlasitZmenu()
RaiseEvent StalaSeZmena
End Sub


Regular Module
CODE
Public chg As Zmena


Form Code [Mane]
CODE
Private WithEvents chgMane As HlaseniZmeny
Private Sub cmdCallDialog_Click()
DoCmd.OpenForm "Dia", acNormal, , , , acDialog
End Sub

Private Sub cmdShrinkT_Click()
CurrentDb.Execute "Delete * From T Where Pole1 <> 'A'"
chgMane.OhlasitZmenu
End Sub

Private Sub Form_Open(Cancel As Integer)
Me.Label1.Caption = Me.SpinButton1.Value
Set chg = New Zmena
Set chgMane = New HlaseniZmeny
Set chg.Udalost = chgMane
End Sub

Private Sub chgMane_StalaSeZmena()
lstS.Requery
Debug.Print "Requery from event on main"
End Sub


Form Code [Dia]
CODE
Private WithEvents chgDia As HlaseniZmeny
Private Sub cmdAdd_Click()
CurrentDb.Execute "Insert Into T (Pole1) Values(chr(asc('" & DMax("Pole1", "T", "Pole1") & "')+1))"
Set chgDia = New HlaseniZmeny
Set chg.Udalost = chgDia
chgDia.OhlasitZmenu
Set chgDia = Nothing
End Sub


It's functional, but feels awkward, clunky and not at all intuitive, like scratching my left ear with my right foot. The class module has a reference to the main form, which violates the principle of encapsulation, but I found no way to make the dialog form activate the event routine in the main form. I have to have a global variable to link the two WithEvents variables to, or nothing works, but this also violates encapsulation.

Is this really how these constructs are supposed to operate, or have I accidentally stumbled onto a Mad-Max version that happens to work, but isn't the proper way to build such procedures?
Go to the top of the page
 
ranman256
post Jan 2 2018, 07:35 AM
Post#2



Posts: 867
Joined: 25-April 14



I dont see the need for custom events.
Ive never seen a normal event that could not accomplish the desired tasks.
Go to the top of the page
 
Jeff B.
post Jan 2 2018, 08:03 AM
Post#3


UtterAccess VIP
Posts: 10,065
Joined: 30-April 10
From: Pacific NorthWet


Giving users the ability to modify table design in Access (if I'm interpreting your description accurately) is not a good idea. Access is a relational database, not a spreadsheet-on-steroids. Even if you/the developer created a beautifully normalized relational table design, the first user who does NOT understand relational database design will muck it up!

... or maybe I'm reacting to insufficient caffeine this morning ...

--------------------
Regards

Jeff Boyce
Microsoft Access MVP (2002-2015)

Mention of hardware or software is, in no way, an endorsement thereof. The FTC of the USA made this disclaimer necessary/possible.
Go to the top of the page
 
PhilS
post Jan 2 2018, 09:23 AM
Post#4



Posts: 484
Joined: 26-May 15
From: The middle of Germany


Well, I'm not entirely sure where the core problem lies.

If you are looking for a concrete solution to the illustrated problem of re-querying forms after data has been modified in a dialog, you might not need custom (or any) events at all. Just requery the source form after the dialog was closed.
I recently published a video tutorial on dialog forms. That should answer most of the potential questions in that regard.

If you rather want to understand and/or practice working with custom events, there recently was a discussion about custom form events here on UA. That should give you some hints.
The core problem seems to be that you need a publicly available variable as your event source. But, frankly, I do not fully understand your description of the scenario and the intended use case.
Quite some time ago I wrote a text about dealing with events from multiple source objects. That is not exactly your scenario, but if I understand your requirements correctly, it shows an approach to solve at least part of your problem.

--------------------
Go to the top of the page
 
pdanes
post Jan 4 2018, 08:05 AM
Post#5



Posts: 81
Joined: 19-June 10



ranman256: I don't know that I necessarily "need" custom events, but it seemed like a good way to accomplish the task (if I could get it to work). If you know of a way to do it with regular events, I'd be happy to hear about it.


Jeff B.: I'm not giving the users any ability to modify a table design (I hope), nor do I have any desire to do so. When I wrote 'modify the tables', I meant the data in the tables, not their structure. Sorry if I was unclear on that point. Maybe 'update the tables' would have been better wording.


PhilS: Yes, I know I can requery a control after closing a form. That is the way I have been doing it so far. But that requires either setting some global 'modified' flag, or just always requerying the control, regardless of whether anything was changed. And it requires the point where the form is called to know about every possible control that was impacted by the called form. Using events I thought would fix that, since each control could listen for anything that would affect its contents, and do its own requery when necessary. The user alters something in a table, that action broadcasts the event "Table X has changed", and anything using that table would be triggered to re-scan it.

That is what my reading has indicated should be possible with custom events, and what I hoped to accomplish. However, it still doesn't work the way I think it should, and I don't know if I'm doing something stupid, or if I misunderstood how custom events are supposed to work.
Go to the top of the page
 


Custom Search
RSSSearch   Top   Lo-Fi    19th July 2018 - 08:23 PM