VBA Variable Scope in a Case Statement - vba

Wondering how variables work when used in a Case statement. It seems like they are declared in the first Case, regardless of whether that Case is relevant.
'The following code will throw an error
Select Case team
Case "Philadelphia Eagles"
dim record as String
Case "Dallas Cowboys"
dim record as String
End Select
Even if 'team' isn't Philadelphia Eagles, it claims I've already declared the variable 'record'
I was under the impression that anything in a case statement was completely skipped over if that case wasn't relevant.
'The following code works
Select Case team
Case "Philadelphia Eagles"
dim record as String
Case "Dallas Cowboys"
record = "8-8"
End Select
Just want to confirm that I am understanding the Case statement correctly here.
Thank you!
Josh

Variable declarations (Dim statements) are resolved at the start of the execution of the program, which is why your Dim record statements weren't "skipped" over in your example.
You should put your variable declarations once at the top of your code, just after you start the subroutine or function. You cannot use Dim on the same variable twice. If the variable is an array which you need to resize, you can use ReDim [Preserve] instead.
Sub Subname()
Dim record as String
Select Case team
Case "Philadelphia Eagles"
record = "16-0"
Case "Dallas Cowboys"
record = "8-8"
End Select
End Sub

Related

Calling an Access VBA function with IF statement as an argument

Assuming I have the following MS Access 2016 function:
Public Function TestFunction(ByVal strTest As String) As String
Is there a way to call the function with something similar to:
strReturn = TestFunction(If a = 1 Then "Apple" Else "Orange")
I would like to write something as compact as possible, and avoid having to write multiple lines for the call, such as:
If a = 1 Then strArg = "Apple" Else strArg = Orange
strReturn = TestFunction(strArg)
You can accomplish this using IIf, e.g.:
strReturn = TestFunction(IIf(a=1,"Apple","Orange"))
But this is generally discouraged when working with expressions other than constants, because IIf will always evaluate both the then and else argument before returning the appropriate value depending on the outcome of the test expression, which can sometimes lead to undesired results.
For example, evaluating the following expression at the Immediate Window (Ctrl+G) will result in a division by zero error, even though the else expression will never be returned:
?iif(true,"Apple",1/0)
If the value for a comes from a well defined range then the solution would be to use either the Choose Function for a contiguous range or Switch Function for a non contiguous well defined range.
Of course the more grown up solution would be to replace both Choose or Switch with a Dictionary.
Why not something like this for multiple possibilities
Dim myArg as String
Select Case a
Case 1: myArg = "Apple"
Case 2: myArg = "Orange"
Case 3: myArg = "Pear"
'etc.
End Select
strReturn = TestFunction(myArg)

Update SQL table using Vb.net

I have a VB.net script that needs to put information into a table in the database. The catch is that it is based off of an item Id, so when I am updating I cannot just insert the row would like to update the row if it is already there. For this I need to use the Update command like so:
mysqlCommand = New SQLCommand(UPDATE tableName Colum2=Newvalue ... Where Column1=ItemId)
However I am wondering if there is anyway to tell wether or not a line was updated when I run
mysqlcommand.ExecuteNonQuery()
so that I do not need to check before I run this command and switch between this update command and a INSERT INTO command
I agree with #Neolisk, but a slight improvement could be to use the following:
Dim recordsAffected As Integer = mysqlcommand.ExecuteNonQuery()
If recordsAffected > 0 Then 'it worked
or this:
Dim recordsAffected As Integer = mysqlcommand.ExecuteNonQuery()
If recordsAffected >= 1 Then 'it worked
#Neolisk's code will work great as long as Column1 is a unique identifier. Otherwise you may be updating more than one row. The "greater than"/"greater than or equal to" operator will catch the scenario where you are updating more than one row.
From documentation of SqlCommand.ExecuteNonQuery # MSDN:
Executes a Transact-SQL statement against the connection and returns the number of rows affected.
So you can write like this:
Dim recordsAffected As Integer = mysqlcommand.ExecuteNonQuery()
If recordsAffected = 1 Then 'it worked
EDIT: Regarding #macoms01 answer, my original intention was to have something like this:
Select Case recordsAffected
Case 0: 'it did not work
Case 1: 'it worked
Case Else: Throw New BadDataException
End Select
You can never be sure that unique constraints are set on the DB - expect bad data.
But then I thought it would probably be too complicated for its purpose.

