Nested inline if statement - vb.net

In VB .Net it is possible to use inline If statements, like this
if a Then ret = "A" Else ret = "Not A"
I know it is also possible to nest these statements. I know this might not be good practice as readability drops down...
If a Then If b Then ret = "A & B" Else ret = "A & Not B" Else ret = "Not A"
which will be evaluated like this :
If a Then
If b Then
ret = "A & B"
Else
ret = "A & Not B"
End If
Else
ret = "Not A"
End If
Now if I remove the last Else statement, I get this :
If a Then If b Then ret = "A & B" Else ret = "A & Not B"
which is :
If a Then
If b Then
ret = "A & B"
Else
ret = "A & Not B"
End If
End If
So I guess the compiler finds the Else and matches it to the last openend If in the line, which makes sense.
My question is : Is it possible to change the evaluation order ? By that I mean is it possible that the Else is matched with the first if ?
So it would look like this :
If a Then
If b Then
ret = "A & B"
End If
Else
ret = "Not A"
End If
But inlined (something like this, parenthesis added to understand what I mean) :
If a Then ( If b Then ret = "A & B" ) Else ret = "Not A"
I tried with parenthesis or adding a End If but it provokes syntax errors, and I couldn't find documentation for this.
I'm not stuck anywhere and I know this might not be a good prorgamming practice, but I just wanted to know (out of curiosity) if it was possible.
I know also I could switch the statements (i.e. test b before a), but let's say I can't (a is a List and must be tested for Nothing before b which would be the Count for example).

You could do it like this
ret = If(a, If(b, "A & B", "A & Not B"), "Not A")
Personally, I never understood the need to put everything in one line.

You may find that this is what you need:
If a And B Then
ret = "A & B"
Else
ret = "Not A"
End If
Or as a single line:
If A And B Then Ret = "A & B" Else RET = "Not A"

I just created a simple console application with your final nested if statement and it worked fine
Sub Main()
Dim a = False
Dim b = True
If a Then
If b Then
Console.WriteLine("A & B")
End If
Else
Console.WriteLine("A & Not B")
End If
Console.ReadLine()
End Sub

Related

Why am I getting a run time error 2185 on a form and not on another?

I'm kinda new to MS Access and I'm sort of learning while coding, so forgive me if my question is a bit weird.
I have created a form based on a table, and in the form I have a text box that the user would type something and it should filter the table and show the results based on what the user typed. There are two forms with pretty much the same code on them (named Rec and Cx). In one of them (Rec) the above description works just fine, but the other (Cx) don't and I get a run-time error 2185. Let me show you some code:
Private Sub strConsRecDesc_KeyUp(KeyCode As Integer, Shift As Integer)
FiltroRec = ""
FilterTextDesc = ""
If Len("" & Me.strConsRecDesc.Text) > 0 Then
intLenDesc = Len(Me.strConsRecDesc.Text)
RequeryForm
strConsRecDesc.SetFocus
Me.FilterOn = True
If intLenDesc > Len(Me.strConsRecDesc.Text) Then
Me.strConsRecDesc = Me.strConsRecDesc & " "
Else
Me.strConsRecDesc = FilterTextDesc
End If
strConsRecDesc.SelStart = intLenDesc
Else
RequeryForm
strConsRecDesc.SetFocus
End If
End Sub
I heard it is good practice to lable variables and fields based on data type, so here int stands for integer, str for strings and Desc refers to the Description field.
Based on what is typed in the field strConsRecDesc I filter the table using the RequeryForm in there, that basically checks all the fields in the form that the user can write into. Let me show you the part for the description field:
strConsRecDesc.SetFocus
If Len(strConsRecDesc.Value) > 0 Then
FilterTextDesc = Me!strConsRecDesc.Value
If Len(FiltroRec) > 0 Then
FiltroRec = FiltroRec & " And "
End If
FiltroRec = FiltroRec & "[recDescricao] LIKE '*" & FilterTextDesc & "*'"
End If
In this form (Rec), I can write, i.e. this is a test and no record is shown, because there is no record with this is a test written in it, and that is correct. If I type something that matches the criteria it works just fine.
However, in the other form (the Cx one), I have the following code for KeyUp:
Private Sub strConsCxDesc_KeyUp(KeyCode As Integer, Shift As Integer)
FiltroCx = ""
FilterTextDesc = ""
If Len("" & Me.strConsCxDesc.Text) > 0 Then
intLenDesc = Len(Me.strConsCxDesc.Text)
RequeryForm
strConsCxDesc.SetFocus
Me.FilterOn = True
If intLenDesc > Len(Me.strConsCxDesc.Text) Then
Me.strConsCxDesc = Me.strConsCxDesc & " "
Else
Me.strConsCxDesc = FilterTextDesc
End If
strConsCxDesc.SelStart = intLenDesc
Else
RequeryForm
strConsCxDesc.SetFocus
End If
End Sub
And the equivalent RequeryForm for the Cx is:
strConsCxDesc.SetFocus
If Len(strConsCxDesc.Value) > 0 Then
FilterTextDesc = Me!strConsCxDesc.Value
If Len(FiltroCx) > 0 Then
FiltroCx = FiltroCx & " And "
End If
FiltroCx = FiltroCx & "[cxDescricao] LIKE '*" & FilterTextDesc & "*'"
End If
But in the Cx one if I type this is a test in the strConsCxDesc textbox I get a run-time error 2185.
I understand that with just this bit of code it is kinda hard to grasp what I'm trying to do, but I really don't know why I'm getting this error if the code is the same.
I appreciate any help, and I'm sorry for my bad english, it's not my mother language.
Thanks in advance.

