Do Until Loop InputBox infinitely loops - vba

I am creating a probability macro where user enters number of players in a card game. If I enter string (ex, Joe), non-integer(ex, 15.67), or integer less than 0 (ex, -25), the InputBox should loop. However, integers greater than 0 should terminate the loop. (I have to force kill Excel to stop the InputBox regardless of user input.)
I want the InputBox to close / Exit Sub once an integer greater than 0 is entered. What am I doing wrong here?
Sub GenerateCards()
Players = InputBox("How many players? Please enter an integer.")
Do Until TypeName(Players) = "Integer" And Players > 0 ' why does this loop even if both conditions are met (ex, Players=5?)
Players = InputBox("How many players? Please enter an integer.")
Loop
End Sub

InputBox() always returns a string, so TypeName() will always return "String".
But you can test if the string that's returned is an integer. First, you can use IsNumeric() to test if the string is a numeric value. Then, you can safely cast it to a Double or an Integer. In fact, you can cast it to both and then compare them against each other. If they're the same, you've got an integer value. For example:
Sub GenerateCards()
Do
Players = InputBox("How many players? Please enter an integer.")
If IsNumeric(Players) Then
If CDbl(Players) = CLng(Players) And Players > 0 Then
' Integer > 0 entered. Exit loop...
Exit Do
End If
End If
Loop
End Sub

Related

(VB.Net) Prevent Duplicates from being added to a list box

I'm having some trouble with catching duplicates in an assignment I'm working on.
The assignment is a track and field race manager. Times are read from a text file, a bib number is then entered for each time loaded from the text file (aka, however many rows there are in the time text file)
The bib numbers and times are then synced in the order from which they were entered. A requirement is that the Bib numbers must be entered one at a time using an input box. Every time a bib number is entered, it is loaded to a list box called lstBibs.
The Issue
I have limited experience working with input boxes, and any attempts Ive made so far to check for duplicates has been ignored in Runtime. I'm also unsure where I would put a loop that checks for duplicates in the input box. Below is my code so far.
Dim i As Integer = 0
Dim Bibno As Integer = 0
Dim strrow As String = ""
Dim count As Integer = 0
Dim errorCount1 As Integer = 0
'Reads through the number of rows in the Time Text File.
'The Number of rows we have in the text file corresponds to the number
'of bib numbers we need. Thus the input box will loop through bib
'numbers until
'we reach the amount of loaded times
Try
For Each item In lstTimeEntry.Items
i += 1
For Bibno = 1 To i
count += 1
Bibno = InputBox("Enter Bib #" & count)
lstBibs.Items.Add(count & " - " & Bibno)
btnSyncTimesBibs.Enabled = True
Next
Next
Catch ex As Exception
'Catches any invalid data that isnt a number
MsgBox("Invalid Input, Please Try Again", , "Error")
lstBibs.Items.Clear()
btnSyncTimesBibs.Enabled = False
End Try
So I'm assuming that I must use a for loop that checks each list box item for a duplicate, I'm just unsure where this loop would go in relation to the code above.
Any and all help is very much appreciated. Thank you.
Don't use exception handling for something that isn't exceptional. Exceptionsl things are things beyond our control like a network connection that isn't available. A user failing to enter proper input is not at all exceptional. Validate the input. Don't make the user start all over again by clearing the list, just ask him to re-enter the last input.
I validate the user input with a TryParse. If the first condition succeeds then the AndAlso condition is checked. It the TryParse fails then the AndAlso condition is never evaluated so we will not get an exception. The second condition is checking if the number has already been used. Only if both conditions pass do we add the number to the used numbers list, update the lstBibs and increment the count.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim Bibno As Integer
Dim count As Integer = 1
Dim usedNumbers As New List(Of Integer)
Do While count <= lstTimeEntry.Items.Count
Dim input = InputBox("Enter Bib #" & count)
If Integer.TryParse(input, Bibno) AndAlso Not usedNumbers.Contains(Bibno) Then
usedNumbers.Add(Bibno)
lstBibs.Items.Add(count & " - " & Bibno)
count += 1
Else
MessageBox.Show("Please enter a number that does not appear in the list box")
End If
Loop
End Sub
As per Steven B suggestion in the comments, you can check it like this:
If Not listTimeEntry.Items.Contains(itemToBeInserted) Then
listTimeEntry.Items.Add(itemToBeInserted)
End If

