This little test program has a lot of user input validation.
About 10 years ago, while working as a pipefitter, I was called upon to figure out how to fit a riser pipe onto a reducer. Since the reducer is tapered, there was no normal way to do it.
I had to calculate as a best guess as to what my dimensions would be based on what I already knew about fitting pipe to pipe. It didn’t turn out near as pretty as I would have hoped, but a grinder does wonders to finish getting it closer to where it needed to be.
While I’m currently laid off, even though I haven’t had to do one of these since then, I finally decided to set down and figure out all of the math involved to create the 8 points and lengths needed for half of the riser circle and to be able to add the differences in the taper of the reducer. It took about 3 days working on and off to complete the formula to do all of the calculations required.
Do to the massive amount of calculations required to output the final 8 lengths, I wanted to create a program that does all of the math for the user.
My first hurdle is the user input validation. I need to validate if the person is inputting a decimal, a fraction or some off the wall entry.
Since the normal user would input a fraction, I searched for a premade function on the internet for the fraction to decimal conversion. I found this one here from a March 14, 2008 blog post. You find very few that go from fraction to decimal. Most samples go from decimal to fraction.
After removing an extra EndIf
, the code worked fine for converting a fraction to a decimal (see code below).
Private Function FractionToDecimal(ByVal frac As String) As String
Dim decimalVal As String = "0"
Dim upper As Decimal = 0
Dim lower As Decimal = 0
Dim remain As Decimal = 0
If frac.IndexOf("/") <> -1 Then
If frac.IndexOf(" ") <> -1 Then
remain = CType(frac.Substring(0, frac.IndexOf(" ")), Decimal)
frac = frac.Substring(frac.IndexOf(" "))
End If
upper = CType(frac.Substring(0, frac.IndexOf("/")), Decimal)
lower = CType(frac.Substring(frac.IndexOf("/") + 1), Decimal)
decimalVal = (remain + (upper / lower)).ToString
End If
Return decimalVal
End Function
After getting the code to work, I then started thinking about user input validation. I added validation for every type of malformed input I could think of and gave the ability to return an error or return the result of the conversion.
As you can see, the first screenshot is a normal conversion. The second screenshot shows the fraction with the enumerator larger than the denominator, I could have allowed this type of input, but in this case I am catching for when people swap the two numbers.
Now the Final Code
Imports System.Text.RegularExpressions
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
Me.Text = "Convert Fraction to Decimal " & My.Application.Info.Version.ToString
End Sub
Private Sub btnConvert_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnConvert.Click
Dim regx As New Regex("^[a-zA-Z]")
Dim inputNfo As String
inputNfo = tbUserInput.Text
Dim outputStr As String = Nothing
If IsNumeric(inputNfo) = True Then
outputStr = inputNfo
tbOutput.ForeColor = Color.Green
lblInputValidation.Text = "Input is Valid"
lblInputValidation.ForeColor = Color.Green
ElseIf regx.IsMatch(inputNfo) = True Then
outputStr = "Please check you are not Spelling your whole number"
lblInputValidation.Text = "Input is Not Valid"
lblInputValidation.ForeColor = Color.Red
ElseIf inputNfo.Contains("/") And inputNfo.Contains(".") = False Then
Dim ReturnString As String
ReturnString = FractionToDecimal(inputNfo)
If ReturnString = "Error Please Check Fraction" Then
outputStr = ReturnString
tbOutput.ForeColor = Color.Red
lblInputValidation.Text = "Input is Not Valid"
lblInputValidation.ForeColor = Color.Red
Else
outputStr = ReturnString
tbOutput.ForeColor = Color.Green
lblInputValidation.Text = "Input is Valid"
lblInputValidation.ForeColor = Color.Green
End If
ElseIf inputNfo = Nothing Or inputNfo = " " Then
outputStr = "Nothing was input"
tbOutput.ForeColor = Color.Red
lblInputValidation.Text = "Nothing was input"
lblInputValidation.ForeColor = Color.Red
Else
outputStr = "Input not reconised"
tbOutput.ForeColor = Color.Red
lblInputValidation.Text = "Input not reconised "
lblInputValidation.ForeColor = Color.Red
End If
tbOutput.Text = outputStr.ToString
End Sub
Private Function FractionToDecimal(ByVal frac As String) As String
Dim decimalVal As String = "0"
Dim upper As Decimal = 0
Dim lower As Decimal = 0
Dim remain As Decimal = 0
If frac.IndexOf("/") <> -1 Then
If frac.IndexOf(" ") <> -1 Then
remain = CType(frac.Substring(0, frac.IndexOf(" ")), Decimal)
frac = frac.Substring(frac.IndexOf(" "))
End If
End If
upper = CType(frac.Substring(0, frac.IndexOf("/")), Decimal)
lower = CType(frac.Substring(frac.IndexOf("/") + 1), Decimal)
If upper > lower Then
Return "Error Please Check Fraction"
Else
decimalVal = (remain + (upper / lower)).ToString
End If
Return decimalVal
End Function
End Class
Starting from the top, we need the “Imports System.Text.RegularExpressions
” for checking user input in the second test.
Next, we set inputNfo
as a string
and equal it to the input text.
Then, we run the inputNfo
through the VB.NET built-in IsNumeric
function to see if it is a recognized decimal number, if it is, then just return that number to the output textbox. No conversion needs to be done.
If inputNfo
is not recognized as a number, we then pass it to the regular expression test and make sure the user is not trying to spell out the number (three instead of 3), if they are, it returns an error, if not, then it passes on to the next test.
The next test would be to find out if the character “/
” is in the string
and also to make sure the character “.
” is not in the string, if it is, then the user input looks something like:
“22. 3/4” , with the decimal in place, it will return an error.
We could add more code to handle that problem and fix it but, why baby the user, make them input the information correctly so they don’t get used to inputting the information incorrectly.
If it passes all of those tests, then the string / number gets passed to the actual function that does the conversion. While in the conversion function we verify that the fraction does not have a larger enumerator than a denominator. Our users should not need to input the fraction in this way. (For the final program that this sample app. was built to test.)
If it fails the test, then it returns an error message, (as in the screenshot above). If it passes, then it returns the result of the Conversion as a decimal.
Conclusion
Again, due to the massive amount of calculations, my final program will require, I need to validate every possible way a user could input a number so the end result would be a decimal, and then I would be able to do the calculations on the input parameters.
If I catch all possible input errors, then any output errors should be easier to trace and fix.
The output of the 8 lengths in my final application will then be converted back from a decimal to a fraction rounded to the nearest 1/16th of an inch.