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
> How To Pass An Error To Calling Code, Access 2003    
 
   
whdyck
post Jun 12 2019, 03:46 PM
Post#1



Posts: 323
Joined: 20-July 11
From: Winnipeg, MB, Canada


I have code in a textbox's AfterUpdate event handler that calls other code in a custom, external-module VBA function. That means that AfterUpdate calls the external VBA function, where, should it fail, its error handler handles the error and displays an error message.

Problem is that if user updates the textbox, then presses Shift+Enter (without tabbing off the textbox), the following sequence occurs:
1. Textbox.AfterUpdate fires first to complete the textbox update.
2. External VBA function fires, as called by Textbox.AfterUpdate.
3. External VBA function errors out and handles the error in its error handler.
4. External VBA function passes control back to the calling Textbox.AfterUpdate.
5. Form saves anyway, since it knows nothing about the error generated in the external module.

Bottom Line: An error occurred that should have prevented the form from saving, but it saved anyway.

Seems like I need a way to get info about the error back to the calling form to prevent the form from saving.

Any suggestions re how to do this?

Thanks for any help you can offer.

Wayne

Go to the top of the page
 
theDBguy
post Jun 12 2019, 03:52 PM
Post#2


Access Wiki and Forums Moderator
Posts: 75,778
Joined: 19-June 07
From: SunnySandyEggo


Hi Wayne. Maybe, maybe not. I can't tell you since I can't see what you're dealing with. Can you post a small demo? What happens if you simply remove the error handler from the module and let the calling routine handle it?

--------------------
Just my 2 cents... "And if I claim to be a wise man, it surely means that I don't know" - Kansas
Access Website | Access Blog | Email
Go to the top of the page
 
whdyck
post Jun 12 2019, 04:10 PM
Post#3



Posts: 323
Joined: 20-July 11
From: Winnipeg, MB, Canada


QUOTE
What happens if you simply remove the error handler from the module and let the calling routine handle it?

OK, I didn't tell all. I cannot remove the error handler from the called external-module function, since there's a lot of existing code that calls it and relies on its error handler to report any errors.

But what if I tried this:
Add an optional success/fail ByRef parameter on the external-module function that I can use to pass back status to the caller. When the textbox's AfterUpdate event calls the external-module function, it passes in its own module-level boolean variable that receives back the status of the called function's success/failure. If Form_BeforeUpdate sees the form's module-level success/fail variable set to false, it knows the called function failed, so it sets Cancel = True so the save aborts.

Does the above sound right, or am I speaking rubbish? I think I'll try it, but maybe there's a simpler or more straightforward way? (Seems kinda convoluted.)

Wayne
Go to the top of the page
 
theDBguy
post Jun 12 2019, 04:45 PM
Post#4


Access Wiki and Forums Moderator
Posts: 75,778
Joined: 19-June 07
From: SunnySandyEggo


Hi Wayne. No, not rubbish. Functions are designed to return a value (or something). You could also manipulate global variables while inside a function. So, you could either examine the returned value or check the variables from the calling routine.

--------------------
Just my 2 cents... "And if I claim to be a wise man, it surely means that I don't know" - Kansas
Access Website | Access Blog | Email
Go to the top of the page
 
PhilS
post Jun 13 2019, 02:07 AM
Post#5



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


QUOTE
You could also manipulate global variables while inside a function. So, you could either examine the returned value or check the variables from the calling routine.

Please don't. This creates hidden dependencies and tight coupling in your code that degrade its maintainability.

QUOTE
I cannot remove the error handler from the called external-module function, since there's a lot of existing code that calls it and relies on its error handler to report any errors.

But what if I tried this:
Add an optional success/fail ByRef parameter on the external-module function that I can use to pass back status to the caller. [...]

This approach is much better than global variables, but maybe more complicated than necessary.

What about this:
- You rename the original module function.
- Remove the error handler from the function
- Create a new function with the original name. This function only calls the renamed original function and handles any errors.
- Now your existing code works as before. The Textbox.AfterUpdate proc calls the new function without the error handling.

The feasibility of this approach depends on the exact implementation of the error handling, of course. But in many cases it should work as intended and will take only a few minutes to implement.

--------------------
Go to the top of the page
 
gemmathehusky
post Jun 13 2019, 04:27 AM
Post#6


UtterAccess VIP
Posts: 4,725
Joined: 5-June 07
From: UK


there is no reason why your form shouldn't know about the error in the external process. If it needs to know, then you need a way to report the error.