Forcing user to enter one entry from two options not to write it together

i have two text boxes : percentage and txtamount
i want to force user to enter percentage or amount not to write it together
casue if he did entered % and amount it makes some problems with me as i have alot of formulas
thanks
What I have tried:
privite sub post_click()
If (Me.percentage.Value >= 0 And Me.txtamount.Value >= 0) Then MsgBox " You should select % or amount ": Exit Sub
If you want to ensure that one (and only one) of your two textboxes has a value in it, use the following:
Private Sub post_Click()
If Not (Me.percentage.Value = "" Xor Me.txtamount.Value = "") Then MsgBox "You should select % or amount": Exit Sub
Testing for >= 0 won't work if the textbox is empty (because "" >= 0 will give a type mismatch). Testing for whether the textbox is "" will give a better indication of whether data has been entered.
Using Xor (which returns True iff one operand is True and the other is False) will therefore determine whether only one textbox has been filled in and the other left empty, and the Not will display the message if that is not the case.

VBA simple test if an integer is a repeating number?

I have an integer I'd like to test to see if it is a repeating number, ie
999
9999
99999
the input value range for what the integer is being used for is any three to five digit number, and sometimes that number may be all 9's. Outside of just using multiple OR statements, I'm wondering if there is a more "elegant" way to test this?
Something like this =(LEN(SUBSTITUTE(A1,MID(A1,1,1),""))=0)
Here is a short little example to help you get started. This vba code checks to see if it is one of your repeating numbers (999,9999,99999) and makes a message box if it is or not one of your repeating numbers.
Sub Test()
Dim MyVal As Long
MyVal = Range("A1").Value
If MyVal = 999 Or MyVal = 9999 Or MyVal = 99999 Then
MsgBox "Integer is a repeating number."
Else
MsgBox "Integer is not a repeating number."
End If
End Sub

Visual Basic - How to sort highest and lowest number of a series?

****I don't necessarily want the code to fix this problem, I would just like if someone would be able to explain to me why this is happening or what I could have done better to solve this problem.****
I have a homework assignment where I need to print out the highest and lowest number of a series.I am currently able to print out the highest and lowest numbers but if all of the numbers entered are positive, then it displays my lowest number as 0, and same if all the entered numbers are negative.
So if someone would be able to explain how to solve this, without necessarily giving away the answer, it would be greatly appreciated!
Here is my code:
Module Module1
'This is going to have the user enter a series of numbers,
'Once the user is finished have them enter '-99' to end the series,
'then it is going to return largest and smallest number
Sub Main()
NumSeries()
End Sub
'This is going to get the series from the users
Sub NumSeries()
Dim largeNum As Integer = 0
Dim smallNum As Integer = 0
Dim userNum As Integer = 0
Dim largeTemp As Integer = 0
Dim smallTemp As Integer = 0
Console.WriteLine("Please enter a series of positive and negative numbers")
Console.WriteLine("Then type '-99' to end the series")
Console.WriteLine()
While (userNum <> -99)
Console.Write("Enter num: ")
userNum = Console.ReadLine()
If (userNum > largeTemp) Then
largeTemp = userNum
largeNum = largeTemp
ElseIf (userNum < smallTemp And userNum <> -99) Then
smallTemp = userNum
smallNum = smallTemp
End If
End While
Console.WriteLine("The largest number is " & largeNum)
Console.WriteLine("The smallest number is " & smallNum)
End Sub
End Module
Two points:
You don't need the variables largeTemp and smallTemp.
(The answer to your question) You should initialize largeNum to a very small number, and smallNum to a very large number. For example, if smallNum is set to zero at the beginning of the program, only numbers smaller than zero will replace it. To find an error like this, you should trace through the program either by hand or with a debugger and see what happens at each step. It would be a good idea to do this now so you'll understand the problem. (Alternatively, as Idle-Mind pointed out, you can initialize largeNum and smallNum to the first item in the list.)
Don't use any sentinel values at all. Simply declare a Boolean variable so you know if you the value retrieved is the very first one or not:
Dim FirstEntry As Boolean = True
If it is, then set both largeNum and smallNum to that value. Now just compare each additional entered value with those stored values to see if they are bigger or smaller than the previously known extreme.
A few things you should improve upon:
You can remove the temp variables. They don't serve any other purpose other than unnecessarily consuming memory and CPU time.
You should initialize your min and max variables with highest and lowest possible values respectively. If you think larger than integer values should be allowed, change the type to Long
Dim largeNum As Integer = Integer.MinValue
Dim smallNum As Integer = Integer.MaxValue
Remove the ElseIf. Use two If statements instead. This is so that both variables will be set with the very first input itself.
If (userNum > largeNum) Then largeNum = userNum
If (userNum < smallNum) Then smallNum = userNum

