Link to home
Start Free TrialLog in
Avatar of koughdur
koughdur

asked on

Microsoft Access 2010: Prevent Form Deactivate

I have developed an application using Microsoft Access 2010 with the 'Document Window Option' set to 'Tabbed Documents'.  Most of the time while the application is running multiple forms are up.  If a user starts to make a change to a record on one form, I would like to force them to either undo or complete that update before moving to another form.  There are a number of validations and additional updates that are triggered when an update on one form is completed.  I do not want the application/database left in an ambiguous state.

So far the best I can do is add a Form.Deactivate event to each of my forms and perform an Undo if the form is dirty.  I'm sure the users will not be entirely happy with this.  Is there a way to either lock out all of the other forms or cancel the deactivate event if the form is dirty?
Avatar of Jim Dettman (EE MVE)
Jim Dettman (EE MVE)
Flag of United States of America image

<<So far the best I can do is add a Form.Deactivate event to each of my forms and perform an Undo if the form is dirty.>>

  But you can also message them and tell them that the form is dirty, and if so do they want to save or cancel.  If save, then just force a save:

 Me.Dirty = False

Jim.
ASKER CERTIFIED SOLUTION
Avatar of Jim Dettman (EE MVE)
Jim Dettman (EE MVE)
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I find that in most cases, having multiple windows open simply causes confusion so I don't allow it.  I also don't use tabbed view but that is a different discussion.  When one form opens another, I have it hide itself and pass its name to the new form in the OpenArgs.  That way when the second form closes, it knows which form to return to.  On the rare occasions where I want multiple forms open at the same time, the first form opens the second in dialog mode so that although you can see both forms, you can only interact with the second one.  Also, don't forget when chaining forms to save the current record before opening the new form.  That solves the inconsistent state issue.
Avatar of koughdur
koughdur

ASKER

That's a good idea and will work for those forms where all of the code that is executed upon a save is the same.

I have one form where they are required to press different buttons in order to make certain changes.  A while back I tried to rewrite that code so that it could all go into a single routine that I could wrap in the AfterUpdate event.  However, there were too many combinations and permutations and so I just put code in the BeforeUpdate event to prevent saves when they tried to make changes without pressing the correct buttons.

Once they are in the Deactivate event code it seems there is no way to put the user back to the updated field so they can save data the proper way.  I was hoping by locking out all of the other forms or cancelling the deactivate that they would be forced to update the proper way.
Jim,

I actually tried the idea of setting a flag and moving focus back to the original form.  The problem is that moving to another form is moving off the record, so it activates my AfterUpdate code which causes problems if the code I've put under each of the buttons hasn't been executed prior to that.
Pat,

I used to not like tabbed views, but I have had all sorts of problems with tab controls.  I used to have a single form with subforms on tabbed pages but there are all sorts of issues with that.  I find that having separate forms with a tabbed view has all of the advantages of tab controls with no additional downsides.  The issues I'm having with moving from form to form are similar to the issues I've seen when moving from subform to subform within a form.
<<I have one form where they are required to press different buttons in order to make certain changes.>>

 So they can save in different ways?   Hum....well the second method would work.   No matter how they tried to move off the form, they'd be forced back.

<<Once they are in the Deactivate event code it seems there is no way to put the user back to the updated field so they can save data the proper way.  I was hoping by locking out all of the other forms or cancelling the deactivate that they would be forced to update the proper way. >>

That's why I suggested the second method.  You can hide the other forms or open in dialog mode as Pat suggested.  That does limit the user however.

I've usually leaned that anyway like Pat as I find most users get confused about what's going on,  but there are some apps where it simply makes sense to have multiple forms or you do need to multi-task a lot.

 When you do the chain method, it also is a bit cumbersome in that the user down the chain, and then backup to go anywhere.   I'm working on one app like that now where they want a tabbed style interface for just that reason.   it takes a lot of clicks to go anywhere and you can't leave anything unfinished.