QUOTE
1. Textbox.AfterUpdate fires first to complete the textbox update.
2. External VBA function fires, as called by Textbox.AfterUpdate. - see below regarding beforeupdate, not afterupdate
3. External VBA function errors out and handles the error in its error handler. - you may need to consider the process, as you really shouldn't be getting errors at this point.
4. External VBA function passes control back to the calling Textbox.AfterUpdate.
5. Form saves anyway, since it knows nothing about the error generated in the external module. - you need to pass the success/failure report back to the calling process


first - the textbox beforeupdate (not the afterupdate) should manage any validation steps, as this is cancel-able
Your Note 5 - A record WILL SAVE, unless you cancel an update, and you can't cancel an AFTER UPDATE event, which happens only AFTER the entry is accepted.

the textbox afterupdate should just attend to any follow up stuff depending on your process. When the afterupdate runs, the textbox has already been updated, so errors in the after update won't affect the textbox value, although they may still be important.

[So, repeating myself somewhat - the record on the form is not ACTUALLY saved until you do something that causes the record to save, such as moving to a new record. Is that what shift-enter does? At that point the form before_update fires, and if not cancelled, the form after_update fires. (if you have these events - if not , the record just saves.) I don't use shift+enter, but if that tries to save the record, then I assume that cancelling an entry in a before update WILL prevent the record saving, and prevent the user moving off the current record, until the record is validated. But it has to be a before update, and not an after update]


so if one of your processes is calling a function, then you need to return a value for the function - so that it DOES know there was a problem.

simply a true/false boolean
CODE

if myafterupdateprocess(arguments) = false then
     'handle error appropriately
end if


or return a value if you have multiple possible results
CODE
select case myafterupdateprocess(arguments)
      case 0; 'ok
      case 1: 'some error
end select


So the calling form SHOULD know about any issues raised in functions. You can even signal errors in subs, (rather than functions) but you would need to set a public variable "flag" to indicate the circumstance - or change a ByRef argument to the sub (which I do not like personally).

finally, if you have a rte in a process, and transfer control to a error handler, then try to exit the error handler as quickly as possible. Do VERY LITTLE in a error handler - in particular, note that error handler code is not re-entrant, and you just cannot raise a second error within a error handler. To exit a error handler you need to exit the sub, or issue the command "resume (label)" to allow the code error handler to become active again.

finally - out of interest - what sort of errors are you getting in the function/ after update event that are causing the problems in the first place?

--------------------
Dave (Male)

(Gemma was my dog)
Go to the top of the page
 
kfield7
post Jun 13 2019, 08:55 AM
Post#7



Posts: 971
Joined: 12-November 03
From: Iowa Lot


An alternative to using a global variable is to pass a variable to the function that can be updated.

function myfunction(sMyError, stuff, more stuff) as whatever

Go to the top of the page
 
whdyck
post Jun 13 2019, 01:15 PM
Post#8



Posts: 323
Joined: 20-July 11
From: Winnipeg, MB, Canada


QUOTE
first - the textbox beforeupdate (not the afterupdate) should manage any validation steps, as this is cancel-able

textbox_AfterUpdate does not do validation--in my case, textbox stores a date/time, which, after update, is used to retrieve the odometer reading of that vehicle as of the date/time in the textbox. Textbox_AfterUpdate retrieves the odometer reading from the website of our Automated Vehicle Locator vendor so that it can auto-populate the odometer value in the form.

Shift+Enter saves in Access 2003; I believe that's default Access behaviour. In my case, if I press Shift+Enter after entering the date in the textbox (but before tabbing off it), Access needs to do two things, in order:
1. Run Textbox_AfterUpdate
2. Save the form.
In retrospect, I suppose not getting an odometer value from the vendor (which is only a default value--user can still enter it manuallly) might not be considered an error, and I should let the form save anyway.

In any case, if I'm calling code in Textbox_AfterUpdate during a save, the calling form needs to know if the call failed so it can abort the save in Form_BeforeUpdate(), which I think we all agree.

QUOTE
finally - out of interest - what sort of errors are you getting in the function/ after update event that are causing the problems in the first place?

The most common is a timeout error when trying to access our AVL vendor's website thru the firewall, although it doesn't happen very often.

Thanks.

Wayne
Go to the top of the page
 
whdyck
post Jun 13 2019, 01:17 PM
Post#9



Posts: 323
Joined: 20-July 11
From: Winnipeg, MB, Canada


QUOTE
What about this:
- You rename the original module function.
- Remove the error handler from the function
- Create a new function with the original name. This function only calls the renamed original function and handles any errors.
- Now your existing code works as before. The Textbox.AfterUpdate proc calls the new function without the error handling.

I think this should work, and I like the approach.

Thanks for the suggestion.

Wayne
Go to the top of the page
 


Custom Search


RSSSearch   Top   Lo-Fi    23rd July 2019 - 08:21 AM