Wrong output result from VBA code in Access tool

I am having some issue with a value that is being determined from some VBA code in my Access tool. I am quite a beginner with VBA and this code was developed alongside a very experienced VBA programmer (who has gone away hence is unable to assist me).
This is the code in question:
Private Sub ValidatePrinting()
Dim rst As DAO.Recordset, PrintMethodVal As Boolean, PracIdVal As Long, datePrintedcol As String, PrintedCount As Integer, ImportedCount As Integer
Dim fromtxt As String, wheretxt As String, conditionalImportedCount As Integer, PrintConditions As Boolean
PrintMethodVal = Me.filter_PrintMethod.Value
PracIdVal = Me.filter_PracticeID.Value
datePrintedcol = Me.filter_LetterRound.Value
datePrintedcol = IIf(datePrintedcol = "1st Round", "datePrinted_1st", IIf(datePrintedcol = "2nd Round", "datePrinted_2nd", ""))
PrintedCount = Me.filter_LetterCount.Value
PrintConditions = Me.filter_PrintConditions.Value
If (datePrintedcol = "") Then
Call DisplayMessage("All letters already sent")
Else
fromtxt = " tbl_main_ListLog as T INNER JOIN tbl_dbextract_GPPractice as GPP ON T.GPPracticeID = GPP.Id"
wheretxt = PrintSQLCriteria(PracIdVal, datePrintedcol)
Set rst = CurrentDb.OpenRecordset(PrintValidationSQL(PrintMethodVal, fromtxt, wheretxt))
ImportedCount = rst.Fields(0).Value
conditionalImportedCount = rst.Fields(1).Value
If ImportedCount = conditionalImportedCount Then
If ImportedCount = PrintedCount Then
If PrintMethodVal = PrintConditions Then
tb_Result = "All OK"
CurrentDb.Execute (" update " & fromtxt & " set " & datePrintedcol & " = date() " & wheretxt)
Else
tb_Result = "Wrong print method selected"
End If
Else
tb_Result = "Counts don't match"
End If
Else
tb_Result = "Mismatched print conditions"
End If
End If
End Sub
So the issue is, when the PrintMethodVal does not equal PrintConditions it outputs "Mismatched Print conditions" as opposed to the "Wrong print method selected" which is what it should. It also outputs "Mismatched Print conditions" when the ImportedCount also does not equal the PrintedCount (as well as the first situation), which is weird as the If should end there and output "Counts don't match".
This code was functioning correctly when originally developed, but I had to include the check for PrintMethodVal = PrintConditions.
What am I missing here?

excel vba ping list of computers

I am working on a project. My goal is, to ping all of the computers from an excel list, but can't figure out why it isn't working. I am quite new at this programming language, and I am sure that I miss out something, because I get the error message: Object required
so here is my code
the main:
Sub pingall_Click()
Dim c As Range
c = Target.Name
For Each c In Range("A1:N50")
If (Left(c, 1) = "C" Or Left(c, 1) = "T") And IsNumeric(Right(c, 6)) And Len(c) = 7 Then
c = sPing(c)
If c = "timeout" Then
MsgBox "timeout"
ElseIf c < 16 And c > -1 Then
MsgBox "ok"
ElseIf c > 15 And c < 51 Then
MsgBox "not ok"
ElseIf c > 50 And c < 4000 Then
MsgBox "big delay"
Else
MsgBox "error"
End If
End If
Next c
End Sub
The function:
Public Function sPing(sHost) As String
Dim oPing As Object, oRetStatus As Object
Set oPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery _
("select * from Win32_PingStatus where address = '" & sHost & "'")
For Each oRetStatus In oPing
If IsNull(oRetStatus.StatusCode) Or oRetStatus.StatusCode <> 0 Then
sPing = "timeout" 'oRetStatus.StatusCode
Else
sPing = sPing & vbTab & oRetStatus.ResponseTime & Chr(10)
End If
Next
End Function
I can get the result if I write sPing(""), but I want it to get the name of pc-s that are in the list.
This is just a test version of the script, I am testing it with one pc for now, that is why I use "MsgBox".
Thank you
The 2nd line inside the Sub pingall_Click() subroutine is the one throwing the Object Required error. i.e. the following line.
c = Target.Name
If you comment it out or delete it, it works. (I tried it.)
Also, you should not be assigning the return value from the function sPing back to c.
Because doing so will overwrite the name of the Server / IP address you have in the cell, since the forloop is looping over 1 cell at a time using the c variable.
So instead, assign it back to a new string variable, and then do whatever you want with it.

