I am trying to use "If" logic in Excel VBA but the script is always selecting the 1st option for two areas, even if the statement is not correct.
The point of the code is if the word "Rate" appears at one location on the screen, then certain output should be created. If it finds it in a different location, then a different output should be created. Currently, it is ready the first "If" statement and the pulling that output even though the first statement is not correct.
Using the example below, The word "Rate" appears at row, column (4,20) on the screen but the statement is creating output like it is at (4,16) and therefore pulling the output from (4,27) instead of (4,31). I have switched the order around and it always uses the first option regardless of if it is a correct statement.
I abbreviated the code as much as possible. I had both Dim'd as a string but changed RateName to Variant to see if that would fix the issue but it did not.
Dim RateName As Variant
Dim Curr As String
If Session.FindText("Rate", 4, 16, 4) Then
RateName = Trim(Session.GetDisplayText(4, 27, 20)) 'R name for Amt Add, Amt Off, Buy/Get
ElseIf Session.FindText("Rate", 4, 20, 4) Then
RateName = Trim(Session.GetDisplayText(4, 31, 20)) 'R name for Flat Amount, Pct Off
End If
If Session.FindText("Rate", 4, 16, 4) Then
Curr = Trim(Session.GetDisplayText(4, 58, 3))
ElseIf Session.FindText("Rate", 4, 20, 4) Then
Curr = Trim(Session.GetDisplayText(4, 62, 3))
End If
Not sure what I am doing wrong since I have similar logic in place elsewhere and it is working.
In the case of VBA, returning something different to 0 is not TRUE. You get true when you use some operator
If Session.FindText("Rate", 4, 16, 4) = "some text/value" Then
If Session.FindText("Rate", 4, 16, 4) <> "some text/value" Then
If Session.FindText("Rate", 4, 16, 4) >= "some text/value" Then
If Session.FindText("Rate", 4, 16, 4) <= "some text/value" Then
Also, if the text returned is "True" or "False" for the IF in VBA is just a text, not TRUE or FALSE
Edit #1 because of your comment...
And you can use this:
If Session.FindText("Rate", 4, 16, 4) = Empty Then
'some code if the logical test is true
else
'some code if the logical test is false
end if
Related
Hoping someone could help me with this. I have the following string:
RSSRRSSRRR;RSRRSSRSRSRSSRSS;RSRSSS;SRRRSSRR;SSSRS;SRSSRRSRRSSS;SRSSRS;SRSSS;RSSRSRSS;RSRSSRSRRSSS;RSSSS;SRSSS;S/RR/SR/SS/RS/RR.SSSRRS;RSSSS;SRSSS;SSSS;RSSRSRSS;SSRSS;SSRRSRSRSS;SRRSRSSS;RSSSRRSS;SSSS;SSSRS;SRSSS;R/SR/SS/RR/RR/SR/RR/S
This is data from a tennis match. The 'S' represents a point won by the server, 'R' represents a point won by the receiver, ';' represents the end of a game and '.' represents the end of the set. The server in the first game will be Player 1 and the server in the second game will be Player 2. This will swap throughout the match after each game. Given a tie break occurs in the 13th game of a set, the '/' will represent when the serve is switched over to the other player.
I want to get the data into the following format:
Set, Game, Point, PlayerPointID, P1net, P2net,result
1, 1, 1, player2 , -1, +1
1, 1, 2, player1 , 0, 0
1, 1, 3, player1 , +1, -1
...
1, 1, 10, player2, -2,+2, Player2
I've wrote the following code so far:
Sub LoopThroughString()
Dim Counter As Integer
Dim MyString As String
MyString = Cells(2, 9)
For Counter = 1 To Len(MyString)
If Mid(MyString, Counter, 1) = "S" Then
Cells(Counter + 1, 16) = Cells(Counter, 16) + 1
ElseIf Mid(MyString, Counter, 1) = "R" Then
Cells(Counter + 1, 16) = Cells(Counter, 16) - 1
End If
Cells(Counter + 1, 17) = -Cells(Counter + 1, 16)
Next
End Sub
That basically just loops the string and calculates net values. I'm not sure however how to deal with the delimiters, how it would swap over player 1 and player 2 after each game. Also how I could do a point, game, set count. The point count would need to reset after each game and the game count would reset after each set. Any ideas?
You can use Split([String], [Delimiter])to get an Array of strings in which there is a delimiter. for example, your string RSSRRSSRRR;RSRRSSRSRSRSSRSS;RSRSSS;SRRRSSRR;SSSRS;SRSSRRSRRSSS;SRSSRS;SRSSS;RSSRSRSS;RSRSSRSRRSSS;RSSSS;SRSSS;S/RR/SR/SS/RS/RR.SSSRRS;RSSSS;SRSSS;SSSS;RSSRSRSS;SSRSS;SSRRSRSRSS;SRRSRSSS;RSSSRRSS;SSSS;SSSRS;SRSSS;R/SR/SS/RR/RR/SR/RR/S when used in the function :
Dim MyArray() As String
MyArray = Split(MyString, ";")
would be separated as such :
RSSRRSSRRR
RSRRSSRSRSRSSRSS
RSRSSS
SRRRSSRR
SSSRS
SRSSRRSRRSSS
SRSSRS
SRSSS
RSSRSRSS
RSRSSRSRRSSS
RSSSS
SRSSS
S/RR/SR/SS/RS/RR.SSSRRS
RSSSS
SRSSS
SSSS
RSSRSRSS
SSRSS
SSRRSRSRSS
SRRSRSSS
RSSSRRSS
SSSS
SSSRS
SRSSS
R/S
R/SS/RR/RR/SR/RR/S
Each line being a separate entry in the Array. MyArray[0] would then be the first line RSSRRSSRRR, which would be the first game, and MyArray[UBound(MyArray)] would be the last one R/SS/RR/RR/SR/RR/S. UBound(MyArray)is the last index of the array provided, which would be equivalent to 25in this example.
To loop through each entry, you can use a for loop :
Dim CurrentGame As Integer
For CurrentGame = 0 to UBound(MyArray)
For Counter = 0 to Len(MyArray[CurrentGame])
' do stuff
' like MyArray[CurrentGame][Counter] to get the character "R", "S" or whatever is there.
Next
Next
NOTE : I assume you are using the default base 0 indexes from your example, but the best practice would be to use For CurrentGame = LBound(MyArray) '... instead, where LBound(MyArray) gives you the first index of the provided Array.
To remember which player is serving, you can create another variable :
Dim player1Serving as Boolean
player1Serving = True
When you want to switch, simply write :
player1Serving = Not player1Serving
And when you want to act according to who is serving :
If player1Serving Then
' Do stuff for Player 1 serving
Else
' Do stuff for Player 2 serving
End If
There is a small error in my For loop as it will not select the part that I want to color. I used a variable hash to put all the names of the document there and then tried the Catia function to color, but still got nothing!
Below is a part fo the code.
Problem zone is the Select Case. It wont actually select and color the part if found.
UPDATE: now i know exactly where the problem is, it is inside case during selection of the part and coloring it. somehow it wont even select the part.
For n = 1 To DokAnzahl
Set Dokument = DokumentArray(n)
ReDim DokumentArrayNew(DokAnzahl)
DokumentArrayNew(n) = CStr(Dokument.Name)
For j = 1 To UBound(arrNamen)
If arrNamenNew(j) = Left(DokumentArrayNew(n), Len(arrNamenNew(1))) Then
'MsgBox "They are equal!"
hash = DokumentArrayNew(n)
ColorCode(j) = arrFarben(j)
'MsgBox ColorCode(j) checked
m = j+1
Select Case ColorCode(j)
Case "NEU" 'rot
Set sel = catia.activedocument.selection
sel.search "Name =hash,all"
sel.visproperties.setRealColor 240, 1, 1, 1
Case "entfällt" 'Gelb
Set sel = catia.activedocument.selection
sel.search "Name =hash,all"
sel.visproperties.setRealColor 240, 240, 16, 1
Case "COP" 'Grün
Set sel = catia.activedocument.selection
sel.search "Name =hash,all"
sel.visproperties.setRealColor 30, 240, 60, 1
Case Else
MsgBox "no color info"
End Select
End If
Next
Next
Your Selection.Search is searching for the word "Hash" and not what is inside the variable hash
Change your Select Case statements to this:
Set sel = catia.activedocument.selection
sel.search "Name =*" & hash & "*,all"
I'm trying to use Excel VBA to control text box background colors depending on the values in certain cells. Each text box corresponds to a different cell with a value in it. I have about 60 text boxes to control and 4 possible colors for each one. Using switch statements, I would basically have to do 4 cases for each of the 60 text boxes... Assuming I use the way I have it set up now as seen below:
Select Case Cells(50, 2).Value
Case Is = 1, 6, 11, 16
.TextBox13.BackColor = RGB(0, 255, 0)
Case Is = 5
.TextBox13.BackColor = RGB(255, 0, 0)
Case Is = 0
.TextBox13.BackColor = RGB(255, 255, 255)
Case Is = 10, 15
.TextBox13.BackColor = RGB(255, 255, 0)
End Select
And so on for all 60. However, the value range is always the same, and the colors correspond with the same values for each one. I'm assuming there must be a way to build one module to actually set the colors, and just use switch statements to determine with cell to send to that module?
EDIT: I've attached a screenshot of the workspace so you can see what I'm going for
Some piece of your code is wrong. It's Select Case ... End Select
Select Case Cells(50, 2).Value
Case 1, 6, 11, 16
tbxObject.BackColor = RGB(0, 255, 0)
Case 5
tbxObject.BackColor = RGB(255, 0, 0)
Case 0
tbxObject.BackColor = RGB(255, 255, 255)
Case 10, 15
tbxObject.BackColor = RGB(255, 255, 0)
End Select
Please, see: Select ... Case statement
If some piece of code is used several times, you have to move it into single general soubroutine, which can accept TextBox object as input parameter.
Sub ColorMyTextBox(wsh As Worksheet, sTextBoxName As String)
Dim txtObject As OleObject
Set txtObject = wsh.OleObjects(sTextBoxName)
If TypeName(txtObject) <> "TextBox" Then Goto Exit_Sub
'here Select Case statement
Exit_Sub:
End Sub
Got it?
Ok, so if I use that, how will I specify the cell numbers to use in the case statements? It won't always be cells(50,2)... And I also get errors when sending the worksheet name
Is it possible to have multiple conditions that can evaluate to true in an if statement? Primarily just shorthand to save some time:
Example:
if value = 1 or value = 9 or value = 3 or value = 17 Then return True
Im wondering if there is something to this effect (could not find in MSDN)
if value = 1,9,3,17 Then return True
Can't do that with an IF statement, but you could use:
SELECT CASE value
CASE 1, 3, 9, 17
' Do something
CASE 2, 4
' Do another thing
CASE ELSE
' Do something else
END SELECT
You can also try like:
If (New List(Of Integer)(New Integer() {1, 3, 5, 7, 9}).Contains(value)) Then
Return TRUE
End If
If it's a return statement, you could make it bit shorter like this;
Return value = 1 Or value = 9 Or value = 3 Or value = 17
Also if the values would be in an array, you could use Linq - Any function;
Dim value As Integer = 1
Dim values = New Integer() {1, 9, 3, 17}
Return values.Any(Function(number) number = value)
You can't do what you want exactly within VB, but you can get around it. Here is one method. Put your values into an Array. You can search the Array using the IndexOf method. If the IndexOf returns a number above -1, then the item was found in the array. There are some gotchas that you will want to read about on the MSDN page.
Dim value As Boolean
Dim myList() As Integer = {1, 9, 3, 17}
If Array.IndexOf(myList, 12) > -1 Then
value = True
Else
value = False
End If
Console.WriteLine("Found: {0}", value)
You can also shorten the test to an inline comparison and assignment, removing the need for the If statement above.:
value = (Array.IndexOf(myList, 12) > -1)
I'm having some problems with the vba script below. It's pretty simple. It's meant to take the value of a dropdown list and respond based on a yes/no/null value in another sheet. The code works fine, except for that there is a problem in the vlookup lines that stops the script from running.
The first two vlookup lines return an "application defined or object defined error", and the third returns a "Data type mismatch" error. Each of the cells that the formulas refer to are formatted as text, so I'm not sure what the problem is... Any feedback would very helpful. Thank you!
If Not Intersect(Target, Range("countryProductCell")) Is Nothing Then
lastcolumn = ActiveSheet.UsedRange.Column - 1 + ActiveSheet.UsedRange.Columns.Count
cellRow = Target.Row
defaultCellColumn = 4
Dim countryIndex As Variant
countryIndex = Array(6, 6, 30, 21, 35, 29, 32, 20, 23, 18, 19, 34, 33, 22, 31, 26, 25, 27, 28, 7, 8, 15, 12, 10, 13, 11, 16, 17, 9)
i = 0
For Each countryCell In Range(Cells(cellRow, 5), Cells(cellRow, lastcolumn))
'If Default is selected
'If Not Target.Value = "(Select Title)" Then
'If Product is not selected
If countryCell.Value = "Use Default" Then
'Look Up Purchaseablility, Needs Array
If Not Application.VLookup(ActiveSheet.Cells(cellRow, defaultCellColumn), Sheets("Active Product Catalog").Range("E:AK"), countryIndex(i), False) = "Yes" Then
'If Not Purchaseable, Change Color
countryCell.Interior.ColorIndex = 3
End If
If Application.VLookup(ActiveSheet.Cells(cellRow, defaultCellColumn), Sheets("Active Product Catalog").Range("E:AK"), countryIndex(i), False) = "Yes" Then
'If Purchaseable, Change Color
countryCell.Interior.ColorIndex = 35
End If
Else
If Application.VLookup(ActiveSheet.Cells(cellRow, countryCell.Column), Sheets("Active Product Catalog").Range("E:AK"), countryIndex(i), False) = "Yes" Then
countryCell.Interior.ColorIndex = 35
End If
End If
'Else
'End If
i = i + 1
Next
End If
You define defaultCellColumn=4 but use undefined variable defaultCell in your first two formulas. It is a good idea to use Option Explicit at the start of your module - then this gets caught when you compile.
Not sure about the third error but your countryIndex array goes all the way to 35 which is more than the number of columns in E:AK. Recognize that VLOOKUP uses column offset relative to the range, not absolute column, for the third parameter (so 2=F in your case, and 35=AM which is outside of the range you specified and will throw an error.)
Data type mismatch error can be handled using the below method.
On Error Resume Next
Result = Application.VLookup(Cells(cellRow, countryCell.Column), Sheets("Active Product Catalog").Range("E:AK"), countryIndex(i), False)
If Result = "Error 2042" Then
Result = "Nothing Found"
Else
MsgBox Result
End If
On Error GoTo 0