Remove repetition from if-else statement - vb.net

I have written an if...else statement which uses an array myArr and a string myStr as follows:
If myArr.Length > 0 AndAlso myArr(0) = "-1" Then
'Do stuff 1
ElseIf myStr= "xyz" Then
'Do stuff 2
ElseIf myArr.Length > 0 Then
'Do Stuff 3
Else
'Do Nothing
End If
It works exactly as I need. But It looks really confusing, mostly because the array length is checked twice. There must be a clearer way to write it, but I can't think of one.
Just to clarify.... the order that each statement is executed is crucial. i.e. Stuff 1 has priority over stuff 2, which has priority over stuff 3.

I don't think you'll be able to get exactly the same flow in a simpler way.
Either you're going to end up doing things different things, or doing duplicate things. eg:
If myArr.Length > 0 Then
If myArr(0) = "-1" Then
'Do stuff
Else
'Do stuff
End If
ElseIf myStr= "xyz" Then
'Do stuff
Else
'Do Nothing
End If
This will cause mystr="xyz" not to happen whenn myArr(0) <> -1 whereas it may have before.

You might be able to get rid of multiple checks against myArr.Length by using nested If statements, but this makes the code less clear.
A clear approach (i.e. one that can be understood easily) is one that allows you to read a code fragment without having to remember the context in which the code is executed. By nesting If statements, more information must be kept in the readers working memory (or short term memory) to deduce the meaning of he code.

I guess this would do the trick:
If myArr.Length > 0 Then
If myArr(0) = "-1" Then
'Do stuff
Else
'Do stuff
End If
ElseIf myStr= "xyz" Then
'Do stuff
Else
'Do Nothing
End If

What you need is nested if
If myArr.Length > 0 Then
'Do stuff for non zero length
If myArr(0) = "-1" Then
'Do stuff for -1 and you already have checked for array length
End If
End If

If myArr.Length > 0 Then
If myArr(0) = "-1" Then
' Stuff 1
Else
' Stuff 3
End If
ElseIf myStr = "xyz"
' Stuff 2
End If
... no further else needed

You can decompose the statements like this:
If myArr.Length > 0 Then
If myArr(0) = "-1" Then
'Do stuff
Else
'Do sstuff
End If
Else
If myyStr= "xyz" Then
'Do stuff
End If
End If

Related

Do you need a multiple Else statements if you run multiple one line If statements?