VB - Index outside of bounds?

Oh my god i hate this thing, i tried millions of ways but couldn't find a working one. Let me explain:
I'm testing each line and checking the first word to be "copy" alright ? After the word copy i want to see if the next word is "1" , the third is "<" and the last is ">" , if all these conditions are fullfilled then the text between "<" and ">" needs to be stored in the variable "copy1" (even if there is more than 1 word between them).
What my code is:
For i = 0 To lstCode.Items.Count - 1
Dim str As String = lstCode.Items.Item(i)
Dim strA() As String = Split(str)
Dim copy1 as string
Dim copy2 as string
Select Case strA(0)
Case copy
If strA(1) = "1" And strA(2) = "<" And strA(strA.Count - 1) = ">" Then
copy1 = ""
For lr As Integer = 3 To strA.Count - 2
copy1 &= (strA(lr) & " ")
Next
End if
End select
And, when i debug it i get the error: Index was outside the bounds of the array ... Does anybody have any idea ?
There is something important i forgot to add, this is the whole code:
Case "copy"
If strA(1) = "1" And strA(2) = "<" And strA(strA.Count - 1) = ">" Then
copy1 = ""
For lr As Integer = 3 To strA.Count - 2
copy1 &= (strA(lr) & " ")
Next
ElseIf strA(1) = "2" And strA(2) = "<" And strA(strA.Count - 1) = ">" Then
copy2 = ""
For lrs As Integer = 3 To strA.Count - 2
copy2 &= (strA(lrs) & " ")
Next
ElseIf strA(1) = "run" Then
Try
IO.File.Copy(copy1, copy2)
Catch ex As IO.IOException
End Try
End If
End Select
So everything works like a charm: copy 1 < c:\csb.log > , copy 2 < c:\blabla.txt > but when the " copy run " statement comes in it gives me the error...
You need to change the operator And with AndAlso.
The second one applies Short Circuit Evaluation to your expression, meaning if the first expression is false the second, third and so on expressions on the same line are not evaluated.
In your line
If strA(1) = "1" And strA(2) = "<" And .......
when the value is "Run" you still evaluate the expression strA(2) = "<" but there is no element at index 2 so you get the error.

Classic ASP - passing a property as byref

In Classic ASP, I have an object, call it bob. This then has a property called name, with let and get methods.
I have a function as follows:
sub append(byref a, b)
a = a & b
end sub
This is simply to make it quicker to add text to a variable. I also have the same for prepend, just it is a = b & a. I know it would be simple to say bob.name = bob.name & "andy", but I tried using the above functions and neither of them work.
The way I am calling it is append bob.name, "andy". Can anyone see what is wrong with this?
Unfortunately this is a feature of VBScript. It is documented in http://msdn.microsoft.com/en-us/library/ee478101(v=vs.84).aspx under "Argument in a class". The alternative is to use a function. Here is an example illustrating the difference. You can run this from the command line using "cscript filename.vbs.
sub append (a, b)
a = a & b
end sub
function Appendix(a, b)
Appendix = a & b
end function
class ClsAA
dim m_b
dim m_a
end class
dim x(20)
a = "alpha"
b = "beta"
wscript.echo "variable works in both cases"
append a, b
wscript.echo "sub " & a
a = appendix(a, b)
wscript.echo "function " & a
x(10) = "delta"
wscript.echo "array works in both cases"
append x(10), b
wscript.echo "sub " & x(10)
x(10) = appendix( x(10), b)
wscript.echo "function " & x(10)
set objAA = new ClsAA
objAA.m_a = "gamma"
wscript.echo "Member only works in a function"
append objAA.m_a, b
wscript.echo "sub " & objAA.m_a
objAA.m_a = appendix(objAA.m_a, b)
wscript.echo "function " & objAA.m_a
Have you tried using with the keyword CALL:
call append (bob.name, "andy")
Classic ASP is fickel about ByRef and ByVal. By default it uses ByRef -- no reason to specify that. If you call a function with parenthesis (without the call), it will pass the variables as ByVal.
Alternatively, you could accomplish the same with:
function append(byref a, b)
append = a & b
end sub
bob.name = append(bob.name, "andy");
Good luck.
As this other answer correctly states, you are facing limitation of the language itself.
The only other option to achieve what you are after as far as I can see it, is to add such sub routine to the class itself:
Public Sub Append(propName, strValue)
Dim curValue, newValue
curValue = Eval("Me." & propName)
newValue = curValue & strValue
Execute("Me." & propName & " = """ & Replace(newValue, """", """""") & """")
End Sub
Then to use it:
bob.Append "name", "andy"
Less elegant, but working.