This question already has answers here:
I use OR to form a multiple condition IF ELSE statement on VBA, it's not working
(2 answers)
How to use OR in if statement in VBA [duplicate]
(1 answer)
Closed 1 year ago.
Hi I have absolutly no clue why the else with "exit for" will not execute.
Value of my respective Excel testing cell as follows:
"VERS.GR.III, KENNNR.1905, V ERS.NR. 1023461"
Function DebitorVorhanden(Debitor As String) As Boolean
Dim Ausgabe As Boolean
Ausgabe = False
Dim TextLänge As Integer
TextLänge = Len(Debitor)
Dim Prüfer As Integer
For Prüfer = 1 To TextLänge
If Mid(Debitor, Prüfer, 1) = "1" Then
Dim PrüferLänge As Integer
PrüferLänge = 0
Dim Prüfer2 As Integer
For Prüfer2 = Prüfer To Prüfer + 6
If Int(Mid(Debitor, Prüfer2, 1)) = 1 Or 2 Or 3 Or 4 Or 5 Or 6 Or 7 Or 8 Or 9 Then
PrüferLänge = PrüferLänge + 1
Else
Exit For
End If
Next Prüfer2
If PrüferLänge = 7 Then
Ausgabe = True
GoTo DebitorGefunden
End If
End If
Next Prüfer
DebitorGefunden:
DebitorVorhanden = Ausgabe
End Function
If Int(Mid(Debitor, Prüfer2, 1)) = 1 Or 2 Or 3 Or 4 Or 5 Or 6 Or 7 Or 8 Or 9 Then
is always true and therefore the if case is running. The Or 2 statements return the value 2 and do not compare the two to the int(...) value.
A working solution would be:
dim tmp
tmp=Int(Mid(Debitor, Prüfer2, 1))
If tmp=1 or tmp=2 or tmp=3 Then
A shorter ways is:
If InStr("123456789", Mid(Debitor, Prüfer2, 1) ) Then
The Or operator "performs a logical disjunction on two expressions."
So expressions on either side of the operator are treated entirely separately.
Meaning that for it to work, it would have to be something like this:
If Int(Mid(Debitor, Prüfer2, 1)) = 1 Or Int(Mid(Debitor, Prüfer2, 1)) = 2 Or Int(Mid(Debitor, Prüfer2, 1)) = 3....
There are several ways to solve the problem; a common approach to handle numbers would be to use the Select Case statement, as you can do things like Case 1 To 9
But I like the InStr approach by Samuel
Related
I have a sheet with 2 tables. I want to find and return the cell of column 1 which has the minimum proteges.
For example, my code would return either Phil,Levy or Sean, Montain in the first run. (then my spreadsheet will add +1 to one of the two - this is already set in excel). etc....
Coach List Protégées
Phil, Levy 7
Sean, Monteine 7
Victor, Chatelais 8
I have write a code but unfortunately ot does it randomly. Any thoughts ?
Code:
Dim Coach As String
Dim ws As Worksheet, t As ListObject, r As Long
For Each t In MyWorksheet.ListObjects
Select Case t.Name
Case "Table1", "Table3", "Table4", "Table6", "Table8", "Table10", "Table12", "Table14", "Table16"
'do nothing
Case Else
'Coach = Application.WorksheetFunction.Min(t.ListColumns(2).Range)--> could use that ?
For r = 1 To t.DataBodyRange.Rows.Count
For r = t.DataBodyRange.Rows.Count To 1 Step -1
If t.DataBodyRange(r, 2) <= t.DataBodyRange(r + 1, 2) Then
Coach = t.DataBodyRange(r , 1)
End If
Next r
End Select
Next t
I think your method needs a variable for the lowest number found as each row is compared.
p = 9999
For r = 1 To t.DataBodyRange.Rows.Count
If t.DataBodyRange(r, 2) <= p Then
p = t.DataBodyRange(r, 2)
Coach = t.DataBodyRange(r, 1)
End If
Next r
I have a DataGridView with 8 Rows. In the following Sub i have an If statement to only do something when i is less than the RowCount, this is purposely so when i use (i + 1) on the last row it will still be in range, yet it is not? I can't figure out why. Would appreciate any help.
This is the sub
Public Sub Durations(dgv As DataGridView)
For i As Integer = 0 To dgv.RowCount
Dim intTotalMinutesOfRows As Integer
Dim IntHoursForRows As Integer
Dim intMinutesForRows As Integer
If i < dgv.RowCount Then
If dgv.Rows(i).Cells("EmployeeID").Value = dgv.Rows(i + 1).Cells("EmployeeID").Value _
And dgv.Rows(i).Cells("Date").Value = dgv.Rows(i + 1).Cells("Date").Value Then
intTotalMinutesOfRows = intTotalMinutesOfRows + dgv.Rows(i).Cells("TotalDurationOfRow").Value
Else
intTotalMinutesOfRows = intTotalMinutesOfRows + dgv.Rows(i).Cells("TotalDurationOfRow").Value
IntHoursForRows = Math.Floor(intTotalMinutesOfRows / 60)
intMinutesForRows = intTotalMinutesOfRows Mod 60
dgv.Rows(i).Cells("TotalDurationForDay").Value = "" & IntHoursForRows & " Hrs " & intMinutesForRows & " Mins"
intTotalMinutesOfRows = 0
End If
End If
Next
Iterate to RowCount - 1 only:
For i As Integer = 0 To dgv.RowCount - 1
^^^
Note that despite you've got If i < dgv.RowCount Then, later in this conditional operator you're trying to access Rows(i + 1), which causes the exception for i = dgv.RowCount - 1. So you have to change your condition to If i < dgv.RowCount - 1 Then as well.
Indexes are zero-based (they start at 0), so index 7 is the 8th row.
Row : 1 2 3 4 5 6 7 8
Index : 0 1 2 3 4 5 6 7
Infact even your loop's end is wrong, because i will go to whatever RowCount is. Thus if RowCount is 8 then i will be 8 as well in the end (which doesn't work, as seen in the indexes above).
In order to loop to the last index you must loop to RowCount - 1:
For i As Integer = 0 To dgv.RowCount - 1
I'm working on a scorecard at work which has columns representing 4 possible outcomes, for example:
Successful,
unsuccessful,
Exceptional,
Other
Each staff member is assessed 5 times in the month against those ratings. So 1 person might have 3 successful, 2 exceptional, 0 unsuccessful, 0 other.
So the max instances of each outcome is 5 but the total sum of instances can't be more than 5.
I could try to type out all the combinations (and get them wrong) - is there any function/formula/VBA that anyone knows of that will list out all of the possible combinations of outcomes for me?
e.g. 5000,4100,4010,4001,3200,3020,3002,3110,3011, etc...
Since your numbers can range from 0005 to 5000, you could just write a simple loop that tests each number to see if the digits total 5:
Sub GetPermutations()
Dim i As Long
For i = 5 To 5000
If SumDigits(i) = 5 Then Debug.Print Format$(i, "0000")
Next
End Sub
Function SumDigits(s As Variant) As Long
Dim i As Long
For i = 1 To Len(s)
SumDigits = SumDigits + CLng(Mid$(s, i, 1))
Next
End Function
Alternatively:
Dim w As Long, x As Long, y As Long, z As Long
For w = 0 To 5
For x = 0 To 5
For y = 0 To 5
For z = 0 To 5
If w + x + y + z = 5 Then Debug.Print w & x & y & z
Next
Next
Next
Next
c#:
// numbering 1 to 4 - i.e.
// 1 sucessful, 2 unsucessful, 3 exception, 4 other
for(int i=1;i<4;i++)
{
for(int n=1;n<4;n++)
{
for(int d=1;d<4;d++)
{
for(int q=1;q<4;q++)
{
if(i+d+n+q<=5)
Console.WriteLine(i+n+d+q+", ");
}
}
}
}
EDIT: just saw you asked for vba:
For number1 As Integer = 1 To 4 Step 1
For number2 As Integer = 1 To 4 Step 1
For number3 As Integer = 1 To 4 Step 1
For number4 As Integer = 1 To 4 Step 1
if(number1+number2+number3+number4<=5) Then
Debug.WriteLine(number1.ToString & number2.toString &number3.toString &number4.ToString & ",");
End If
Next number4
Next number3
Next number2
Next number1
The most simple solution I could think of, there's probably better though.
Thanks for your help everyone - i managed to use a combination of suggestions by starting with the number 1, auto-filling down to 5000, then "text to columns", fixed width to separate the digits, sum to 5, filter and hey presto! Seems to have produced the right number of possible combinations adding up to 5.
Thanks again for your help!
I don't know why this code doesn't work ..i wanna just convert text to number .. It doesn't give me any error but it doesn't work
Public Function ConvertCOMPLEXITYToNumber(ByVal chain As String) As Integer
Select Case chain
Case "1 - Très difficile"
ConvertCOMPLEXITYTToNumber = 1
Case "2 - Difficile"
ConvertCOMPLEXITYTToNumber = 2
Case "3 - Modérée"
ConvertCOMPLEXITYTToNumber = 3
Case "4 - Facile"
ConvertCOMPLEXITYTToNumber = 4
Case Else
ConvertCOMPLEXITYTToNumber = 0
End Select
Exit Function
End Function
That may be because you may have unwanted leading or trailing spaces which fails the comparison. Also you do not need Exit Function at the end of the code. It will exit any ways :)
Try this
Public Function ConvertCOMPLEXITYToNumber(ByVal chain As String) As Integer
Dim Num As Integer
Select Case Trim(chain)
Case "1 - Très difficile": Num = 1
Case "2 - Difficile": Num = 2
Case "3 - Modérée": Num = 3
Case "4 - Facile": Num = 4
Case Else: Num = 0
End Select
ConvertCOMPLEXITYToNumber = Num
End Function
If IsNumeric(Left(Trim(chain),1)) Then
ConvertCOMPLEXITYToNumber = Left(Trim(chain),1)
Else
ConvertCOMPLEXITYToNumber = 0
End If
Here, my approach for you:
Public Function ConvertCOMPLEXITYToNumber(ByVal chain As String) As Integer
'Get the first character
chain = Left(Trim(chain), 1)
'If frist character is numeric
If IsNumeric(chain) Then
'If first number is less than 5, return value
If chain < 5 Then
ConvertCOMPLEXITYToNumber = CInt(chain)
End If
End If
End Function
So I'm developing a minesweeper game and im assigning the mines, but i'm unable to create a algorithm to stop a mine to go to a place where there's already a mine, here's what i have so far:
Public Sub initflags()
Dim line, column As Integer
For line = 0 To 9
For column = 0 To 9
mat(line, column) = 0
Next
Next
Dim numbandeiras As Integer
Dim r, c As Integer
Do Until numbandeiras = 34
Randomize()
line = Int(Rnd() * 10)
column = Int(Rnd() * 10)
r = line
c = column
If r And c = 1 Then
mat(line, column) = 0
Else
numbandeiras = numbandeiras + 1
Call avisinhos()
mat(line, column) = 1
End If
Loop
End Sub
Could someone help me?
Best regards, joao.
The simplest thing to do is to check before setting, e.g:
if mat(line, column) = 0 then
numbandeiras = numbandeiras + 1
avisinhos()
mat(line, column) = 1
end if
You need to store all placed "mines" in an array of some sort. This is better in the end if you want to do something with those mines. If you have mines as objects it makes them even better for now they can have states like dead, alive or "?" like MS version.
Just my 2 cents.