I have a statement that does two If checks on one line:
If JMdict(i).Senses.Count > 0 Then If JMdict(i).Senses.First.Gloss.Count > 0 Then meaning = JMdict(i).Senses.First.Gloss.First Else meaning = ""
I'm wondering if I need to add a second Else, as in below:
If JMdict(i).Senses.Count > 0 Then If JMdict(i).Senses.First.Gloss.Count > 0 Then meaning = JMdict(i).Senses.First.Gloss.First Else meaning = "" Else meaning = ""
Or will the first Else cover all code paths?
Basically, should I be doing
If [First Condition] Then If [Second Condition] Then [Result] Else [Nothing happens]
Or
If [First Condition] Then If [Second Condition] Then [Result] Else [Nothing happens] Else [Nothing happens]
I'm aware I could use AndAlso as a neater solution, I'm just curious how this one-line nested If would work in practice.
Your code
If JMdict(i).Senses.Count > 0 Then If JMdict(i).Senses.First.Gloss.Count > 0 Then meaning = JMdict(i).Senses.First.Gloss.First() Else meaning = ""
is short for this
If JMdict(i).Senses.Count > 0 Then
If JMdict(i).Senses.First.Gloss.Count > 0 Then
meaning = JMdict(i).Senses.First.Gloss.First()
Else
meaning = ""
End If
End If
So if JMdict(i).Senses.Count <= 0 then meaning will not be set.
I might do this, using the short circuiting AndAlso as you mentioned
If JMdict(i).Senses.Any() AndAlso JMdict(i).Senses.First().Gloss.Any() Then meaning = JMdict(i).Senses.First().Gloss.First() Else meaning = ""
or use If() which shortens the code a little
meaning = If(JMdict(i).Senses.Any() AndAlso JMdict(i).Senses.First().Gloss.Any(), JMdict(i).Senses.First().Gloss.First(), "")
Using If() makes it very clear that meaning will be set because we begin with meaning =
For the reading impaired, the If() function can be split into multiple lines
meaning = If(JMdict(i).Senses.Any() AndAlso JMdict(i).Senses.First().Gloss.Any(),
JMdict(i).Senses.First().Gloss.First(),
"")
You can also use If() as a Null Coalescing operator. Note this version of If() only takes two arguments
meaning = If(JMdict(i).Senses.FirstOrDefault()?.Gloss.FirstOrDefault(), "")
The Else block on that single line will NOT run in all cases. It helps to understand why if you expect that code across multiple lines:
If JMdict(i).Senses.Count > 0 Then
If JMdict(i).Senses.First.Gloss.Count > 0 Then
meaning = JMdict(i).Senses.First.Gloss.First
Else
meaning = ""
End If
'There's no Else block for this spot!
End If
To fix this, you have a few options. We could have two Else blocks (not a fan of this):
If JMdict(i).Senses.Count > 0 Then
If JMdict(i).Senses.First.Gloss.Count > 0 Then
meaning = JMdict(i).Senses.First.Gloss.First
Else
meaning = ""
End If
Else
meaning = ""
End If
Or we can use AndAlso:
If JMdict(i).Senses.Count > 0 AndAlso JMdict(i).Senses.First.Gloss.Count > 0 Then
meaning = JMdict(i).Senses.First.Gloss.First
Else
meaning = ""
End If
This is actually pretty good. It's readable, and not too long. But in keeping with the original code in the question, let's stuff it all back on the same line:
If JMdict(i).Senses.Count > 0 AndAlso JMdict(i).Senses.First.Gloss.Count > 0 Then meaning = JMdict(i).Senses.First.Gloss.First Else meaning = ""
IMO, the above puts a bit too much into a single expression, where you must scroll or mess with line breaks to understand it. Let's work on shortening it more into something we can actually read and parse as a human. I'll start with the If() conditional operator:
meaning = If(JMdict(i).Senses.Count > 0 AndAlso JMdict(i).Senses.First.Gloss.Count > 0, JMdict(i).Senses.First.Gloss.First, "")
That's a little better, but only a little (128 characters vs 145). We can move some of it to an additional line to set the meaning up front, and then overwrite it only if the condition matches:
meaning = ""
If JMdict(i).Senses.Count > 0 AndAlso JMdict(i).Senses.First.Gloss.Count > 0 Then meaning = JMdict(i).Senses.First.Gloss.First
Hmmm. Not much improvement. This would have worked better in C#. It's a step, though. From here we can also use slightly different Linq operators plus null conditionals to further simplify things:
meaning = JMdict(i).Senses.FirstOrDefault()?.Gloss?.FirstOrDefault()
If meaning Is Nothing Then meaning = ""
At last, we're starting to get something that's a reasonable amount of code for a human to process and understand. Plus, we can reduce it even more using the null-coalescing If() variant:
meaning = If(JMdict(i).Senses.FirstOrDefault()?.Gloss?.FirstOrDefault(), "")
Now this I like. One line, no scrolling. There are some advanced features that not every VB.Net programmer might know, but even if you've not seem them before you should still be able to follow what the code does.

Limit to ElseIf Conditions?

So I have some VBA code designed to go through a few things based on a value in a cell. The value in the cell is read and the code runs accordingly. This works without issue with.
If Target.Value = "something" Then
End If
ElseIf Target.Value = "something2" Then
End If
ElseIf Target.Value = "something3" Then
End If
ElseIf Target.Value = "something4" Then
End If
That works perfectly, however if I add an additional ElseIf condition I get the compiler error of "Else without If". Changing ElseIf to Else on the fifth condition doesn't fix the issue. My question is that is there a limit to the amount of ElseIf conditions I can run? I literally only need this fifth one to be entirely done with what I am trying to do. I am positive the code within the condition has no errors.
The End If goes at the end only:
If Target.Value = "something" Then
'Do something
ElseIf Target.Value = "something2" Then
'Do something
ElseIf Target.Value = "something3" Then
'Do something
ElseIf Target.Value = "something4" Then
'Do something
End If
Definitely you should "upgrade" your multiple ElseIf and go with Select Case.
This will let you implement more scenarios in the future easier.
Select Case Target.Value
Case "something"
' code 1 here
Case "something2"
' code 2 here
Case "something3"
' code 3 here
Case "something4"
' code 4 here
Case "something5", "something6" ' <-- replaces using another If with And
' code 5 here
' Case ....
End Select

Two If statements inside each other in VBA

