VBA: Break Out of Deeply Nested If Statements - vba

Typically when I want to break out of a statement I just set a boolean flag for control flow, but I have a special case with many nested If statements and I'd really like to have a way to break out of several with one simple statement.
In Java you can name a loop and then break to that location; is there anything like that for VBA that can be used from a deeply nested location in If statements? I know VBA has the Exit statement for loops (while, for, etc), so I'm wondering if there is something similar for Ifs.
Ideally I'd like to do something this:
If ...
*NAMED_IF*
If ...
If ...
:
*break out of NAMED_IF*
:
End If
End If
*Now We end up at this control position*
End If

There isn't an if-statement specific method to break out of nested if-statements, but you could use the GoTo-statement instead:
If ...
'*NAMED_IF*
If ...
If ...
'*break out of NAMED_IF*'
GoTo GoToHere
End If
End If
End If
'*Now We end up at this control position*
GoToHere:

Related

VBA: nested With with If statement

Is nested With allowed in VBA? If it is, how to use it with IF statement?
I have the following nested With combined with If statement and compiler gave me an error message saying "End With without With".
With
If
With
End With
Else
End With <- End With without With
End If
I put the first With outside the IF statement because the IF statement can use it. Since the above code didn't work, I tried a different way. Another error message was obtained if I moved the first With inside the IF statement. This time, the error message says "Else without If". That leads me to wonder if nested With is allowed in VBA.
A google search turned up one hit, which is not exactly the same as my problem.
Try like below
With
If <Logical Test> Then
With
'Your action here
End With
Else
'Your other actions here.
End If
End With
The With End With structure applies to the current scope only. The scope of if else is different to else endif. Thus the with should either encompass the whole if statement or appear seperately in each scope.
It's perfectly possible to have a with end with nested inside other With End With structures. In this case you have to remember that the leading . Refers to the current scope.

What's the difference between GoTo, using a Select, and using separate function?

To start off, I know that using Goto is never a good idea. But I'm having a hard time seeing the difference between the following structures...All of them process conditions sequentially, stop processing when they find a true value, then return control to a specified location in the code (the next line, as that's where this particular 'GoTo' target is). What is the difference between:
Ifs with GoTo:
If ConditionA then 'This is designed to skip the evaluation of condition B if condition A is met.
Do something
Goto Resume
End If
If ConditionB then
Do something
Goto Resume
End If
Resume:
Select Case:
Select ConditionIsTrue 'This will also skip the evaluation of B if A is true.
Case A
Do something
Case B
Do something
End select
Separate sub:
EvaluateConditions(condition)
Sub EvaluateConditions(condition)
If A then
DoSomething
Exit Sub
End If
If B then
DoSomething
Exit Sub
End If
End Sub
In general,
'goto' transfers the control of execution to the label that you are assigning. The control never comes back to where you use 'goto'. As the program flow is altered altogether, it is not advisable to use 'goto'. It becomes hard to debug.
When you write a subroutine and call it from other part of your code, the control is transferred back to the called part of your code once the execution of subroutine is complete. Hence, unlike goto, the program flow will not be affected and is always advisable to use subroutines instead of goto.
In case of select statement, it is not much different from multiple 'if-else' statements. Instead of having too many 'if-else' you can use 'select' to have a more cleaner code.
Being specific to what you have asked, all three does the same and there is no difference as such. What you choose depends on your requirement, number of conditions, re-usability of the piece of code and future enhancements.
If you have a very few conditions ( 2 or 3) and if you are sure that the piece of code doesn't require future enhancements, it is 'ok' to use goto.(still not a great choice)
If the piece of code should be reusable or even otherwise, using subroutine is the best choice. In fact, even if you have a very few conditions, it is better to use 'select' statement within the subroutine so that your code looks clean and is easy to add further conditions in future.

What are a good No OP operation for vb.net?

