I am working on an assignment for school where I have to validate a data entry. My first issue is that running the function does not produce an error message when I run the code and use any other letter as customer type.
My second issue is that the 40% discount for the Else clause that is commented out is applying even though it is commented out.
Private Sub GetDiscountPercent(customerType As String, subtotal As Decimal,
ByRef discountPercent As Decimal)
If customerType = "R" Then
If subtotal < 100 Then
discountPercent = 0
ElseIf subtotal >= 100 AndAlso subtotal < 250 Then
discountPercent = 0.1D
ElseIf subtotal >= 250 Then
discountPercent = 0.25D
End If
ElseIf customerType = "C" Then
If subtotal < 250 Then
discountPercent = 0.2D
Else
discountPercent = 0.3D
End If
'Else
'discountPercent = 0.4D
End If
End Sub
Private Sub btnExit_Click(sender As Object,
e As EventArgs) Handles btnExit.Click
Me.Close()
End Sub
Private Sub ClearResultBoxes(sender As Object,
e As EventArgs) _
Handles txtCustomerType.TextChanged, txtSubtotal.TextChanged
txtDiscountPercent.Text = ""
txtDiscountAmount.Text = ""
txtTotal.Text = ""
End Sub
Function IsValidCustomerType() _
As Boolean
If IsValidCustomerType = "R" Then
MessageBox.Show("Customer Type has to be R or C or T", "Entry Error")
txtCustomerType.Select()
Return False
Else
Return True
End If
If Not IsValidCustomerType = "C" Then
MessageBox.Show("Customer Type has to be R or C or T", "Entry Error")
txtCustomerType.Select()
Return False
Else
Return True
End If
End Function
End Class
I am working on an assignment for school where I have to validate a data entry. My first issue is that running the function does not produce an error message when I run the code and use any other letter as customer type.
Speculating that this is wrong:
Function IsValidCustomerType() _
As Boolean
If IsValidCustomerType = "R" Then
^^^^^^^^^^^^^^^^^^^^^^^^^
MessageBox.Show("Customer Type has to be R or C or T", "Entry Error")
txtCustomerType.Select()
Return False
Else
Return True
End If
If Not IsValidCustomerType = "C" Then
MessageBox.Show("Customer Type has to be R or C or T", "Entry Error")
txtCustomerType.Select()
Return False
Else
Return True
End If
End Function
End Class
You've declared that this function returns a boolean. You cannot compare this to a string in a meaningful way, and if option strict is on it won't even compile.
Even if you could compare a bool with a string the logic of this is wrong. If you managed to make Type = C, then the code will never reach that check because it either returns true or false (in this case false) because C is not R, so while C is valid, you'll never check for it being C, because the code will only ever consider if it's R or not
You need to stop coding and write out your algorithm using pen and paper
My second issue is that the 40% discount for the Else clause that is commented out is applying even though it is commented out.
Gonna go out on a limb here and say that because this code is wrong, or because of some other compiler error elsewhere, you're seeing a dialog that says "There were build errors. Whould you like to run the last successful build?" and youre saying "Yes", and you're running a version of the app where that code isn't commented out..
Related
I'm trying to get return false when a/b where b is equal to 0 so that my error message appears to the user. So far I've managed to do a check within my sub but I need the check to be within the function. Currently, I get a infinity as the result, when for example 7 is divided by 0. I've basically made a pretty basic calculator and would appreciate any help.
Function:
Private Function validationCheck() As Boolean
' The following checks if the two fields are numerical values, are not blank and if the 2nd number is not zero
'The latter is for the purpose of division
'If the fields meet the above conditions then true is returned
'Else if either one is not met, then false is returned
If IsNumeric(txt1stNumber.Text) And txt1stNumber.Text <> "" And IsNumeric(txt2ndNumber.Text) And txt2ndNumber.Text <> "" Then
Return True
Else
Return False
End If
End Function
Division Sub
Private Sub btnDivide_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDivide.Click
'The following sub is the code for the division button.
'First it checks whether false is returned from the ValidationCheck funtion
'If so, an error message is shown
'Else if true is returned, then the values are divided together to form the result
If validationCheck() = False Then
MsgBox("Please enter a numerical value for both fields. Also, field cannot be left blank.")
ElseIf validationCheck() = True Then
lblResult.Text = Val(txt1stNumber.Text) / Val(txt2ndNumber.Text)
End If
You can add one more condition into you function to evaluate txt2ndNumber.Text like this, then if the number b is 0 or 00 like this this will also return false.
Private Function validationCheck() As Boolean
If IsNumeric(txt1stNumber.Text) And txt1stNumber.Text <> "" And IsNumeric(txt2ndNumber.Text) And txt2ndNumber.Text <> "" Then
Dim number As Double = txt2ndNumber.Text
If number = 0 Then
Return False
Else
Return True
End If
Else
Return False
End If
End Function
Recently I have been tasked with making a calculator in VB. It must include stuff like logic or denary/binary/hex conversions. When I was making the binary->denary conversion I encountered a thing where an if statement checking if the inputted number is binary always returned true and activated. Here is the code for the binary conversion system: (please forgive me for the goto's)
Private Sub bbin_Click(sender As Object, e As EventArgs) Handles bbin.Click
If temp = IsNumeric(inputbox.Text) Then
MessageBox.Show("Value Not Numeric", "ERROR", MessageBoxButtons.OK)
inputbox.Text = ""
Else
For i = 1 To Len(inputbox.Text)
If Mid(inputbox.Text, i, 1) <> "0" Or Mid(inputbox.Text, i, 1) <> "1" Then
MessageBox.Show("Value Not Binary", "ERROR", MessageBoxButtons.OK)
inputbox.Text = ""
GoTo skipbin
End If
Next
For x = 1 To Len(inputbox.Text)
If Mid(inputbox.Text, x, 1) = "1" Then
decnum = decnum + 2 ^ (Len(inputbox.Text) - (x - 1))
End If
Next
binnum = inputbox.Text
inputbox.Text = ""
End If
textbox.Text = "Dec = " + decnum.ToString + " Bin = " + binnum.ToString + " Hex = " + hexnum.ToString
skipbin:
End Sub
Let me explain:
The inputbox is the place where the user can input the numbers/operations. The first If checks if the value inputed is a number.
Then a check is ran to ensure the number is binary. (this is where im having problems)
The conversion is ran. It doesn't work as intended at the moment, but I'm sure I'll get it working.
Then the binary and denary values get displayed in a second textbox that I use to display the answers.
The problem I'm having is only with this section: (again, forgive me for the goto functions)
For i = 1 To Len(inputbox.Text)
If Mid(inputbox.Text, i, 1) <> "0" Or Mid(inputbox.Text, i, 1) <> "1" Then
MessageBox.Show("Value Not Binary", "I AM ERROR", MessageBoxButtons.OK)
inputbox.Text = ""
GoTo skipbin
End If
Next
It's supposed to check each digit if it's a 1 or a 0, and if not, it displays an error and skips the conversion.
What do I need to change to make the input validation work as intended?
You need And instead of Or.
When you get a bit of code that you can't figure out why it doesn't work, it is often a good idea to make the minimal bit of code that shows the problem - removing everything else can often lead you to the problem.
In this case, to confirm my answer was correct, I used this:
Option Infer On
Option Strict On
Module Module1
Sub Main()
Dim s = "000012"
For i = 1 To Len(s)
Dim c = Mid(s, i, 1)
If c <> "0" And c <> "1" Then
Console.WriteLine("Value Not Binary: {0}", c)
End If
Next
Console.ReadLine()
End Sub
End Module
You can use AndAlso instead of And: it eliminates any unnecessary processing of the clauses (known as short-circuiting). Similarly, there is OrElse instead of Or.
Your problem is your condition result is always true for any binary number.
try this instead
Dim currentChar = CInt(Mid(InputBox.Text, i, 1))
If currentChar <> 0 And currentChar <> 1 Then
MessageBox.Show("Value Not Binary", "ERROR", MessageBoxButtons.OK)
InputBox.Text = ""
GoTo skipbin
End If
So I've been working on this project for a couple of weeks, as I self teach. I've hit a wall, and the community here has been so helpful I come again with a problem.
Basically, I have an input box where a user inputs a name. The name is then displayed in a listbox. The name is also put into an XML table if it is not there already.
There is a button near the list box that allows the user to remove names from the list box. This amends the XML, not removing the name from the table, but adding an end time to that name's child EndTime.
If the user then adds the same name to the input box, the XML gets appended to add another StartTime rather than create a new element.
All of this functions well enough (My code is probably clunky, but it's been working so far.) The problem comes when I try to validate the text box before passing everything through to XML. What I am trying to accomplish is that if the name exists in the listbox on the form (i.e hasn't been deleted by the user) then nothing happens to the XML, the input box is cleared. This is to prevent false timestamps due to a user accidentally typing the same name twice.
Anyhow, I hope that makes sense, I'm tired as hell. The code I've got is as follows:
Private Sub Button1_Click_2(sender As System.Object, e As System.EventArgs) Handles addPlayerButton.Click
playerTypeCheck()
addPlayerXML()
clearAddBox()
End Sub
Private Sub playerTypeCheck()
If playerTypeCBox.SelectedIndex = 0 Then
addMiner()
ElseIf playerTypeCBox.SelectedIndex = 1 Then
addHauler()
ElseIf playerTypeCBox.SelectedIndex = 2 Then
addForeman()
End If
End Sub
Private Sub addMiner()
If minerAddBox.Text = String.Empty Then
Return
End If
If minerListBox.Items.Contains(UCase(minerAddBox.Text)) = True Then
Return
Else : minerListBox.Items.Add(UCase(minerAddBox.Text))
End If
If ComboBox1.Items.Contains(UCase(minerAddBox.Text)) = True Then
Return
Else : ComboBox1.Items.Add(UCase(minerAddBox.Text))
End If
End Sub
Private Sub addPlayerXML()
If System.IO.File.Exists("Miners.xml") Then
Dim xmlSearch As New XmlDocument()
xmlSearch.Load("Miners.xml")
Dim nod As XmlNode = xmlSearch.DocumentElement()
If minerAddBox.Text = "" Then
Return
Else
If playerTypeCBox.SelectedIndex = 0 Then
nod = xmlSearch.SelectSingleNode("/Mining_Op/Miners/Miner[#Name='" + UCase(minerAddBox.Text) + "']")
ElseIf playerTypeCBox.SelectedIndex = 1 Then
nod = xmlSearch.SelectSingleNode("/Mining_Op/Haulers/Hauler[#Name='" + UCase(minerAddBox.Text) + "']")
ElseIf playerTypeCBox.SelectedIndex = 2 Then
nod = xmlSearch.SelectSingleNode("/Mining_Op/Foremen/Foreman[#Name='" + UCase(minerAddBox.Text) + "']")
End If
If nod IsNot Nothing Then
nodeValidatedXML()
Else
Dim docFrag As XmlDocumentFragment = xmlSearch.CreateDocumentFragment()
Dim cr As String = Environment.NewLine
Dim newPlayer As String = ""
Dim nod2 As XmlNode = xmlSearch.SelectSingleNode("/Mining_Op/Miners")
If playerTypeCBox.SelectedIndex = 0 Then
newMinerXML()
ElseIf playerTypeCBox.SelectedIndex = 1 Then
newHaulerXML()
ElseIf playerTypeCBox.SelectedIndex = 2 Then
newForemanXML()
End If
End If
End If
Else
newXML()
End If
End Sub
Private Sub nodeValidatedXML()
If playerTypeCBox.SelectedIndex = 0 Then
minerValidatedXML()
ElseIf playerTypeCBox.SelectedIndex = 1 Then
haulerValidatedXML()
ElseIf playerTypeCBox.SelectedIndex = 2 Then
foremanValidatedXML()
End If
End Sub
Private Sub minerValidatedXML()
If minerListBox.Items.Contains(UCase(minerAddBox.Text)) = False Then
appendMinerTimeXML()
End If
End Sub
Private Sub appendMinerTimeXML()
Dim xmlSearch As New XmlDocument()
xmlSearch.Load("Miners.xml")
Dim docFrag As XmlDocumentFragment = xmlSearch.CreateDocumentFragment()
Dim cr As String = Environment.NewLine
Dim newStartTime As String = Now & ", "
Dim nod2 As XmlNode = xmlSearch.SelectSingleNode("/Mining_Op/Miners/Miner[#Name='" & UCase(minerAddBox.Text) & "']/StartTime")
docFrag.InnerXml = newStartTime
nod2.AppendChild(docFrag)
xmlSearch.Save("Miners.xml")
End Sub
And lastly, the clearAddBox() subroutine
Private Sub clearAddBox()
minerAddBox.Text = ""
End Sub
So, I should point out, that if I rewrite the nodeValidated() Subroutine to something like:
Private Sub nodeValidatedXML()
If playerTypeCBox.SelectedIndex = 0 Then
appendMinerTimeXML()
ElseIf playerTypeCBox.SelectedIndex = 1 Then
appendHaulerTimeXML()
ElseIf playerTypeCBox.SelectedIndex = 2 Then
appendForemanTimeXML()
End If
End Sub
then all of the XML works, except it adds timestamps on names that already exist in the list, which is what i'm trying to avoid. So if I haven't completely pissed you off yet, what is it about the minerValidated() subroutine that is failing to call appendMinerTimeXML()? I feel the problem is either in the minerValidated() sub, or perhaps clearAddBox() is somehow firing and I'm missing it? Thanks for taking the time to slog through this.
Edit: Clarification. The code as I have it right now is failing to append the XML at all. Everything writes fine the first time, but when I remove a name from the list and then re-add, no timestamp is added to the XML.
You need to prevent the user accidentally typing the name twice.(Not sure if you mean adding it twice)
For this I believe you need to clear the minerAddBox.Text in your addminer() if this line is true.
minerListBox.Items.Contains(UCase(minerAddBox.Text)) = True
minerAddBox.Text = ""
Return
Now it will return back to your addplayerXML which will Return to your clearbox(), since you have this in your addplayerXML()
If minerAddBox.Text = "" Then
Return
Now you get to your clearbox() (Which is not really needed now since you cleared the minerAddBox.Text already)
when I remove a name from the list and then re-add, no timestamp is added to the XML.
your minerValidatedXML() is true, because you are not clearing the textbox when you re-add a name to the list box. Or you may need to remove the existing listbox item if it is the same as the textbox
If minerListBox.Items.Contains(UCase(minerAddBox.Text)) = True Then
minerListBox.Items.remove(UCase(minerAddBox.Text))
I keep getting a error and because of this my code wont work. The error is "Function 'DisplayArray' doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used". I can't get rid of this error. I'm new to programming, can anyone help?
Private Function DisplayArray() As String
Dim j As Integer = 0
ReDim Preserve Array(UpperSub)
Dim AddNum As Double = 0.0
txtAddNum.Focus()
If Double.TryParse(txtAddNum.Text, AddNum) Then
If AddNum > 100 Then
MessageBox.Show("Number must be below 100")
ElseIf AddNum < 0 Then
MessageBox.Show("Number must be above 0")
Else
Array(UpperSub) = CDec(AddNum)
UpperSub = UpperSub + 1
End If
Else
MessageBox.Show("Value has to be a number")
End If
txtAddNum.Clear()
txtDisplay.Clear()
For j = 0 To UpperSub - 1
txtDisplay.Text = txtDisplay.Text _
& CStr(Array(j)) & ControlChars.NewLine
Next
txtNumberOfScores.Text = CStr(UpperSub)
End Function
A Function is designed to return a result, using the Return keyword. Your Function does not have a Return statement. Since none of the possible code paths (determined by branching on the If statements as well as the flow from beginning to end) return a value, you're getting this part of the error message: "Function 'DisplayArray' doesn't return a value on all code paths."
The second part of the error message means that if you tried to assign the return value of the Function to a variable, like this:
Dim result As String = DisplayArray()
You'd get a null value, as nothing is returned from the function.
The simplest solution is to change from a Function to a Sub. Subs in VB.NET do not return a value. So change
Private Function DisplayArray() As String
To
Private Sub DisplayArray()
And
End Function
To
End Sub
Note that the As String() in the Function declaration says this method will return a value that is a String, and the Sub has no return value (again, because it doesn't return a value).
To make this a Function that returns a value, you'll have to return at least one value from the method. Here's an example:
Private Function DisplayArray() As String
Dim j As Integer = 0
ReDim Preserve Array(UpperSub)
Dim AddNum As Double = 0.0
txtAddNum.Focus()
If Double.TryParse(txtAddNum.Text, AddNum) Then
If AddNum > 100 Then
MessageBox.Show("Number must be below 100")
Return String.Empty
ElseIf AddNum < 0 Then
MessageBox.Show("Number must be above 0")
Return String.Empty
Else
Array(UpperSub) = CDec(AddNum)
UpperSub = UpperSub + 1
txtAddNum.Clear()
txtDisplay.Clear()
For j = 0 To UpperSub - 1
txtDisplay.Text = txtDisplay.Text _
& CStr(Array(j)) & ControlChars.NewLine
Next
Return CStr(UpperSub)
End If
Else
MessageBox.Show("Value has to be a number")
Return String.Empty
End If
End Function
Essentially, if the validation fails, an empty string is returned. If the validation passes, the rest of the code is executed and the string value of UpperSub is returned.
You could then assign it to the TextBox like this:
txtNumberOfScores.Text = DisplayArray()
The above is a simple example based on your posted code, intended to show you how to return values from a Function. Adjust it to fit your needs (or use a Sub instead). Given that you want to update the display of the txtDisplay with the array and txtNumberOfScores as well you should do fine with a Sub.
I am doing my homework for my visual basic class. I have most of the code written and everything seems to be working well except for my If Not statement that catches the exception when the loop does not find what it is looking for. Anyone see a problem with the way the code looks. The file is loaded in using the browse button already and it works find when I enter information that the loop can find.
Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Handles btnSearch.Click
'event level variables
Dim Found As Boolean
Dim Counter As Integer
'looks for entry match
If rdoAbbrev.Checked = True Then
Do Until Found Or Counter > 257
If Country(Counter).Abbreviation.ToUpper = txtAbbrev.Text.ToUpper Then
Found = True
txtCountry.Text = Country(Counter).Names
Else
Counter += 1
End If
Loop
Else
Do Until Found Or Counter > 257
If Country(Counter).Names.ToUpper = txtCountry.Text.ToUpper Then
Found = True
txtAbbrev.Text = Country(Counter).Abbreviation
Else
Counter += 1
End If
Loop
If Not Found Then
MessageBox.Show("This is not a valid entry.", "NO MATCH FOUND", MessageBoxButtons.OK)
If rdoAbbrev.Checked = True Then
txtAbbrev.Text = ""
txtAbbrev.Focus()
Else
txtCountry.Text = ""
txtCountry.Focus()
End If
End If
End If
'match not found response
'reset variables
Counter = 0
Found = False
End Sub
You If Not Found block only occurs if rdoAbbrev.Checked = True. Is that what you intended? If not, then that block of code should either be located outside of the first If block (below it) or you should have a second If block after the first While loop.
EDIT
It looks like Country is an array. You should probably use Counter >= Country.Length.
Arrays in VB.NET are 0-based. Meaning that the first item is located at Country(0), the second item is at Country(1), etc. If there are 100 elements in the array, then the last element is located at Country(99). Country(100) does not exist and will cause an Exception if you try to access it.
I'm not sure what the requirements of your homework are, but usually to iterate over the elements of a collection (array, list, etc), you would use a For loop. You can jettison from the loop early with the Exit command.
For Counter As Integer = 0 To Country.Length - 1
'...Country(Counter)
If Found Then Exit For
Next
Assuming you want the "Not Found" part to execute regardless of the rdoAbbrev.Checked property, it looks like a slight error in your logic (easily fixed).
Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click
'event level variables
Dim Found As Boolean
Dim Counter As Integer
'looks for entry match
If rdoAbbrev.Checked = True Then
Do Until Found Or Counter > 257
If Country(Counter).Abbreviation.ToUpper = txtAbbrev.Text.ToUpper Then
Found = True
txtCountry.Text = Country(Counter).Names
Else
Counter += 1
End If
'You could also write this as:
'Found = Country(Counter).Abbreviation.ToUpper = txtAbbrev.Text.ToUpper
'If Found Then
' txtCountry.Text = Country(Counter).Names
'Else
' Counter += 1
'End If
Loop
Else
Do Until Found Or Counter > 257
If Country(Counter).Names.ToUpper = txtCountry.Text.ToUpper Then
Found = True
txtAbbrev.Text = Country(Counter).Abbreviation
Else
Counter += 1
End If
'You could also write this as:
'Found = Country(Counter).Names.ToUpper = txtCountry.Text.ToUpper
'If Found Then
' txtAbbrev.Text = Country(Counter).Abbreviation
'Else
' Counter += 1
'End If
Loop
End If
'match not found response
'Move your "Not Found" here so that the not found works regardless of the rdoAbbrev.Checked property.
If Not Found Then
MessageBox.Show("This is not a valid entry.", "NO MATCH FOUND", MessageBoxButtons.OK)
If rdoAbbrev.Checked = True Then
txtAbbrev.Text = ""
txtAbbrev.Focus()
Else
txtCountry.Text = ""
txtCountry.Focus()
End If
End If
'reset variables
Counter = 0
Found = False
End Sub
Probably you should End the If statements within their range in the code and avoid ending all your If statements at the end of the code lines. usually works for me in Basic. I think that Basic has a lot of advantages, but for me it still not a high level language that has some problems because it is so easy to work with.