So with all that said, why not leave it in the hands of the user?   How about visibly flagging the user that a form is dirty with something like changing the form caption?   Maybe putting an asterisk (*) in front of the form name?

 Or an a ontimer event, checking once a minute if any forms are dirty and giving them a message?

Jim.
<<The problem is that moving to another form is moving off the record, >>

 Not sure I understand that....switching forms should not cause a save.

Jim.
I am quite confused by your description of the app.  The BeforeUpdate event is the final event to run BEFORE a record is saved and is the place where you put all your final validation or any validation that involved multiple fields such as relationship tests or dates.  DateA must be > DateB for example.  Or FldA or FldB is required but not both.  HOW you get to this event is irrelevant.  The point is that the buck stops here.

Regarding the tab control, I use it extensively.  Once you understand that it doesn't impact anything else, you can pretty much ignore it although I did have one app where I did some fancy stuff like change the font color on certain tabs to indicate that their subforms contained data.  Although, I don't have a serious objection to the tabbed interface for a user view (I still usually hide all but the current form), I have serious objections to it as a design interface.  If it were possible to switch on the fly, I would probably have used the tabbed interface for apps that warranted it but I will NEVER use it as a design interface.  It is far too limiting to not actually be able to see multiple objects at once.  Having tabs for them doesn't cut it.  I want to be able to see multiple windows at once.
Jim,

Thanks for the suggestions.  I have five forms.  Four of them have simple save processes and so I used your first idea and prompt the user to Save/Undo the changes.

The fifth form has a rather complicated save process.  I was able to use your second method to fix that.  The reason my earlier attempt hadn't worked was because:

1. I set the flag in the BeforeUpdate event rather than the OnDirty event.  I incorrectly thought that the BeforeUpdate event fired as soon as fields in the record changed.

2. I was using the wrong method to force the user back to the original form.  When multiple forms are open, all I needed to do was execute Docmd.OpenForm for the original form and it would come to the front.  I had added code to also SetFocus to the form and a particular field which I believe was causing the BeforeUpdate event to fire.  By just "opening" the form I was able to move back to the original form without firing any events.

3. There was code in my original form's OnActivate event that was firing every time I  returned to the original form.  I skip this code now if I'm coming back to the form because the update was not complete.

Now it works as expected.  Thanks.
Pat,

I agree with you that tabbed documents are a pain when developing.  The last thing I do before releasing my app is to convert to tabbed documents.  The nice thing about tabbed documents for users is that they can only see one form at a time.  This somewhat limits what they can do and helps them focus on one form at a time.

The reason I went away from tab controls is because on small screens, when a user scrolls up/down the tabs disappear.  This was confusing some users.  The tabs for the tabbed documents view never disappear.  Also (and I know you are going to laugh at this) I like split forms.  Or at least my users do.  They are used to Excel and like to deal with spreadsheet like data, but Microsoft doesn't let us put split forms on tabbed pages.  Most of my forms are split forms, so I can have my tabs and split forms too by going with tabbed documents view.
The last thing I do before releasing my app is to convert to tabbed documents.
And then you never make a single design change after that?  As I said, I don't mind them as a user interface but until it doesn't required shutting down the app to change views, I'll stick with overlapping forms.
The nice thing about tabbed documents for users is that they can only see one form at a time.
But most apps allow multiple forms to be open which defeats the purpose.
They are used to Excel and like to deal with spreadsheet like data, but Microsoft doesn't let us put split forms on tabbed pages
I haven't tried this because I don't like "split forms" so I can't say that it will or won't work.  When I want the effect of a split form, I simply use two subforms.  I get what I want but don't have to deal with the quirks of the MS implementation and I can put them on tab pages.  The other reason that I rarely use split forms is because they imply an unfiltered recordsource.  And, since I almost always use SQL Server rather than ACE, I never use unfiltered recordsources.  A major advantage of moving to SQL Server is to improve performance so if you are bringing down ever record of a table because you are using a split form, you are not having the server do the heavy lifting.  You are bringing all the data from the table down to the local machine and that completely defeats the purpose of using a "real" server BE.