Something we can just put break point on while making sure it doesn't do anything else.
In c, that would be while(false);
What to do in vb.net?
If you always need it to break there you can put
Stop or Debugger.Break()
If you really want a No-Op for some reason (could this turn into a contest for the most ineffectual single line of code?!), how about these?
System.Threading.Thread.Sleep(1) - 1ms is unlikely to have a huge impact outside of a loop
Debug.Write("") - doesn't appear to output anything.
There is a legitimate use-case for this.
When a temporary breakpoint is required after the statement of interest and this is the last line inside an if statement, an extra no-op type statement is required to place the temporary breakpoint on.
In this case I use:
If someCondition >0 Then
doSomething
Space (1) 'Dummy line to place breakpoint
End If
This returns a string containing one space, but does not assign it to anything. I use it in VBA, but it's also supported in .net
My two cents...
You can combine any series of commands onto one line with colons:
If False Then : End If
Select Case False : Case Else : End Select
I've also made it into a sub. Then it gets a recognizable name of own:
'Definition...
Public Sub noop () 'Or Private, Protected, etc.
End Sub
'Usage...
Sub Main()
If sometest Then
noop
Else
MsgBox "test is false"
End If
End Sub
Very strange question, you could place a BreakPoint about anywhere in the code. But here are some useless lines :
Do While False
Loop
While False
End While
Even the following :
Dim hello = Nothing
Or this :
Format("", "")
A no-op statement is also useful as an aid to document code nicely and make it more easily understandable. You could for example put in a statement like A = A.
For example:
If MyNumber => 100 then A = A
Else:
I know this is an old query, but for what it is worth, my preferred solution to the original question is
Debug.Assert (vbTrue)
If you wanted, you could use a variable instead of vbTrue and then enable/disable all breakpoints in your code by changing one variable
Dim bDisableBreakpoints as Boolean: bDisableBreakpoints = vbTrue
'your code here
Debug.Assert (bDisableBreakpoints)
'rest of your code
Simply change bDisableBreakpoints to vbFalse and the breakpoints will be set wherever you have used Debug.Assert
My personal favorite is
dim b=1
Then I put a breakpoint there.

Is there any limitation for IF condition while using "OR" in vb?

In my code i want to use if condition. In which i want to use "OR" around 18 times.
Like for e.g.
If a="something" or a="something" or a="something" or.........(up to 18 times)... then
'do nothing
else
'do action
end if
[Note : value of a is changing in For loop every time]
so i just want to ask does there any limitation in IF for using OR in limited times.
OR is there any other better way to do the same.
Thanks
As far as I know, there is no limitation when using OR this way.
Yet, you may consider alternative ways of coding this.
Negating a condition using Not
First, if you do nothing in the first case, then consider using the Not statement:
If Not True Then
'do somethin
'no else
End If
Consider using Select Case
Second, if you are checking the very same variable, you could either consider using a Select Case but it doesn't seem appropriate in your case if you have only one case.
Try to use a search
Eventually, if you are checking strings, you could probably better use a search within an array (with Application.Match if you are within Excel or .Contains) or within a String using Instr.
Using a collection or a dictionary
[EDIT] Another very good way to handle this would be to use the Dictionary Structure of VBA and check if a exists (see MSDN for some information).
This answer is just an elaboration on my comments to JMay, full credit to him. I think the original poster meant to the "Something" in his question differ, with a being the loop variable.
For each a in MyList
Select Case a
Case "something", "something2", "something3", "something4", "something5", _
"something6", "something7", "something8", "something9", "something10", _
"something11", "something12", "something13", "something14", "something15", _
"something16", "something17", "something18"
'DO NOTHING
Case Else
'do-something code goes here
' and here
' and here
' and here
End Select
Next a

VB.Net's For Next

Is there a difference between these?
For i = 0 To Something.Length - 1
'do something
Next
For i = 0 To Something.Length - 1
'do something
Next i
It is only for readability:
You can optionally specify counter in the Next statement. This improves the readability of your program, especially if you have nested For loops. You must specify the same variable as the one that appears in the corresponding For statement.
From http://msdn.microsoft.com/en-us/library/5z06z1kb.aspx
Nope. There is no difference. Even with nested loops there is no difference because nested for-loops cannot overlap.