?
Solved

Exiting All Subs

Posted on 2005-03-31
12
Medium Priority
?
635 Views
Last Modified: 2012-06-27
I run into this problem quite often.  Let's say that I call one sub from inside another and in the called sub I encounter a situation so that I want to exit all the subs (the called and the calling).  If I do "Exit Sub" it only exits the called sub, not the sub doing the calling.  The only way that I can think of to exit the calling sub is to turn some public boolean variable to false before I exit the called sub.  That way when I test the variable in the calling sub and if has been turned to false exit that sub as well.  Is there a statement that I can use from within the called sub that will exit not only itself but also whatever sub called it?  

Thanks
Kyle

PS.  I am by no means an expert programmer so please tell me how people that know what they're doing usually handle this situation.  Should I be structuring my code differently?  Should I always be making my tests in the main sub so that, if I do have to exit, I don't have to worry about exiting more than one sub?
0
Comment
Question by:kgerb
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 3
  • +2
12 Comments
 
LVL 11

Accepted Solution

by:
bingie earned 252 total points
ID: 13677612
The only thing you can do (as far as I can remember) is to have the boolean variable you suggested.

You can change you sub's into boolean functions, and if the function returns false - you can have it exit the calling sub.
0
 
LVL 12

Author Comment

by:kgerb
ID: 13677826
Thanks for the help bingie!
I hadn't thought of changing my subs to boolean functions.  I'm going to leave this Q open until tomorrow in case anybody else has any other ideas.  Thanks again:)
0
 
LVL 14

Assisted Solution

by:Shiju Sasidharan
Shiju Sasidharan earned 248 total points
ID: 13678207
Hi kgerb
ur current method is good.

well, here is another idea

place on error goto statement only in the top level sub routine
and when u want to return from other functions , explicitly raise an error
and catch that error in the top level sub routine and resume next statement
here is a simple example. Here i used a sample number 1111 to raise event
use a number that normally other errors can get
in other words here u can use
        Err.Raise 1111
 as a return statement from all sub level routines
try this ..
'=======================================
Private Sub Command1_Click()
    Call Test1
End Sub

Private Sub Test1()
'Top level sub

On Error GoTo Last:
    Debug.Print "From Test1"
    Call Test2
    Debug.Print "Test1 Continue..."
Last:
    If Err.Number = 1111 Then
        Err.Clear
        Resume Next
    End If
End Sub

Private Sub Test2()
    Debug.Print "From Test2"
    Call Test3
End Sub
Private Sub Test3()
    Debug.Print "From Test3"
    Err.Raise 1111
    Test4
End Sub
Private Sub Test4()
    Debug.Print "From Test4"
    Test5
End Sub
Private Sub Test5()
    Debug.Print "From Test5"
End Sub
'========================================

i hope this will help u

;-)
Shiju
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 14

Expert Comment

by:Shiju Sasidharan
ID: 13678226
hi
for more clarification use these
'=========================
Private Sub Command1_Click()
    Call Test1
End Sub
Private Sub Test1()
On Error GoTo Last:
    Debug.Print "From Test1"
    Call Test2
    Debug.Print "Test1 End"
Last:
    If Err.Number = 1111 Then
        Err.Clear
        Resume Next
    End If
End Sub
Private Sub Test2()
    Debug.Print "From Test2"
    Call Test3
    Debug.Print "Test2 End"
End Sub
Private Sub Test3()
    Debug.Print "From Test3"
    Err.Raise 1111
    Test4
    Debug.Print "Test3 End"
End Sub
Private Sub Test4()
    Debug.Print "From Test4"
    Test5
    Debug.Print "Test4 End"
End Sub
Private Sub Test5()
    Debug.Print "From Test5"
    Debug.Print "Test5 End"
End Sub
'=========================
;-)
Shiju
0
 
LVL 8

Assisted Solution

by:anthonywjones66
anthonywjones66 earned 252 total points
ID: 13679207
Just to amplify Shiju's solution which is likely the correct one.

This sounds like exception handling.  That is code discovers a problem with data which means that it can't continue with it's normal operation.

In this case you ought to raise an error as in Shiju's response.  It is common to see Subs become functions so that they can return error status codes so you end up with code like:-

Private Function Test2() as Long
  Dim lResult as Long
  lResult = Test3()
  If lResult <> 0 Then
    Test2 = lResult
  Else
     ' continue
  End If
End Function

As you can see the code bloats quite a lot with clutter which is only designed to handle expectional circumstances and obscures the primary (nominal) function of the code.

If you develop an architecture of using returned error status codes you also end up with another problem.  What happens if you have a procedure which true is a function. Eg.  A CalcTotal should return a total value for something.  In natural use you would want:-

sngTotal = CalcTotal()

But if you have already allocated all return values as error status then you would have:-

lResult = CalcTotal(sngTotal)

and CalcTotal will have to modify a parameter.  This is unnatural and again makes the code much harder to read (we tend to assume most parameters to be input values).

Anthony.

0
 
LVL 16

Assisted Solution

by:jimbobmcgee
jimbobmcgee earned 248 total points
ID: 13680519
>>  What happens if you have a procedure which true is a function.

