Results 1 to 37 of 37

Thread: Distance Calculator

  1. #1

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Distance Calculator

    I am a little confused with this assignment and haven't touched it in a few weeks. Any help is greatly appreciated.

    Name:  Capture.PNG
Views: 2316
Size:  362.9 KB

    I wrote some code initially and wasn't getting anywhere as this is the first assignment we have where we are required to use listboxes and loops. My main question is where it states "The application opens... Enter the speed limit and number of days you plan to drive."

    Now, does this just require the use of 2 listboxes? One that opens initially with the app that just holds the info for speed limit and days planned to drive? Then the second listbox will hold all of the info for hours driving per day?

    Below is the last edit of my code, I have removed some things so its a bit patchy.

    Code:
    Dim strSpeed As String
            Dim decSpeed As Decimal
    
            Dim strDays As String
            Dim decDays As Decimal
    
            Dim strHours As String
            Dim decHours As Decimal
            Dim decTotalMiles As Decimal = 0
    
            Dim strInputMessage As String = "Enter the speed of the vehicle in Miles Per Hour"
            Dim strInputHeading As String = "Vehicle Speed"
            Dim strNormalMessage As String = "Enter the number of days you plan to travel"
            Dim strNormalHeading As String = "Travel Days"
            Dim strHoursMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strHoursHeading As String = " Daily Driving Hours"
            Dim strNonNumericError As String = "Enter Numeric values only"
            Dim strNegativeError As String = "ERROR- Negative values are not allowed"
            Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"
    
            'Loop Variables
            Dim intMaxNumberOfEntries As Integer = 15
            Dim intNumberOfEntries As Integer = 1
            Dim strCancelClicked As String = ""
    
            strHours = InputBox(strHoursMessage & intNumberOfEntries, strHoursHeading, " ")
    
            Do Until intNumberOfEntries > intMaxNumberOfEntries Or strHours = strCancelClicked
    
                If IsNumeric(strSpeed) Then
                    decSpeed = Convert.ToDecimal(strSpeed)
                    If decSpeed >= 1 Then
                        strInputMessage = strNormalMessage
                    Else
                        strInputMessage = strNegativeError
                    End If
                Else
                    strInputMessage = strNonNumericError
                End If
    
                If IsNumeric(strDays) Then
                    decDays = Convert.ToDecimal(strDays)
                    If decDays > 1 Then
                        strInputMessage = strHoursMessage
                    Else
                        strInputMessage = strNegativeError
                    End If
                Else
                    strInputMessage = strNonNumericError
                End If
    
                If IsNumeric(strHours) Then
                    decHours = Convert.ToDecimal(strHours)
                    If decHours >= 1 And decHours <= 20 Then
                        lstData.Items.Add(decHours)
                        decTotalMiles += decHours
                        intNumberOfEntries += 1
                        strInputMessage = strHoursMessage
                    Else
                        strInputMessage = strTwentyError
                    End If
                Else
                    strInputMessage = strNonNumericError
                End If
    
                If intNumberOfEntries <= intMaxNumberOfEntries Then
                    strHours = InputBox(strHoursMessage & intNumberOfEntries, strHoursHeading, " ")
                End If
            Loop
    
            If intNumberOfEntries > 1 Then
                lblTotal.Visible = True
                decTotalMiles = (decSpeed * decHours)
                lblTotal.Text = "Total distance traveled is " & decTotalMiles.ToString("F1") & "miles "
            Else
                MsgBox("No values entered", , "Input Error")
            End If
    
        End Sub

  2. #2
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: Distance Calculator

    To work out what controls are needed you need to read the requirements, which are mainly in the "Algorithms" section.

    Item 1 specifies that you should be able to enter the speed limit, and number of days. You need some way to input those values, which could be via textboxes, or possibly an InputBox. Neither of those options are the "best" way to do things, but seem to be what is expected, and of the two a textbox makes more sense (as the user can then see what they've entered after they've typed it). Using a listbox for those values wouldn't make much sense, because they are very different information (that doesn't mean a listbox isn't wanted there, but there is nothing in the assignment that implies it should be).

    Item 2 specifies that there should be a Distance button that allows you to enter the hours for each day, and then the calculation will be done. There are a few ways this could be done, but it seems that what is wanted is that you add the number of hours per day to a listbox (after checking the input is valid, according to the Notes section). After all values have been entered (which you could do using a loop), do the calculation based on the values in the listbox (which you should do using a loop).


    Note that your current code is trying to do nearly all the work inside one loop, which is very messy (especially as you keep checking strSpeed and strDays, which don't change inside the loop). The code should be several sections, including checking the speed+days values (and not allowing further progress if they aren't valid), inputting the number of hours each day (with some kind of validation of each value), and calculating the final result.

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    I would suggest that you complete each step in Algorithms section before even starting the next. If you try to do everything at once then it becomes a jumble in your mind and a jumble in the code.

    If you read step 1 on its own, would you be thinking about ListBoxes? I hope not. There's nothing there that suggests a list of any kind. If the user has to enter a value then that is usually done via a TextBox. As you're entering numbers, you might consider a NumericUpDown but most beginners don;t even know that that control exists and most teachers will assume a TextBox will be used.

    Step 2 sounds to me like you need another TextBox for input, a Button for the user to click and a ListBox for the value in the TextBox to be added to on that click. It says that the user is to enter the number of hours to travel each day and you have already entered the number of days in step 1, so you would need to limit the number of entries in step 2 based on the data entered in step 1. The loop would come in when you perform a calculation based on the items in the ListBox each time you add a new one. On the click of the Button, add the new value, loop through the list to perform the calculation and then display the result. Displaying a result is usually done with a Label.

    I'll let you take it from there but this is basically how you need to approach these problems, i.e. divide and conquer. Break them down into smaller problems, solve each part separately and then put the partial solutions together. In this case, much of the dividing is already done for you. You simply have to conquer.

  4. #4

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Okay I have made a little progress, I have added another button and 2 TextBox to accommodate for the Speed and Days Traveling variables. However, once more I find myself lost. When the user enters the amount for (Speed Limit & Days Traveling) the 'Distance' button is activated. Now, How can I make the variables from the 'BtnEnter' action transfer to the 'BtnDistance' section? So that the Speed and Days variables are already accounted for and the user will only have to enter the 'Hours' variable?

    I have provided my code that I have completed. Thanks again. Breaking it down into smaller chunks has made it a lot less stressful to think about.

    Code:
     Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnDistance.Click
    
            Dim strHours As String
            Dim decHours As Decimal
            Dim decTotalHours As Decimal
            Dim decTotalMiles As Decimal = 0
            Dim strInputMessage As String = "Enter the amount of hours you plan to drivve on day #"
            Dim strHoursMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strInputHeading As String = " Daily Driving Hours"
            Dim strNonNumericError As String = "Enter Numeric values only"
            Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"
    
            'Loop Variables
            Dim intMaxNumberOfEntries As Integer = 10
            Dim intNumberOfEntries As Integer = 1
            Dim strCancelClicked As String = ""
    
            strHours = InputBox(strHoursMessage & intNumberOfEntries, strInputHeading, " ")
    
            Do Until intNumberOfEntries > intMaxNumberOfEntries Or strHours = strCancelClicked
    
                If IsNumeric(strHours) Then
                    decHours = Convert.ToDecimal(strHours)
                    If decHours > 0 And decHours <= 20 Then
                        lstHours.Items.Add(decHours)
                        decTotalMiles += decHours
                        intNumberOfEntries += 1
                        strInputMessage = strHoursMessage
                    Else
                        strInputMessage = strTwentyError
                    End If
                Else
                    strInputMessage = strNonNumericError
                End If
    
                If intNumberOfEntries <= intMaxNumberOfEntries Then
                    strHours = InputBox(strInputMessage & intNumberOfEntries, strInputHeading, " ")
                End If
            Loop
    
            'Calculates and displays total miles
            If intNumberOfEntries > 1 Then
                lblTotal.Visible = True
                decTotalMiles = decTotalHours * decSpeed
                lblTotal.Text = "Total Distance is " &
                    decTotalMiles.ToString("F1") & " miles"
            Else
                MsgBox("No weight loss value entered")
            End If
    
        End Sub
    
        Private Sub mnuDistance_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles mnuDistance.ItemClicked
    
        End Sub
    
        Private Sub DistanceCalculator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            lstHours.Items.Clear()
            txtSpeedLimit.Clear()
            txtDays.Clear()
            lblTotal.Text = ""
            lblTotal.Visible = False
            btnEnter.Enabled = True
            btnDistance.Enabled = False
    
        End Sub
    
        Private Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
    
            'Button for Speed Limit and Days Traveling 
            Dim decSpeed As Decimal
            Dim decDays As Decimal
    
            If Decimal.TryParse(txtSpeedLimit.Text, decSpeed) And Decimal.TryParse(txtDays.Text, decDays) Then
                If decSpeed >= 50 And decSpeed <= 85 Then
                    If decDays >= 1 And decDays <= 10 Then
                        btnDistance.Enabled = True
                    Else
                        MsgBox("Enter Days you plan to travel. 1-10")
                    End If
    
                Else
                    MsgBox("Enter Speed limit. 50-85 MPH", , "Input Error")
                End If
    
            Else
                MsgBox("Please Enter Numeric Information", , "Input Error")
                txtSpeedLimit.Text = ""
                txtDays.Text = ""
                txtSpeedLimit.Focus()
            End If
        End Sub
    End Class

  5. #5
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    You can't transfer variables from one method to another. If a variable is declared inside a method then that's the only place that variable exists. If you need to access the same variable from more than one method then you need to declare it outside all of them, as a member variable, also known as a field. You're clearly already doing that for some so you'll need to add those ones to the list.

  6. #6

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    That has me even more confused.... I am only asking for (speed, days) in one section, and (hours) in another section. So even then how would I declare a variable in that section when the user inputs information into another? I am browsing through my book and see no mention of a 'Member Variable' or 'Field'. I'm not sure how I can set a decimal variable in one section when the user enters the number in another.

  7. #7
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Distance Calculator

    It's in there, but there are a wide variety of names it could be using. 'Member variable' does seem like the most common, but form-level variable is also common.

    Basically, you are declaring a bunch of variables. If you declare them within a method, then they are only visible inside that method, and only exist for the life of that method. Most variables declared within a method are destroyed as soon as you reach that End Sub (or End Function). There's a way to change that, which is why I said "most variables", but that is an obscure edge case.

    If you declare a variable outside of any method, but still in the form, then that variable has class scope. Such a variable is visible to all methods in the class, and will exist as long as the class exists. If you aren't familiar with classes....forms are classes, and you ARE familiar with forms.

    Therefore, anything that will be used between different functions will need to be in a variable declared at class scope, so just move those variables outside of the function. You are declaring variables with Dim, which you have to do inside methods. Dim will also work fine outside of methods, but it is more common to declare them Private (or Friend or Public, but that's a different matter).
    My usual boring signature: Nothing

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    Does the word "outside" confuse you? You are currently declaring those variables INSIDE a method so they are only accessible to code INSIDE that method. If you declare the variables OUTSIDE all the methods then it is accessible to all those methods. A variables declared inside a method is called a local variable while a variable declared outside a method is called, amongst other things, member variables or fields. Anything that can be accessed directly on a type or an instance of a type is a member, i.e. anything that can be access using SomeType.SomeMember or someObject.SomeMember. All your methods a members, as are properties, events and variables that are not local to a method. If you read the MSDN documentation for any type you'll see a Members section, where it lists all the externally accessible members. There are rarely any fields listed as they are normally only used internally, i.e. declared Private, just as in this case.

  9. #9

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    So it would just be easier to have 1 button?

    a- check speed and day variables
    b- hold day variable and move to hours
    c- enter hours determined by 'days' variable
    d- calculate total miles traveled

  10. #10
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: Distance Calculator

    Most of us wouldn't think it was easier, and based on what you said earlier I don't think you would either.

    I suspect that you are confused about the explanations above, so here's a simple example:
    Code:
        Private Sub mnuDistance_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles mnuDistance.ItemClicked
            Dim variableThatOnlyExistsInThisSub as Integer  'inside a sub
        End Sub
    
        Dim variableThatExistsInTheWholeForm as Integer  'outside a sub

  11. #11

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Okay I found the three paragraphs in my book that reference the 'class' variable. The example is given on a sales tax app and says "the variable should be referenced in the form load event. The variable must be declared before the first procedure in the program." The code example in my book looks as so.

    Code:
     Public Class frmSalesTaxCalculator
    
        Const _cdecSalesTax As Decimal = 0.0875D
    
        Private Sub frmSalesTaxCalculator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
           
            lblSalesTaxHeading.Text = _cdecSalesTax.ToString("P") & "Sales Tax"
            lblTotalCost.Text = ""
            lblSalesTaxTotal.Text = ""
            txtName.Focus()
    
        End Sub
    So seeing as how the variable is set as a constant it will hold the same value throughout. Should my code look similar to the following.

    Code:
    Public Class DistanceCalculator
    
        Dim strSpeed As String
        Dim strDays As String
        Const _cstrSpeed = txtSpeedLimit.Text
        Const _cstrDays = txtDays.Text
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
    
        End Sub

  12. #12
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Distance Calculator

    Perhaps that's not the best book. That IS a class level variable, but it's a constant. If you replace Const with Private, you'd get to what we are talking about. Constants are pretty much what they sound like: Constant. There is a use for them, but I wouldn't say they are common. Meanwhile class variables that are NOT constant are quite common. You don't HAVE to assign them a value when you create them, either. If you can, then it's not bad to do so, but sometimes you can't. This is one of those times that you can't.

    What you are doing there won't work for the simple reason that the textboxes don't exist when this line runs:

    Const _cstrSpeed = txtSpeedLimit.Text

    The textboxes are just controls. They are created in code just like pretty much everything else. That code is hidden, but if you wanted to see it (along with a whole bunch of class variables that violate the rule your book stated) then you can find them in the .designer.vb file that is associated with the form. In that file is a function called InitializeComponents that does nothing more than create all the controls for the form, position them, and set any properties they have. Until this method runs, the controls simply don't exist. However, any variable created at class scope has to be created before any code runs in the class, so they are created before InitializeComponents has had a chance to run.

    So, what you actually want is something more like this:

    Code:
    Public Class DistanceCalculator
    
        Private strSpeed As String
        Private strDays As String
        Private_cstrSpeed As Decimal
        Private _cstrDays As Decimal
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
    
        End Sub
    My usual boring signature: Nothing

  13. #13
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Distance Calculator

    As a class. You'd need to figure out how to replace the random values with the users input.

    Code:
        Private Shared prng As New Random
        Private Trip As List(Of TravelSegment)
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Trip = New List(Of TravelSegment)
    
            Const n As Integer = 3
            For x As Integer = 1 To n 'add n random segments
                Dim aSeg As New TravelSegment
                aSeg.SpeedInMPH = prng.Next(35, 91) 'random speed 35 to 90 MPH
                aSeg.DaysTraveledAtSpeed = CDec(prng.NextDouble())  'random time traveled
                Trip.Add(aSeg)
            Next
    
            'what the data looks like
            For Each ts As TravelSegment In Trip 'info
                Debug.WriteLine("Speed: {0:n0}  Days: {1:n2}  Hours: {2:n2}  Distance: {3:n2}", ts.SpeedInMPH, ts.DaysTraveledAtSpeed, ts.HoursTraveledAtSpeed, ts.SpeedInMPH * ts.HoursTraveledAtSpeed)
            Next
    
            Dim distance As Decimal = Trip.Sum(Function(ts) ts.MilesTraveled())
            Debug.WriteLine("Total Distance: {0:n2}", distance)
        End Sub
    
        Public Class TravelSegment
            Public Shared ReadOnly OneHourAsDay As Decimal = 1D / 24D
            Public SpeedInMPH As Decimal = 0D
            Public DaysTraveledAtSpeed As Decimal = 0D
    
            Public Function MilesTraveled() As Decimal
                Dim hours As Decimal = 24D * Me.DaysTraveledAtSpeed
                Return Me.SpeedInMPH * hours
            End Function
    
            Public Function HoursTraveledAtSpeed() As Decimal
                Return 24D * Me.DaysTraveledAtSpeed
            End Function
        End Class
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  14. #14

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    I have already decided that this is not the best book. Just about everything I have come on here for help I have been redirected in a much easier and cleaner way. I brought it up with our instructor actually and he said the same thing, "most of what you learn in the book you wont actually apply". Oh well!

    I have cleaned up my code now and its not showing any errors. When it loads though, the 'BtnEnter' code doesn't seem to work at all, but I am able to bypass and click the 'distance' button. I didn't add the 'enter' button until i had already wrote code for my 'distance' button. Is it because the distance code is listed before?

    Code:
    Public Class DistanceCalculator
    
        Private strSpeed As String
        Private strDays As String
        Private _cstrSpeed As Decimal
        Private _cstrDays As Decimal
    
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
    
        End Sub
    
        Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles mnuExit.Click
    
            Close()
    
        End Sub
    
        Private Sub mnuClear_Click(sender As Object, e As EventArgs) Handles mnuClear.Click
    
            lstHours.Items.Clear()
            lblTotal.Visible = False
            btnDistance.Enabled = True
    
        End Sub
    
        Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnDistance.Click
    
            Dim decspeed As Decimal
            Dim strHours As String
            Dim decHours As Decimal
            Dim decTotalHours As Decimal
            Dim decTotalMiles As Decimal = 0
            Dim strInputMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strHoursMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strInputHeading As String = " Daily Driving Hours"
            Dim strNonNumericError As String = "Enter Numeric values only"
            Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"
    
            'Loop Variables
            Dim intMaxNumberOfEntries As Integer = 10
            Dim intNumberOfEntries As Integer = 1
            Dim strCancelClicked As String = ""
    
            strHours = InputBox(strHoursMessage & intNumberOfEntries, strInputHeading, " ")
    
            Do Until intNumberOfEntries > intMaxNumberOfEntries Or strHours = strCancelClicked
    
                If IsNumeric(strHours) Then
                    decHours = Convert.ToDecimal(strHours)
                    If decHours > 0 And decHours <= 20 Then
                        lstHours.Items.Add(decHours)
                        decTotalMiles += decHours
                        intNumberOfEntries += 1
                        strInputMessage = strHoursMessage
                    Else
                        strInputMessage = strTwentyError
                    End If
                Else
                    strInputMessage = strNonNumericError
                End If
    
                If intNumberOfEntries <= intMaxNumberOfEntries Then
                    strHours = InputBox(strInputMessage & intNumberOfEntries, strInputHeading, " ")
                End If
            Loop
    
            'Calculates and displays total miles
            If intNumberOfEntries > 1 Then
                lblTotal.Visible = True
                decTotalMiles = decTotalHours * decSpeed
                lblTotal.Text = "Total Distance is " &
                    decTotalMiles.ToString("F1") & " miles"
            Else
                MsgBox("No value entered")
            End If
    
        End Sub
    
        Private Sub mnuDistance_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles mnuDistance.ItemClicked
    
        End Sub
    
        Private Sub DistanceCalculator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            lstHours.Items.Clear()
            txtSpeedLimit.Clear()
            txtDays.Clear()
            lblTotal.Text = ""
            lblTotal.Visible = False
            btnDistance.Enabled = False
            btnEnter.Enabled = True
    
        End Sub
    
        Private Sub btnEnter_Click(sender As Object, e As EventArgs)
    
            'Button for Speed Limit and Days Traveling 
            Dim decSpeed As Decimal
            Dim decDays As Decimal
    
            If Decimal.TryParse(txtSpeedLimit.Text, decSpeed) And Decimal.TryParse(txtDays.Text, decDays) Then
                If decSpeed >= 50 And decSpeed <= 85 Then
                    If decDays >= 1 And decDays <= 10 Then
                        btnDistance.Enabled = True
                    Else
                        MsgBox("Enter Days you plan to travel. 1-10")
                    End If
    
                Else
                    MsgBox("Enter Speed limit. 50-85 MPH", , "Input Error")
                End If
    
            Else
                MsgBox("Please Enter Numeric Information", , "Input Error")
                txtSpeedLimit.Text = ""
                txtDays.Text = ""
                txtSpeedLimit.Focus()
            End If
        End Sub
    End Class

  15. #15
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    Take a look at those methods that are supposed to be handling events. Notice that most of them have a Handles clause at the end of the declaration but 'btnEnter_Click' does not? That means that those other methods are handling the specified events whereas that method is not. I'm not sure what you to lose that but there are various ways.

    You can add it back manually, i.e. in the code window, and that's probably the easiest way under the circumstances but there are other ways too. For instance, if you select that Button in the designer, open the Events window and click the Events button on the tool bar, you can then select any existing method with an appropriate signature as the handler for any event. You'll see that the Click event has no handler and you can select one using the drop-down provided. Even if you don't do that now, it's good to know that it's possible for future reference.

  16. #16

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Okay thank you I got that figured out, not sure how I lost that part either. Back to class variables.. When I try and run the code now it at least gets past the BtnEnter handle however it is not holding the values for (Speed and Days) still. In the class they are written (_cstrSpeed) (_cstrDays) for the decimal variable.

    Do I need to replace the (decDays) (decSpeed) variables in the Distance button code with (_cstrSpeed) (_cstrDays)? I know textbox values are always a string and need to be converted. I guess i'm just confused because I'm not sure if I need to label all variables the same or if the class variable knows already.

  17. #17
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    Where in that Click event handler are you assigning values to '_cstrSpeed' and '_cstrDays'? Nowhere, so why would you expect them to have useful values? They're only going hold values if you actually assign a value in the first place. Either get rid of the local variables and just use the fields or at least assign the values of the locals to the fields before completing the method.

    A reason to do the latter is that a failure to pass input will result in a zero value for the variable so using locals will prevent your fields losing their last good value if the user enters invalid input. If that doesn't matter then don't bother with locals at all.

    On an unrelated note, why are those variables named like that? If you're going to use Hungarian Notation then at least use it properly because otherwise you're misleading someone reading the code. Surely the point of using a "str" prefix is to make it obvious that something is a String, but if it's a Decimal then it's worse than useless.

  18. #18

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    You're right they are not assigned values anywhere. This was my first time using a class variable so I was using the example given to me and assumed it was correct; my apologies. I know you guys are all VB experts but I have only started this (my first coding class) 8 weeks ago so I do not understand a lot of the terms and keywords you all use.

    When you say field do you mean class variable? By removing all of my variables in the event handles and leaving the (days, speed) variables as 'Private' class variables will allow me to hold the value entered by the user? This is where I am stuck and cannot figure this out, Why will it not hold the values given in the textbox???

    Code:
    Public Class DistanceCalculator
    
        Private strSpeed As String
        Private strDays As String
        Private decSpeed As Decimal
        Private decDays As Decimal
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
    
        End Sub
    
        Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles mnuExit.Click
    
            Close()
    
        End Sub
    
        Private Sub mnuClear_Click(sender As Object, e As EventArgs) Handles mnuClear.Click
    
            lstHours.Items.Clear()
            lblTotal.Visible = False
            btnDistance.Enabled = True
    
        End Sub
    
        Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnDistance.Click
    
            Dim decspeed As Decimal
            Dim strHours As String
            Dim decHours As Decimal
            Dim decTotalHours As Decimal
            Dim decTotalMiles As Decimal = 0
            Dim strInputMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strHoursMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strInputHeading As String = " Daily Driving Hours"
            Dim strNonNumericError As String = "Enter Numeric values only"
            Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"
    
            'Loop Variables
            Dim intMaxNumberOfEntries As Integer = 10
            Dim intNumberOfEntries As Integer = 1
            Dim strCancelClicked As String = ""
    
            strHours = InputBox(strHoursMessage & intNumberOfEntries, strInputHeading, " ")
    
            Do Until intNumberOfEntries > intMaxNumberOfEntries Or strHours = strCancelClicked
    
                If IsNumeric(strHours) Then
                    decHours = Convert.ToDecimal(strHours)
                    If decHours > 0 And decHours <= 20 Then
                        lstHours.Items.Add(decHours)
                        decTotalMiles += decHours
                        intNumberOfEntries += 1
                        strInputMessage = strHoursMessage
                    Else
                        strInputMessage = strTwentyError
                    End If
                Else
                    strInputMessage = strNonNumericError
                End If
    
                If intNumberOfEntries <= intMaxNumberOfEntries Then
                    strHours = InputBox(strInputMessage & intNumberOfEntries, strInputHeading, " ")
                End If
            Loop
    
            'Calculates and displays total miles
            If intNumberOfEntries > 1 Then
                lblTotal.Visible = True
                decTotalMiles = decTotalHours * decSpeed
                lblTotal.Text = "Total Distance is " &
                    decTotalMiles.ToString("F1") & " miles"
            Else
                MsgBox("No value entered")
            End If
    
        End Sub
    
        Private Sub mnuDistance_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles mnuDistance.ItemClicked
    
        End Sub
    
        Private Sub DistanceCalculator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            lstHours.Items.Clear()
            txtSpeedLimit.Clear()
            txtDays.Clear()
            lblTotal.Text = ""
            lblTotal.Visible = False
            btnDistance.Enabled = False
            btnEnter.Enabled = True
    
        End Sub
    
        Private Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
    
            'Button for Speed Limit and Days Traveling 
            Dim decSpeed As Decimal
            Dim decDays As Decimal
    
            If Decimal.TryParse(txtSpeedLimit.Text, decSpeed) And Decimal.TryParse(txtDays.Text, decDays) Then
                If decSpeed >= 50 And decSpeed <= 85 Then
                    If decDays >= 1 And decDays <= 10 Then
                        btnDistance.Enabled = True
                    Else
                        MsgBox("Enter Days you plan to travel. 1-10")
                    End If
    
                Else
                    MsgBox("Enter Speed limit. 50-85 MPH", , "Input Error")
                End If
    
            Else
                MsgBox("Please Enter Numeric Information", , "Input Error")
                txtSpeedLimit.Text = ""
                txtDays.Text = ""
                txtSpeedLimit.Focus()
            End If
        End Sub
    End Class

  19. #19
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Distance Calculator

    Quote Originally Posted by Bsquared View Post
    I have already decided that this is not the best book. Just about everything I have come on here for help I have been redirected in a much easier and cleaner way. I brought it up with our instructor actually and he said the same thing, "most of what you learn in the book you wont actually apply". Oh well!
    Did you have to pay for that book, and if so, how much? That's what would burn my biscuits.
    My usual boring signature: Nothing

  20. #20

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Actually I have been very upset about this. I had to pay $180 for it but at least my campus bookstore will buy it back for at least 1/2 price depending on condition i return it in. Which at this point might be a pile of charred ashes.

    I am using the (Shelly Cashman Series- Microsoft Visual Basic 2012 Intro)

  21. #21
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: Distance Calculator

    Quote Originally Posted by Bsquared View Post
    When you say field do you mean class variable?
    That's right.
    By removing all of my variables in the event handles and leaving the (days, speed) variables as 'Private' class variables will allow me to hold the value entered by the user? This is where I am stuck and cannot figure this out, Why will it not hold the values given in the textbox???
    Because you didn't remove the variables of the same name in the events:
    Code:
    Public Class DistanceCalculator
    
        Private strSpeed As String
        Private strDays As String
        Private decSpeed As Decimal
        Private decDays As Decimal
    ...
    
        Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnDistance.Click
    
            Dim decspeed As Decimal
            Dim strHours As String
            Dim decHours As Decimal
            Dim decTotalHours As Decimal
    ...
    
        Private Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
    
            'Button for Speed Limit and Days Traveling 
            Dim decSpeed As Decimal
            Dim decDays As Decimal
    Remove the lines I highlighted in red.

  22. #22

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Okay I did that but it is still doing the same thing. Is there something I'm completely missing here? I thought that would hold the value of the text boxes.

    Name:  calculator.PNG
Views: 1867
Size:  92.7 KB

    I should only be able to add four days worth of driving hours. Is there new script that I need to write in the 'Distance button handler' to make it recognize the value?

  23. #23
    PowerPoster
    Join Date
    Sep 2005
    Location
    Modesto, Ca.
    Posts
    5,196

    Re: Distance Calculator

    Dim intMaxNumberOfEntries As Integer = 10
    You need to set that value to the value in the Days Traveling TextBox.

  24. #24

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    like such? Still having the same problem with it not holding the value.

    Code:
     Private Sub txtSpeedLimit_TextChanged(sender As Object, e As EventArgs) Handles txtSpeedLimit.TextChanged
    
            Dim intNumberOfEntries As Integer = 1
            Dim intMaxNumberOfEntries As Integer = 10
    
        End Sub

  25. #25
    PowerPoster
    Join Date
    Sep 2005
    Location
    Modesto, Ca.
    Posts
    5,196

    Re: Distance Calculator

    Quote Originally Posted by Bsquared View Post
    like such? Still having the same problem with it not holding the value.

    Code:
     Private Sub txtSpeedLimit_TextChanged(sender As Object, e As EventArgs) Handles txtSpeedLimit.TextChanged
    
            Dim intNumberOfEntries As Integer = 1
            Dim intMaxNumberOfEntries As Integer = 10
    
        End Sub
    No, not even close. I don't see you using the TextBox and your in the wrong procedure.

    Code:
        Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnDistance.Click
    
            Dim decspeed As Decimal
            Dim strHours As String
            Dim decHours As Decimal
            Dim decTotalHours As Decimal
            Dim decTotalMiles As Decimal = 0
            Dim strInputMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strHoursMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strInputHeading As String = " Daily Driving Hours"
            Dim strNonNumericError As String = "Enter Numeric values only"
            Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"
    
            'Loop Variables
            Dim intMaxNumberOfEntries As Integer = 10

  26. #26
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Distance Calculator

    Let's try to talk about it by analogy. Programming requires you to look at some things and think, "Oh, it's just like this other thing." It's metaphor, and it helps us talk about complicated things using easily-understood ideas. Textbooks don't often go this deep. They expect a lecture will do that work for them. Fire is a metaphor we can all understand. Let's burn things.

    Private Sub txtSpeedLimit_TextChanged is a large, wooden crate. It's sitting on your front porch. What is inside the crate? You don't know. The box just says "FRAGILE" on it, so you can assume it's Italian. What's inside the crate? You can't tell. So you open it. Now you know what's inside the crate!

    There's another crate on your porch. It also says "FRAGILE" on it. You break it open, and find it had the same stuff inside as the other crate. But it's different stuff, right?

    We have a porch, two crates, and two sets of "stuff" inside the crate. We've also got a third crate marked "FRAGILE". We can assume it's PROBABLY got the same stuff inside, but we can't look at it until we open the crate. Let's focus on this empty box now. We'll burn the open boxes and their contents. It's just the porch and the closed crate now.

    We know there's a basketball in the crate. We want to play basketball. So we open the crate, take the basketball out, and go play with it. We put the basketball on the porch and go inside.

    When we exit again, the old crate's been burned and a new "FRAGILE" crate is on the porch. Also our old basketball. We want to play basketball. We can either:
    • Take the basketball on the porch and play with it.
    • Open the crate, remove its basketball, and play with that basketball.


    But if we burn the porch, we lose the crate AND the basketball. If we want to play basketball, we have to find a new porch, get a "FRAGILE" crate on it, and open it to get a new basketball.

    That is exactly how variables work.

    When a variable is created inside a Sub, it's like the stuff inside the "FRAGILE" crate. It doesn't really exist until you call the sub (open the crate). You can take those things out of the crate if you want (Functions return values.) But if you burn the crate without taking the stuff out, the contents are burned too (After End Sub or End Function, all of the variables are gone again.)

    You can open a new crate (call the Sub/Function again.) You can take things out of it (Functions return values) and put it on the porch (You can create variables outside of the Sub/Function and inside the class.) If you put something on the porch, you can use it again without opening a crate (class variables "live" longer than Subs/Functions). If you burn the porch, everything goes with it (Class variables 'die' with their class.)

    So in #24, both of your variables are inside the crate. When you call that method, it's like you open the crate, look at what's inside, then burn it. What you WANT to do is open the crate, take the basketball and other things out, put those things on the porch, then burn the crate but not the porch.

    So you should do your calculation and store the results in fields so they're on the porch when you burn the crate.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  27. #27

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Can you explain a little more please? When you say assign the value to the text box I think of something like

    decSpeed = txtSpeedLimit.Text

  28. #28
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    Quote Originally Posted by Bsquared View Post
    Can you explain a little more please? When you say assign the value to the text box I think of something like

    decSpeed = txtSpeedLimit.Text
    That's the exact opposite. It's just like maths in school. If you were told to assign the value of X to the Y variable, would you do this:
    Code:
    X = Y
    I would certainly hope not. The value on the right is being assigned to the variable on the left, i.e.
    Code:
    Y = X
    is assigning the value of X to the Y variable. It is EXACTLY the same as the maths you were taught in primary school. So, what do you think that assigning the value of the decSpeed variable to the Text property of the TextBox would look like?

  29. #29

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Oh great! Math was never my strong point. Which I've noticed has actually hampered me on quite a few of these assignments.

    so if its opposite and (x= value, y=text box) then yes I see Y=X but I still am not sure how I code it in the BtnDistance handler, it's not like another variable is it that I need to add a 'dim' in front of? Or is it something simple as

    Code:
    txtSpeedLimit.text = decSpeed
    txtDays.text = decDays
    Apologies, but I've gotten a little lost on this one since I added the (class variables, fields) with having never used them before, it is code i have never used. So I am trying my best to figure this out with what little my book offers, google, and all your input.

  30. #30
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    Not having reread every post to make sure I haven't missed anything, I think you're trying to overcomplicate things. In post #18 you had this:
    Code:
        Private Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
    
            'Button for Speed Limit and Days Traveling 
            Dim decSpeed As Decimal
            Dim decDays As Decimal
    
            If Decimal.TryParse(txtSpeedLimit.Text, decSpeed) And Decimal.TryParse(txtDays.Text, decDays) Then
                If decSpeed >= 50 And decSpeed <= 85 Then
                    If decDays >= 1 And decDays <= 10 Then
                        btnDistance.Enabled = True
                    Else
                        MsgBox("Enter Days you plan to travel. 1-10")
                    End If
    
                Else
                    MsgBox("Enter Speed limit. 50-85 MPH", , "Input Error")
                End If
    
            Else
                MsgBox("Please Enter Numeric Information", , "Input Error")
                txtSpeedLimit.Text = ""
                txtDays.Text = ""
                txtSpeedLimit.Focus()
            End If
        End Sub
    For starters, you're already setting the Text property of some TextBoxes there so I don't understand why that has suddenly become confusing.

    Apart from that, your original issue was that you weren't retaining values between method calls because you were using local variables. I said way back that the solution to that was to use member variables instead. I specifically said that the way to do that was to move your variable declarations from inside the method to outside:
    Code:
        'Button for Speed Limit and Days Traveling 
        Dim decSpeed As Decimal
        Dim decDays As Decimal
    
        Private Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
    
            If Decimal.TryParse(txtSpeedLimit.Text, decSpeed) And Decimal.TryParse(txtDays.Text, decDays) Then
                If decSpeed >= 50 And decSpeed <= 85 Then
                    If decDays >= 1 And decDays <= 10 Then
                        btnDistance.Enabled = True
                    Else
                        MsgBox("Enter Days you plan to travel. 1-10")
                    End If
    
                Else
                    MsgBox("Enter Speed limit. 50-85 MPH", , "Input Error")
                End If
    
            Else
                MsgBox("Please Enter Numeric Information", , "Input Error")
                txtSpeedLimit.Text = ""
                txtDays.Text = ""
                txtSpeedLimit.Focus()
            End If
        End Sub
    That is all that's required, as far as I can tell. Those variables are used inside the method in exactly the same way as they were before inside that method but they are also accessible from other methods because they are declared outside all of them.

    Does that not solve your original issue, i.e. not retaining those values between method calls?

  31. #31
    Fanatic Member kpmc's Avatar
    Join Date
    Sep 2017
    Posts
    1,012

    Re: Distance Calculator

    Here is my distance calculator

    Code:
    Public Class Form1
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim DirStr As String = Nothing
            Dim TotalMiles As Double = Nothing
            Dim TotalMinutes As Double = Nothing
    
            Dim OrigZip As String = "Start Address"
            Dim DestZip As String = "End Address"
    
            'distancematrix
            Dim url As String = "http://maps.googleapis.com/maps/api/distancematrix/xml?origins=" &
                OrigZip & "&destinations=" & DestZip & "&mode=driving&language=en-EN&sensor=false"
    
            'directions
            Dim url2 As String = "https://maps.googleapis.com/maps/api/directions/xml?origin=" &
               OrigZip & "&destination=" & DestZip & "&key=yourGoogleAPIKey"
    
            Dim XMLDoc As XDocument = XDocument.Load(url2)
            For Each ele As XElement In XMLDoc...<step>
                Dim DirectionText As String = "<input type=""checkbox"">" & CType(ele.Element("html_instructions"), String)
                Dim DistanceText As String = CType(ele.Element("distance").<value>.Value, String)
                Dim DistanceMiles As Double = Math.Round(CDbl(DistanceText) / 1609.34, 2)
                Dim DurationText As String = CType(ele.Element("duration").<value>.Value, String)
                Dim DurationMinutes As Double = Math.Round(CDbl(DurationText) / 60, 2)
    
                TotalMiles = TotalMiles + DistanceMiles
                TotalMinutes = TotalMinutes + DurationMinutes
                DirStr = DirStr & DirectionText & " <font color=""red"">" & DistanceMiles & " Miles, " & DurationMinutes &
                    " Minutes</font> <br><br>"
            Next
            Dim BuilHTML As String = "<!DOCTYPE html PUBLIC "" -// W3C // DTD XHTML 1.0 Transitional//EN"" " & vbCrLf &
                    """http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">" & vbCrLf &
                    "<html xmlns=""http://www.w3.org/1999/xhtml"">" & vbCrLf &
                    "<head>" & vbCrLf &
                    "<meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" />" & vbCrLf &
                    "<title>Directions</title>" & vbCrLf &
                    "</head>" & vbCrLf &
                    "<body>" & vbCrLf &
                    "Total Miles=" & TotalMiles & " Total Minutes=" & TotalMinutes & "<br><br>" & vbCrLf &
                    DirStr & vbCrLf &
                    "</body>" & vbCrLf &
                    "</html>"
            WebBrowser1.DocumentText = BuilHTML
        End Sub
    End Class

  32. #32

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Not the first time i've been accused of over complication things with my coding. This however, did not fix my problem but gave me an error.

    I do remember you saying that to remove local variables which I did. I thought the 'Private' class variables at the top were holding my value.

    I'm confused because you said all I needed to do was move variables, and he's telling me I need to add a value to a text box. So i'm not really sure what I need to do. But adding the other variables in between subs didn't do anything for me besides give me and error saying its already been declared in the class.

    Code:
    Public Class DistanceCalculator
    
        Private strSpeed As String
        Private strDays As String
        Private decSpeed As Decimal
        Private decDays As Decimal
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
    
        End Sub
    
        Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles mnuExit.Click
    
            Close()
    
        End Sub
    
        Private Sub mnuClear_Click(sender As Object, e As EventArgs) Handles mnuClear.Click
    
            lstHours.Items.Clear()
            txtSpeedLimit.Clear()
            txtDays.Clear()
            lblTotal.Text = ""
            lblTotal.Visible = False
            btnDistance.Enabled = False
            btnEnter.Enabled = True
    
        End Sub
    
        Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnDistance.Click
    
            Dim strHours As String
            Dim decHours As Decimal
            Dim decTotalHours As Decimal
            Dim decTotalMiles As Decimal = 0
            Dim strInputMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strHoursMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strInputHeading As String = " Daily Driving Hours"
            Dim strNonNumericError As String = "Enter Numeric values only"
            Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"
    
            'Loop Variables
            Dim intMaxNumberOfEntries As Integer = 10
            Dim intNumberOfEntries As Integer = 1
            Dim strCancelClicked As String = ""
    
            strHours = InputBox(strHoursMessage & intNumberOfEntries, strInputHeading, " ")
    
            Do Until intNumberOfEntries > intMaxNumberOfEntries Or strHours = strCancelClicked
    
                If IsNumeric(strHours) Then
                    decHours = Convert.ToDecimal(strHours)
                    If decHours > 0 And decHours <= 20 Then
                        lstHours.Items.Add(decHours)
                        decTotalMiles += decHours
                        intNumberOfEntries += 1
                        strInputMessage = strHoursMessage
                    Else
                        strInputMessage = strTwentyError
                    End If
                Else
                    strInputMessage = strNonNumericError
                End If
    
                If intNumberOfEntries <= intMaxNumberOfEntries Then
                    strHours = InputBox(strInputMessage & intNumberOfEntries, strInputHeading, " ")
                End If
            Loop
    
            'Calculates and displays total miles
            If intNumberOfEntries > 1 Then
                lblTotal.Visible = True
                decTotalMiles = decTotalHours * decSpeed
                lblTotal.Text = "Total Distance is " &
                    decTotalMiles.ToString("F1") & " miles"
            Else
                MsgBox("No value entered")
            End If
    
        End Sub
    
        Private Sub mnuDistance_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles mnuDistance.ItemClicked
    
        End Sub
    
        Private Sub DistanceCalculator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            lstHours.Items.Clear()
            txtSpeedLimit.Clear()
            txtDays.Clear()
            lblTotal.Text = ""
            lblTotal.Visible = False
            btnDistance.Enabled = False
            btnEnter.Enabled = True
    
        End Sub
        'Button for Speed Limit and Days Traveling 
        Dim decSpeed As Decimal
        Dim decDays As Decimal
    
        Private Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
    
            If Decimal.TryParse(txtSpeedLimit.Text, decSpeed) And Decimal.TryParse(txtDays.Text, decDays) Then
                If decSpeed >= 50 And decSpeed <= 85 Then
                    If decDays >= 1 And decDays <= 10 Then
                        btnDistance.Enabled = True
                    Else
                        MsgBox("Enter Days you plan to travel. 1-10")
                    End If
    
                Else
                    MsgBox("Enter Speed limit. 50-85 MPH", , "Input Error")
                End If
    
            Else
                MsgBox("Please Enter Numeric Information", , "Input Error")
                txtSpeedLimit.Text = ""
                txtDays.Text = ""
                txtSpeedLimit.Focus()
            End If
        End Sub
    
        Private Sub txtSpeedLimit_TextChanged(sender As Object, e As EventArgs) Handles txtSpeedLimit.TextChanged
    
    
        End Sub
    End Class

  33. #33
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Distance Calculator

    Try this and observe the difference. It doesn't help you "solve the problem", but you will get an idea of how things are working.

    Code:
    Public Class DistanceCalculator
    
        Private outside As Decimal = 0
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
            Dim inside As Decimal = 10
    
            Dim insideText As String = "inside: " & inside.ToString()
            Dim outsideText As String = " outside: " & outside.ToString()
    
            lblHeader.Text = insideText & outsideText
    
            inside = inside + 10
            outside = outside + 10
        End Sub
    
    End Class
    Run this, and start clicking the label. The first time you click you should see:

    "inside: 10 outside: 10"

    The second time:

    "inside: 10 outside: 20"

    This demonstrates what is happening. Because 'outside' is not part of the Sub, it holds its value. But because 'inside' is created inside the Sub every time, it always starts at 10. So it doesn't matter that the code adds 10 to it at the end. The next time you click the Label, a new 'inside' is created and assigned 10. Now watch this:

    Code:
    Public Class DistanceCalculator
    
        Private outside As Decimal = 0
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
            Dim inside As Decimal = 10
    
            Dim insideText As String = "inside: " & inside.ToString()
            Dim outsideText As String = " outside: " & outside.ToString()
    
            lblHeader.Text = insideText & outsideText
    
            inside = inside + 10
            outside = outside + 10
        End Sub
    
        Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles mnuExit.Click
    
            Dim outsideText As String = "outside: " & outside.ToString()
            lblHeader.Text = outsideText
    
        End Sub
    
    End Class
    Now the "exit" item does something with 'outside'. So it doesn't "exit" anymore, whatever, we're wizards and we're going to do what we want. Click the label a few times. Maybe it says, "inside: 10 outside: 40". Now click the Exit menu item. What's the label say? I bet it says "outside: 40".

    This is how we learn as programmers. When we don't get how something works, we write small programs like this that don't make any sense, but help us understand what is going on. If 'outside' behaved like 'inside' and was reset every time, then clicking the "Exit" button would show it has a value of 10. But it doesn't. Clicking Exit always shows the same value that 'outside' had the last time you clicked the label.

    Now try changing it to this. What happens?
    Code:
    Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles mnuExit.Click
    
        Dim insideText As String = "inside: " & inside.ToString()
        lblHeader.Text = insideText
    
    End Sub
    This won't compile! This is because 'inside' doesn't exist inside this Sub, and it doesn't exist as part of the class. Learn what this error message looks like. You'll see it hundreds of times, and the sooner you know what it means the sooner you'll know exactly what to do to fix it.

    Now change it to this:
    Code:
    Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles mnuExit.Click
    
        Dim inside As Decimal = 100
        Dim insideText As String = "inside: " & inside.ToString()
        lblHeader.Text = insideText
    
    End Sub
    Click the Exit button, and you'll see the value of 'inside' is 100. What do you think you will see if you click the label? Try it. What do you get? Can you explain why?

    Now try this:
    Code:
    Public Class DistanceCalculator
    
        Private inside As Decimal = 0
        Private outside As Decimal = 0
    
        Private Sub lblHeader_Click(sender As Object, e As EventArgs) Handles lblHeader.Click
            Dim inside As Decimal = 10
    
            Dim insideText As String = "inside: " & inside.ToString()
            Dim outsideText As String = " outside: " & outside.ToString()
    
            lblHeader.Text = insideText & outsideText
    
            inside = inside + 10
            outside = outside + 10
        End Sub
    
        Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles mnuExit.Click
            inside = 100
    
            Dim insideText As String = "inside: " & inside.ToString()
            lblHeader.Text = insideText
        End Sub
    
    End Class
    It may not compile, I'm not 100% sure on this. If it doesn't, look at the error message. It means "you have two variables with the same name." Which two variables have the same name? How might you decide how to fix that?

    If it does compile, click each button. Try to guess what you will see each time. If you guess right, good! If not, try to think about why.

    Understanding how to coordinate these 'inside' and 'outside' values is key to writing more complicated programs. But there's already a trick: you just expect txtSpeedLimit to always be there, and always represent the same TextBox. Which kind of variable do you think it is?
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  34. #34
    PowerPoster
    Join Date
    Sep 2005
    Location
    Modesto, Ca.
    Posts
    5,196

    Re: Distance Calculator

    Remove this,
    Code:
        'Button for Speed Limit and Days Traveling 
        Dim decSpeed As Decimal
        Dim decDays As Decimal
    You have already declared these variables at the top of the class,
    Code:
        Private strSpeed As String
        Private strDays As String
        Private decSpeed As Decimal
        Private decDays As Decimal
    I should only be able to add four days worth of driving hours. Is there new script that I need to write in the 'Distance button handler' to make it recognize the value?
    I tried to explain earlier but you didn't seem to catch on.
    Code:
    Do Until intNumberOfEntries > intMaxNumberOfEntries Or strHours = strCancelClicked
    you set "intMaxNumberOfEntries" to 10 so you always be able to enter 10 days. Would it make more sense to use the number of days that were entered?
    Code:
    intMaxNumberOfEntries = decDays
    or

    Code:
    Do Until intNumberOfEntries > decDays Or strHours = strCancelClicked
    I'm assuming that txtDays.Text is the TextBox for Days Traveling.

    I usually don't just provide an exact example, l like to see people solve there problem but this has been going on for 11 days. Maybe you will be able to learn something from seeing the code work correctly.

  35. #35

    Thread Starter
    Member
    Join Date
    Jun 2017
    Posts
    35

    Re: Distance Calculator

    Thanks for clearing the confusion up with the class variables.

    Yeah, I was definitely just overthinking things and confusing myself. Looking at that makes perfect sense, I just get stressed and make things
    scarier than they need to be. That took care of the problem. I also fixed my loop so I am getting the total miles correctly but my labels are acting weird when they pop up with my errors.

    Name:  error1.PNG
Views: 1704
Size:  34.2 KB

    I'm getting the extra number at the end of the message for the corresponding day. Will it always show that?

    Code:
    Dim strInputMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strHoursMessage As String = "Enter the amount of hours you plan to drive on day #"
            Dim strInputHeading As String = " Daily Driving Hours"
            Dim strNonNumericError As String = "Enter Numeric values only"
            Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"

  36. #36
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Distance Calculator

    It will if you write code to do it. The code you've shown us is not the issue. Based on this:
    vb.net Code:
    1. Dim strTwentyError As String = "ERROR - Hours can only be between 1 and 20"
    that 'strTwentyError' variable will contain the text shown in the code. If that's not the text you're seeing then you're doing something wrong somewhere else. The extra "2" doesn't just appear out of thin air. You're putting it there but you haven't shown us the code that does it.

    If you debug your code properly, i.e. set a breakpoint and then step through the code and watch the appropriate variables, then you'll be able to see where for yourself. Debugging is crucial skill in software development so, if you don't know how to do it, you should spend some time to learn now. It will save you immeasurable time in the long run. You simply can't build anything of any complexity without being able to debug.

    By the way, if those Strings aren't actually going to vary then you should declare them as constants rather than variables. That might actually show up the issue if you are changing the value of that variable somewhere. If it becomes a constant then changing its value is not allowed so any code that does will be flagged as a compilation error. If you make that change and the code still compiles then you must be doing something else. If you simply look for every usage of that variable/constant in code then you should probably be able to identify where.

  37. #37
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Distance Calculator

    JMC is right, you wrote code that does this. If I assume #32 is like your most recent code, let's have a look, bolded lines are important.

    Code:
    Do Until intNumberOfEntries > intMaxNumberOfEntries Or strHours = strCancelClicked
    
        If IsNumeric(strHours) Then
            decHours = Convert.ToDecimal(strHours)
            If decHours > 0 And decHours <= 20 Then
                lstHours.Items.Add(decHours)
                decTotalMiles += decHours
                intNumberOfEntries += 1
                strInputMessage = strHoursMessage
            Else
                strInputMessage = strTwentyError
            End If
        Else
            strInputMessage = strNonNumericError
        End If
    
        If intNumberOfEntries <= intMaxNumberOfEntries Then
            strHours = InputBox(strInputMessage & intNumberOfEntries, strInputHeading, " ")
        End If
    Loop
    So if "strength hours" or whatever 'strHours' stands for is numeric, it's converted to Decimal and stored in "Deck Hours" (decHours). If Deck Hours is out of range, "strength input message" is set to "strength hours message". If "internal number of entries" is less than or greater to "internal max number of entries", you decide to show an input box.

    The label is the result of concatenating "strength input message" and "internal number of entries". We know in our case that the value of "strength input message" will be the "strength twenty error". The value of "internal number of entries" will be numeric, let's say 1. So the final string will be "ERROR - Hours can only be between 1 and 201.", becasue that's what you get when you add "1" on the end.

    I'm going to go out on a limb and say InputBox here is a strange choice. You shouldn't use InputBox if the input doesn't matter. You shouldn't care about how many "strength hours" the user input if there was an error. I only get now that you're trying to get a number of hours from the user, and want to display error messages if the input was wrong. This is why in professional code we just don't use InputBox, we prefer to flash an icon next to the TextBox and tell you what you did wrong. But you're writing a classroom example, so we're going to have to make do. That also means I have to hold back a lot of other advice I might give, so let's roll.

    Buy a notebook. Before you write code like this, write out what you want. Like this:
    Ask the user to input a number of hours between 1 and 20. If the input is not numeric, tell them it was a problem and ask again. If the input is not between 1 and 20, tell them it was a problem and ask again.
    If it's more than 3 or 4 sentences, it's too big. If it's more than 2, frown at it and read it over and over to see if there are parts you can cut. I see a part we can cut: in 2 different places, we say "tell them it was a problem and ask again". We do that for 2 different reasons, but the same error message can apply. So now we can rewrite it:
    Ask the user to input a number of hours between 1 and 20. If the input is not valid, tell them it was a problem and ask again.
    That's two sentences, and it's not obvious how to make it 1 sentence, so we're good. Now it's time to start implementing it in code.

    "Ask the user to input a number of hours" is easy:
    Code:
    Dim inputHeader As String = "Daily Driving Hours"
    Dim inputMessage As String = "Please input a number of hours between 1 and 20."
    Dim inputHours As String = InputBox(inputMessage, inputHeader, "")
    "If the input is not between 0 and 20..." is something we can do, this bit of code will be useful:
    Code:
    Dim hours As Decimal = 0
    Dim isValid As Boolean = False
    If Decimal.TryParse(hours) Then
        isValid = 0 < hours AndAlso hours <= 20
    End If
    That gives us a nice 'isValid' Boolean to tell us if the number is valid. It will be false if the text is not a number and it will be false if hte number is out of range.

    "Tell them it is a problem and ask again". OK, hm. We need a loop.
    Code:
    Dim inputHeader As String = "Daily Driving Hours"
    Dim inputMessage As String = "Please input a number of hours between 1 and 20."
    Dim inputHours As String = InputBox(inputMessage, inputHeader, "")
    
    Dim hours As Decimal = 0
    Dim isValid As Boolean = False
    If Decimal.TryParse(inputHours, hours) Then
        isValid = 0 < hours AndAlso hours <= 20
    End If
    
    While Not isValid 
        inputHours = InputBox(inputMessage, inputHeader, "")
    
        If Decimal.TryParse(inputHours, hours) Then
            isValid = 0 < hours AndAlso hours <= 20
        End If
    End While
    We could argue I'm not doing "tell them it's a problem", but I think they'll figure it out. The assignment does not say you need to do that. What makes me frown here is we have repetition again. So I can expand my loop:
    Code:
    Dim inputHeader As String = "Daily Driving Hours"
    Dim inputMessage As String = "Please input a number of hours between 1 and 20."
    Dim isValid As Boolean = False
    Dim hours As Decimal = 0
    
    Do 
    
        Dim inputHours As String = InputBox(inputMessage, inputHeader, "")
    
        Dim isValid As Boolean = False
        If Decimal.TryParse(inputHours, hours) Then
            isValid = 0 < hours AndAlso hours <= 20
        End If
    
    Until isValid
    Finally, I want to read the code back and see how it compares to what I wrote down:
    "Ask the user for a number between 1 and 20. Determine if the number is valid. If the number is not valid, repeat.
    That is more or less the same thing, so I win: I implemented this part of the task.

    This is how I learned to write code 20 years ago, and it's still how I write code today. I often start with a very big blob of code, then after I get it working I start finding ways to make it smaller and leaner. I pick very small, easy-to-understand chunks of code so I can be sure I don't get overwhelmed, and so I don't pay a heavy price if I want to delete it all.

    Very important to this is learning how to work backwards from a visible error to the cause. Here is how I found your error.

    "Oh, hm, the String is wrong? Let's go see where he defines it."

    "Hm, no number there. OK, how about where he displays the InputBox?"

    "Aha, when displaying the input box, he displays the strength input message with the internal number of entries concatenated. That's where the number comes from."
    Get in the habit of thinking like that. Something you didn't expect happened. A line of code you wrote caused it. Find that line of code and ask yourself if what you're seeing matches what it does. 999 times out of 1000 you'll realize you asked the computer to do the wrong thing!
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width