I tried to write two If statements inside each other in VBA, but it gives me wrong answer. When I debug it, it shows that the program doesn't go through the ElseIf and keeps going with the else of the first If.
How can I have two If statements working properly inside each other?
Code:
If ConfigBox.Value <> ... Then
If ListBox1.Value = ... Then
DO SOMETHING
Else
DO SOMETHING
End If
ElseIf ListBox1.Value = ... Or ListBox1.Value = ... Then
DO SOMETHING
Else
DO SOMETHING
End If
Your nesting is a bit off. You would want to do something like this:
If ConfigBox.Value <> ... Then
If ListBox1.Value = ... Then
Code
ElseIF ListBox1.Value = ... Or ListBox1.Value = ... Then
Code
Else
Code 'if ListBox1.Value doesn't meet above criteria
End If
Else
Code 'if ConfigBox criteria is not met. You could start another nested If for the ListBox1 here too.
End If
try with below
If ((ConfigBox.Value <> "1") And (ListBox1.Value = "2")) Then
'Do Something
ElseIf ((ConfigBox.Value <> "1") And (ListBox1.Value <> "2")) Then
'Do Something
ElseIf ListBox1.Value = "3" Or ListBox1.Value = "4" Then
'Do Something
Else
'Do Something
End If

if condition true do next for loop iteration

I have code like:
For Each dr As DataRow In items.Tables(0).Rows()
If dr("PRICE") = 0.0 Or dr("PRICE").ToString = "0.0" Then
'Skip end go in for-each again
Else
'Do something else.
End If
Next
I want to know if condition is true (Price is 0) then it should go to next item in for-each and do IF check again. Something like a NEXT?
As asawyer already pointed out, using the Continue Keyword is what you would want to do. It does exactly what you need - it just jumps to the next iteration of the loop specified. In your program it would look like this:
For Each dr As DataRow In items.Tables(0).Rows()
If dr("PRICE") = 0.0 Or dr("PRICE").ToString = "0.0" Then
Continue For
Else
...Do something else.
End If
Next

Exit a while loop in VBS/VBA

Is there a method of exiting/breaking a while in VBS/VBA?
Following code won't work as intended:
num = 0
while (num < 10)
if (status = "Fail") then
exit while
end if
num = num+1
wend
VBScript's While loops don't support early exit. Use the Do loop for that:
num = 0
do while (num < 10)
if (status = "Fail") then exit do
num = num + 1
loop
what about changing the while loop to a do while loop
and exit using
Exit Do
While Loop is an obsolete structure, I would recommend you to replace "While loop" to "Do While..loop", and you will able to use Exit clause.
check = 0
Do while not rs.EOF
if rs("reg_code") = rcode then
check = 1
Response.Write ("Found")
Exit do
else
rs.MoveNext
end if
Loop
if check = 0 then
Response.Write "Not Found"
end if}
Incredibly old question, but bearing in mind that the OP said he does not want to use Do While and that none of the other solutions really work... Here's something that does exactly the same as a Exit Loop:
This never runs anything if the status is already at "Fail"...
While (i < 20 And Not bShouldStop)
If (Status = "Fail") Then
bShouldStop = True
Else
i = i + 1
'
' Do Something
'
End If
Wend
Whereas this one always processes something first (and increment the loop variable) before deciding whether it should loop once more or not.
While (i < 20 And Not bShouldStop)
i = i + 1
'
' Do Something
'
If (Status = "Fail") Then
bShouldStop = True
End If
Wend
Ultimately, if the variable Status is being modified inside the While (and assuming you don't need i outside the while, it makes no difference really, but just wanted to present multiple options...
I know this is old as dirt but it ranked pretty high in google.
The problem with the solution maddy implemented (in response to rahul) to maintain the use of a While...Wend loop has some drawbacks
In the example given
num = 0
While num < 10
If status = "Fail" Then
num = 10
End If
num = num + 1
Wend
After status = "Fail" num will actually equal 11. The loop didn't end on the fail condition, it ends on the next test. All of the code after the check still processed and your counter is not what you might have expected it to be.
Now depending on what you are all doing in your loop it may not matter, but then again if your code looked something more like:
num = 0
While num < 10
If folder = "System32" Then
num = 10
End If
RecursiveDeleteFunction folder
num = num + 1
Wend
Using Do While or Do Until allows you to stop execution of the loop using Exit Do instead of using trickery with your loop condition to maintain the While ... Wend syntax. I would recommend using that instead.
While many have mentioned Do While...Loop, there are no examples showing the While is not necessary:
count = 0
Do
count = count + 1
wscript.echo count
If (count > 9) Then
Exit Do
End If
'...Some other logic that can be ended early...
wscript.sleep(1000)
Loop
If you already have the variable to compare against and it makes sense to complete the loop, Do While... is great. However, if you're doing something a little more granular, like the WScript.Sleep above that delays the script can be avoided.
Use Do...Loop with Until keyword
num=0
Do Until //certain_condition_to_break_loop
num=num+1
Loop
This loop will continue to execute, Until the condition becomes true
While...Wend is the old syntax and does not provide feature to break loop! Prefer do while loops