Instead, you make all functions return an error status and pass your output variable as a pointer (ByRef argument).  For example:

    Function CalcTotal(ByVal in_nNum1 As Long, ByVal in_nNum2 As Long, ByRef out_p_nTotal) As Boolean

        On Error Goto CalcTotal_Error:

        out_p_nTotal = in_nNum1 / in_nNum2
        CalcTotal = True

    CalcTotal_Error:
        CalcTotal = False

    End Function

    Private Sub Button_Click()

        Dim nRetVal
       
        If CalcTotal(5, 3, nRetVal) = True Then
           MsgBox "Result: " & nRetVal
        Else
           MsgBox "Error"
        End If

        If CalcTotal(5, 0, nRetVal) = True Then
           MsgBox "Result: " & nRetVal
        Else
           MsgBox "Error"
        End If

    End Sub

Clicking the button will give the following results:

    1.6666666666666666666666666666667
    Error

Better alternatives would be to make te function return a Long value and set it to Err.Number -- then you can tell exactly what error occured.

HTH

J.
0
 
LVL 8

Expert Comment

by:anthonywjones66
ID: 13680669
J.,

I was trying to point out (obviously not successfully) that using the return value as an error status in a language that has adequate exception handling mechanisms already in place is poor design.  It leads to confusing code where the normal flow of execution is cluttered with code designed only to handlle exceptional cases.

We expect functions to munge input parameters and return a resulting value.  y = fn(x)  is a convention nearly all in the engineering and technical fields have come to be familar with.  err = fn(x, y)  is a little harder to understand on first sight.  The reader is forced to remember (or delve into the code of fn to discover) that y is in fact the true value we want back. Also code is much easier to read (maintian/modify) if the lines following the call to fn is relevant to the task at hand.

It may seem a small matter of style but these little things can have a cumaltive effect which can ultimately end with code becoming unmaintainable and buggy, that can get expensive.

Anthony.


0
 
LVL 12

Author Comment

by:kgerb
ID: 13690051
Thank you all for your comments.  They were very helpful and opened my eyes to new possibilities.

Anthony,
I think you made an excellent point with your last comment.  I can tell that you have a vast amount of experience from which you draw when you write about this kind of thing.  I am still very much learing about programming but, considering everybody I work with knows 0, I know infinitely more than they do.  The last thing that I want to do is write confusing code that would cause them diffiiculty if they ever had to modify anything I created.

Thanks again to you all for the comments

Kyle
0
 
LVL 14

Expert Comment

by:Shiju Sasidharan
ID: 13691029
Hi
>>The last thing that I want to do is write confusing code that would cause them diffiiculty if they ever had to modify anything I created

in my view code must be crystal clear - logically and methodogically
never try to write complexly, try to write more complex problems more simple  ;-)
0
 
LVL 16

Expert Comment

by:jimbobmcgee
ID: 13693942
anthonywjones66;

I agree with the principals of clear codin.  However, in this case, the available error handling in VB6 is not sufficient for the needs of the user (namely, kgerb).  It is indeed more confusing to use err = doit(in1, in2, p_out).  Confusion can be greatly reduced with the aid of a consistent, strong naming convention and a decent amount of commenting.  This method also allows you to have multiple outputs, too.

Don't feel that have not taken your comments on board but, please don't take me for someone who hasn't experienced these problems, myself.  As we all know, there are limits to the functionality of functions and we can only work with the tools we have.  Returning an error code/boolean is the cleanest way to evaluate the success of a process.  Until, that is, they come up with functions that can return multiple values.

The only true answer to the problem you are describing is make sure the documentation and inline commenting is detailed.  

But we all do that anyway, don't we?

J.
0
 
LVL 8

Expert Comment

by:anthonywjones66
ID: 13701710
J.,

I guess we could get into bun fight over this but the crux of it is that you don't feel that the VB6 error handling is sufficient in this case whereas I do.  In fact kgerb didn't provide any details either way hence I was just guessing, quoting from my original post, 'this sounds like ...'.

Multiple values from functions?  Type, Object or array depending on your requirements but I would conceed that these can seem a bit heavy at times.  Problem is that this is a slippery slope.  E.g, It may be tempting at times use those 'output' parameters as inputs also.  Before we know it variables are seemingly changing value of their own free will because we forgot that a certain 'function' modifies some of it's parameters.  More bugs, more time, more expense.

Documentation?   Yep all for that especially for general coding standards and practices.

Commenting....  well that's just another can of worms I don't think I'll open right now :)

Anthony.
0
 
LVL 16

Expert Comment

by:jimbobmcgee
ID: 13777542
Let he who has ever written the perfect error handler cast the first bun...

You're right, I don't think the VB error handler is as good as it could be -- it was (and is) sufficient but has been surpassed with things such as Try/Catch...

I also agree that you shouldn't cross-use input and output parameters -- DirectX, for example, is a nightmare for it.  Then again, how often have we all used y = y + x?

Type, Object and arrays are all useful in related outputs but not really for (y, err) = f(x).  Perhaps, instead, a concept of func(ByVal x, ByRef p_Err) is more readable...

The world would be a better place with sufficient commenting but I, too, didn't bring my can-opener...

J.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses
Course of the Month8 days, 16 hours left to enroll

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question