What's Wrong With my logic in this Vb program?

I'm new to visual basic and I just started taking classes on it at school. I was given an assignment to write an app that tells if an input in a textbox is a Prime Number Or Not.
I have written this code snippet in Visual Studio:
Public Class PrimeNumberApp
Public Sub CheckButton_Click(sender As Object, e As EventArgs) Handles CheckButton.Click
Dim x, y As Integer
x = Val(PrimeTextBox.Text)
For y = 2 To (x - 1)
Select Case x
Case Is = (33), (77), (99)
MsgBox("Its not a prime number, try a different number!")
Exit Sub
End Select
If x Mod y = 0 Then
MsgBox("Its not a prime number, try a different number!")
Exit Sub
Else
MsgBox("Its a prime number, you're golden!")
Exit Sub
End If
Next
Select Case x
Case Is <= 0
MsgBox("I'm only accepting values above 0. :p")
Exit Sub
End Select
End Sub
I have this code snippet displaying a Message Box telling whether the input by the user is a prime number or not with the help of the Mod operator in visual basic.
If you go through the code carefully, you'll notice I had to separately create more or less escape statements for the number 33, 77 and 99.
I had to do this cause every time I typed either of those three numbers, I'd get the result that the number is a prime number which is incorrect since they're all divisible by numbers apart from themselves. Without getting things mixed up, the program displays other prime and non-prime numbers with the right Message Box, just those three.
I had spent hours trying to figure out what I had done wrong before I added the lines below to put myself out of vb misery, lol.
Select Case x
Case Is = (33), (77), (99)
MsgBox("Its not a prime number, try a different number!")
Exit Sub
End Select
But doing this isn't healthy if I really want to be awesome at coding. So here's my question, how do I get this program fixed to display the right message box when any integer is typed in the text box. Thanks.
Your code doesn't seem to work at all. It seems to always say that every number is a prime number. You loop through every possible divisor and in that loop you test to see if the input is evenly divisible by the current divisor. That part makes sense. The problem, though is that you always immediately exit the loop after the first iteration regardless of the result of the test. Pay close attention to this code from inside your loop:
If x Mod y = 0 Then
MsgBox("Its not a prime number, try a different number!")
Exit Sub
Else
MsgBox("Its a prime number, you're golden!")
Exit Sub
End If
If we remove all of the spurious details, you can tell that the logic is flawed:
If MyTest = True Then
Exit Sub
Else
Exit Sub
End If
As you can see, no matter what the result of the test is, it's always going to exit the loop. Therefore, the loop will never progress beyond the first iteration. In order to make it continue testing every possible divisor, you need to remove the Exit Sub statements and just keep track of the result in a variable. For instance, something like this:
Dim isPrime As Boolean = True
For y = 2 To x - 1
If XIsEvenlyDivisibleByY Then
isPrime = False
Exit For
End If
Next
If isPrime Then
' ...
Else
' ...
End If
Notice that once the first evenly divisible divisor is found, I have it Exit For. There's no point in searching any further since one is enough to make it not prime.
For what it's worth, you should use Integer.TryParse rather than Val and you should use MessageBox.Show rather than MsgBox. Val and MsgBox are old VB6 style functions. It's preferable to use the newer .NET-only versions.
here is an example of how to find prime numbers, for example up to 100, using 2 loops to check every single number in a given range. In this case I started by 2 because as you know 2 is the smallest of the prime numbers.
Dim i As Integer = 2, j As Integer = 2
For i = 2 To 100
For j = 2 To (i / j)
If i Mod j = 0 Then
Exit For
End If
Next
If (j > (i / j)) Then
Console.WriteLine("{0} is prime", i)
End If
Next