vb.net Select Case error

When i want define values in Select Case i got error:
'Value' is not declared. It may be inaccessible due to its protection level.
When Dim Value As Object is outside Select Case - No error. My target is get Value different on special numbers. For example:
Select Case Integer
Case 1
Dim Value As New UserControl1
Case 2
Dim Value As New UserControl2
Case Else
Dim Value As New UserControl3
End Select
Try this, assuming all 3 user control types derive from the base UserControl object:
Dim Value as UserControl
Select Case Integer
Case 1
Value = New UserControl1
Case 2
Value = New UserControl2
Case Else
Value = New UserControl3
End Select
It is not passable to declare a variable inside a scope and access it outside the scope such as as select case statement. However you problem is easily solved by separating the declaration and initialization. This enables you to use the variable outside the select case as the variable is in the higher scope. The variable is declared as System.Windows.Controls.UserControl as this is the most specific common type.
Dim Value As UserControl
Select Case Integer
Case 1
Value = New UserControl1
Case 2
Value = New UserControl2
Case Else
Value = New UserControl3
End Select

Is it possible to define same variable twice in classic ASP?

Is it somehow possible to declare same variable in .asp file twice? Example below does not look very clever, but this is just an example and I have to sort it out.
Dim number : number = 1
Select Case number
Case 1
Dim a
Case 2
Dim a
End Select
Theoretically you can of course declare a variable twice, the problem is, asp will throw an error, if the variable is declared in the same scope.
whatever you want to achieve, keep in mind, you can (almost) always access the variables in parent scope, thus rendering a double declaration useless.
Dim number : number = 1
Dim a
Select Case number
Case 1:
a = "whatever"
Case 2:
a = "something different"
End Select
response.write a

Pass in Array to Select Case

this may be a dense question and I'm not finding it to be a dup of this one, but I need some help with understanding if an array can be used in a Select Case statement.
I have a sub routine that I will create a string array dynamically. The XML is also listed, but it could be any of the values listed below. It will be something like this:
Dim offensiveLine() As String = New String() {"center", "right wing", "left wing"}
Dim defensiveLine As String = "defense"
Dim playerInfo = <Player><Name>John</Name><Position val="right wing"/></Player>
What I want to do is see if this player is in one of the offensiveLine. So I say:
Dim playerPosition = playerInfo.Position.#val
Select Case playerPosition
Case offensiveLine
'do something
Case defensiveLine
'do something
Case Else
'do nothing
End Select
Here is lies the issue: Case offensiveLine is invalid. I know I could write out Case "center", "right wing", "left wing", but that would defeat the purpose of what I'm trying to do, which is to make a generalized variable that is an array that can be read from in a Case statement. Secondly, I know I can't create a variable like Dim offensiveLine = ""center", "right wing", "left wing"" and pass that in.
Any insight on how I may be able to pass in an array to a Case statement and have each one evaluated?
You may want to consider using an if clause here rather than a switch. Try this logic: if offensiveLine contains playerPosition, then offensive line, etc.
You actually can use a Select statement:
Dim playerPosition = playerInfo.Position.#val
Select Case True
Case offensiveLine.Contains(playerPosition)
'do something
Case defensiveLine.Contains(playerPosition)
'do something
Case Else
'do something - otherwise you don't need the 'Case Else'
End Select
The trick is the True in the first line of the Select.
The Select..Case construct does not work like that. However, it is easy to test if an element exists in an array:
If offensiveLine.Contains(playerPosition) Then
'Do something
ElseIf defensiveLine.Contains(playerPosition) Then
'Do something else
End If