BASIC was one of the first places ever to have exception
handling. That's had two effects:
1) Newer languages handle it better
2) There has been a lot added on and taken off over the years.
So you've got a lot of different choices about how you want to
do your exception handling, but you can't do it the way it was
originally designed, and you can't do it the way you would if
you designed it now, in hindsight.
So don't beat yourself up to much about 'proper' design of your
exception handling: you can't get there from here, and even if you
could, some one else would do it different.
For myself, I always capture the exception information and then
Raise all errors back up until they reach the user interface level.
The user interface level decides what if any message to display
or action to take.
And in general, I code my subroutines so that they can be exited
cleanly at any point, so I don't have to worry about clean-up
code.
However, this is not a popular style, and sometimes you do need
clean up code. The most common approach to handling clean-up
code in Access VBA, is to have separate 'catch' and 'always' sections
with your 'try' block. VBA doesn't support separate 'catch' and 'always'
sections in the same way that other languages do now, but there are
three methods that VBA does support
a) Use GOSUB for each try block. This method will amaze all your
friends and amuse your enemies. It works well in VBA but is not
required (and not supported) in any other language, so it's a linguistic
dead end.
b) Use a separate subroutine for each try block. This allows you to
put your 'catch' section inside the subroutine, and the 'always' section
outside the subroutine. This level of complexity is not often required.
c) Use a common 'catch' and 'always' block for all 'try' blocks in a
subroutine. This is the method you will most often see in Access
examples, and created by the Access wizards. If you want to have
multiple try blocks handled differently, you put code into the catch
and always blocks to determine the kind and location of the exception.
Sub fred
on error goto catch_block 'begin try block
do something
Always_block:
on error resume next 'end try block
clean up, close objects etc
exit sub
Catch_block:
display error messages, capture error log
roll back transactions, clear flags etc.
Resume Always_block.
End sub. 'end
You can put separate 'catch' and 'always' blocks into a subroutine,
but there is no way to nest them, and it quickly becomes tiresome.
Realistically, if you want separate catch blocks inside a subroutine,
it is better to put them in line. You do this by using
On Error Resume Next
and testing err.Number to catch exceptions. This is also the way
it is done in VBS, which doesn't support separate catch blocks
at all.
Use On Error Resume Next for inline exception handling, if that
is your preferred style.
Use a 'catch' and 'always' block to clean up code before exit.
From the catch block, resume to the always block.
You could easily use Resume Next if your 'try' block was a
single line, followed immediately by your 'always' block. Theoretically,
there is nothing wrong with that construct. But in reality, such code
is rare. If I saw such code, I would be more amazed by the code
than I would be by the exception handler. When you get to that point,
or if you feel comfortable with having amazing code, then you can
reconsider using 'resume next' :~)
(david)