Text Box Calculations - handling empty fields

Hi Experts,

I have 6 textboxes in a webform to record pricing of order items, they are:
txtQuantity
txtUnitCost
txtNetTotal
txtVATRate
txtVAT
txtTotal
Hopefully their individual prpose is self-explanatory.
I am trying to semi-automate the entry of this information to make it as efficient as possible:
I have been partially successful in this using the following code -  
aspx page:
 <tr>
                                    <td>
                                        Quantity:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtQuantity" AutoPostBack="true" OnTextChanged="txtQuantity_TextChanged" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        Unit cost:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtUnitCost" AutoPostBack="true" Text="0" TextMode="SingleLine" ReadOnly="false" OnTextChanged="txtUnitCost_TextChanged" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        Net total:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtNetTotal" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        VAT Rate:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtVATRate" AutoPostBack="true" OnTextChanged="txtVATRate_TextChanged" runat="server"  Text="0.2" TextMode="SingleLine" ReadOnly="false" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        VAT:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtVAT" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        Total:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtTotal" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>

Open in new window


Code Behind:
 protected void txtQuantity_TextChanged(object sender, EventArgs e)
    {

        int qty = Convert.ToInt32(txtQuantity.Text);
        decimal uc = Convert.ToDecimal(txtUnitCost.Text);
        decimal rate = Convert.ToDecimal(txtVATRate.Text);

        if (string.IsNullOrEmpty(txtVATRate.Text) || !string.IsNullOrEmpty(txtVATRate.Text) && (string.IsNullOrEmpty(txtUnitCost.Text) || !string.IsNullOrEmpty(txtUnitCost.Text)))
        {
            txtNetTotal.Text = (qty * uc).ToString();
            txtVAT.Text = (rate * (qty * uc)).ToString();
            txtTotal.Text = ((rate * (qty * uc)) + (qty * uc)).ToString();

        }
    }


    protected void txtUnitCost_TextChanged(object sender, EventArgs e)
    {
        int qty = Convert.ToInt32(txtQuantity.Text);
        decimal uc = Convert.ToDecimal(txtUnitCost.Text);
        decimal rate = Convert.ToDecimal(txtVATRate.Text);

        if (string.IsNullOrEmpty(txtVATRate.Text) || !string.IsNullOrEmpty(txtVATRate.Text) && (string.IsNullOrEmpty(txtUnitCost.Text) || !string.IsNullOrEmpty(txtUnitCost.Text)))
        {
            txtNetTotal.Text = (qty * uc).ToString();
            txtVAT.Text = (rate * (qty * uc)).ToString();
            txtTotal.Text = ((rate * (qty * uc)) + (qty * uc)).ToString();

        }
    }


    protected void txtVATRate_TextChanged(object sender, EventArgs e)
    {
        int qty = Convert.ToInt32(txtQuantity.Text);
        decimal uc = Convert.ToDecimal(txtUnitCost.Text);
        decimal rate = Convert.ToDecimal(txtVATRate.Text);

        if (string.IsNullOrEmpty(txtVATRate.Text) || !string.IsNullOrEmpty(txtVATRate.Text))
        {
            txtNetTotal.Text = (qty * uc).ToString();
            txtVAT.Text = (rate * (qty * uc)).ToString();
            txtTotal.Text = ((rate * (qty * uc)) + (qty * uc)).ToString();
        }
    }

Open in new window


I am having two issues that i'm not sure how best to resolve:

1. Because the calculations expect an int and two decimals if any of the boxes are empty at the point of post-back the page errors - to avoid this I have set the text of UnitCost to 0 and instructed the user to edit this as required, similarly for non-taxable items the VATRate has to be set to 0 it cannot be blank. Perhaps this is the best approach but it makes for a rather clunky feel - is there a way to handle this more gracefully?
2. The calculation runs on each post-back and each post-back runs as the user tabs out of an editable textbox, however at this point all text boxes lose focus and so th user is forced to repeatedly click back into the next box they wish to edit, again it makes the thing feel very clunky. I presume this is related to the postback but I don't quite undersatnd what is happening and therefore how to combat it, can anyone advise please?

Many thanks in advance
forstersAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

käµfm³d 👽Commented:
You can use TryParse to test if the text box values are both populated and valid:

e.g.

int qty;

int.TryParse(txtQuantity.Text, out qty);

Open in new window


If the value contained within txtQuantity.Text is a valid integer, then qty will hold the converted value; otherwise it will hold the default value for an int, which is zero.


Posting back as each field is tabbed out of is excessive. I would suggest either postponing the validation until a submit button is clicked, or add in some Javascript validation to provide a more user-friendly experience. You should not rely solely on Javascript validation for your inputs, though. Still validate on the server.
0
forstersAuthor Commented:
Hi kaufmed,

Thank you for your reply, I had been wondering about TryParse, will that work for the decimals too?

Re. the posting back, I agree but I wasn't sure how to handle the user potentially going back to a box to edit, I think I would like the screen to update as they make any edits so they can check figures as they go.
Javascript makes total sense and was my first attempt, unfortunately I don't really know my way around the language well enough to trouble shoot so when it didn't work I retreated to familiar ground. Ha looks like i'm going to have to face my demons and try again.

Thanks for your help I will have another go and report back!
0
forstersAuthor Commented:
Further to my last I have modified my code behind to include the TryParse as suggested - which solves the problem of empty fields nicely, but obviously leaves me with the postback and focus problem. I have found a promising looking piece of javascript so I will attempt that next :

 protected void txtQuantity_TextChanged(object sender, EventArgs e)
    {
        int qty;
        decimal uc;
        decimal rate;

        int.TryParse(txtQuantity.Text, out qty);
        decimal.TryParse(txtUnitCost.Text, out uc);
        decimal.TryParse(txtVATRate.Text, out rate);
      
            txtNetTotal.Text = (qty * uc).ToString();
            txtVAT.Text = (rate * (qty * uc)).ToString();
            txtTotal.Text = ((rate * (qty * uc)) + (qty * uc)).ToString();
       
    }


    protected void txtUnitCost_TextChanged(object sender, EventArgs e)
    {
        int qty;
        decimal uc;
        decimal rate;

        int.TryParse(txtQuantity.Text, out qty);
        decimal.TryParse(txtUnitCost.Text, out uc);
        decimal.TryParse(txtVATRate.Text, out rate);
       
        txtNetTotal.Text = (qty * uc).ToString();
        txtVAT.Text = (rate * (qty * uc)).ToString();
        txtTotal.Text = ((rate * (qty * uc)) + (qty * uc)).ToString();

    }


    protected void txtVATRate_TextChanged(object sender, EventArgs e)
    {
        int qty;
        decimal uc;
        decimal rate;
        
        int.TryParse(txtQuantity.Text, out qty);
        decimal.TryParse(txtUnitCost.Text, out uc);
        decimal.TryParse(txtVATRate.Text, out rate);
       
        txtNetTotal.Text = (qty * uc).ToString();
        txtVAT.Text = (rate * (qty * uc)).ToString();
        txtTotal.Text = ((rate * (qty * uc)) + (qty * uc)).ToString();
      
    }

Open in new window

0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

forstersAuthor Commented:
Bit flummoxed with the Javascript, I realise I am now in the wrong zone for a JavaScript question but can anyone advise?

I am getting the following error:
Cannot assign to a function result

My code is :
<script type="text/javascript" language="javascript">
    function TryParseInt(str, defaultValue)
    {
        var retValue = defaultValue;
        if (str != null)
        {
            if (str.length > 0)
            {
                if (!isNaN(str))
                {
                    retValue = parseInt(str);
                }
            }
        } return retValue;
    }

    function TryParseDecimal(str, defaultValue) {
        var retValue = defaultValue;
        if (str != null) {
            if (str.length > 0) {
                if (!isNaN(str)) {
                    retValue = parseInt(str);
                }
            }
        } return retValue;
    }

function VATcalc()
    {
        var qty = document.getElementById('<%=txtQuantity.ClientID%>');
        var uc = document.getElementById('<%=txtUnitCost.ClientID%>');
        var rate = document.getElementById('<%=txtVATRate.ClientID%>');
        
        document.getElementById('<%=txtNetTotal.ClientID%>') = (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)) ;
        document.getElementById('<%=txtVAT.ClientID%>') = (TryParseDecimal(rate.value, 0) * (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)));
        document.getElementById('<%=txtTotal.ClientID%>') = ((TryParseDecimal(rate.value, 0) * (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0))) + (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)));
    }

</script>

Open in new window


And I am calling the function with :

onchange="VATcalc();" in each of the editable textboxes.
0
käµfm³d 👽Commented:
In lines 34 - 36, you are trying to assign the DOM element, not its value. Add ".value" to the end of each:

e.g.

document.getElementById('tb4').value = (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)) ;
document.getElementById('tb5').value = (TryParseDecimal(rate.value, 0) * (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)));
document.getElementById('tb6').value = ((TryParseDecimal(rate.value, 0) * (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0))) + (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)));

Open in new window

0
forstersAuthor Commented:
Ahh yes, thank you.

Ok cool so my textboxes are now auto-calculating except, for some reason it is ignoring the VATRate in all calculations...

I thought it might be because I had set the default value to 0 but having tried removing that and replacing it with 0.2 I'm no further forward.

I had set the txtVATRate textbox Text="0.2" but even if I amend the textbox on screen it doesn't feature in any of the calculations, I must have got something else wrong...can you see my error?

<script type="text/javascript" language="javascript">
    function TryParseInt(str, defaultValue)
    {
        var retValue = defaultValue;
        if (str != null)
        {
            if (str.length > 0)
            {
                if (!isNaN(str))
                {
                    retValue = parseInt(str);
                }
            }
        } return retValue;
    }

    function TryParseDecimal(str, defaultValue) {
        var retValue = defaultValue;
        if (str != null) {
            if (str.length > 0) {
                if (!isNaN(str)) {
                    retValue = parseInt(str);
                }
            }
        } return retValue;
    }

function VATcalc()
    {
        var qty = document.getElementById('<%=txtQuantity.ClientID%>');
        var uc = document.getElementById('<%=txtUnitCost.ClientID%>');
        var rate = document.getElementById('<%=txtVATRate.ClientID%>');
        
        document.getElementById('<%=txtNetTotal.ClientID%>').value = TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0);
    document.getElementById('<%=txtVAT.ClientID%>').value = (TryParseDecimal(rate.value, 0.2) * (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)));
        document.getElementById('<%=txtTotal.ClientID%>').value = ((TryParseDecimal(rate.value, 0.2) * (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0))) + (TryParseInt(qty.value, 0) * TryParseDecimal(uc.value, 0)));
    }

</script>

Open in new window


 <tr>
                                    <td>
                                        Quantity:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtQuantity" onchange="VATcalc();" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        Unit cost:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtUnitCost" onchange="VATcalc();" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        Net total:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtNetTotal" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        VAT Rate:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtVATRate" onchange="VATcalc();" runat="server"  Text="0.2" TextMode="SingleLine" ReadOnly="false" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        VAT:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtVAT" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        Total:
                                    </td>
                                    <td>
                                        <asp:TextBox ID="txtTotal" runat="server" Width="200px"></asp:TextBox><br />
                                        <br />
                                    </td>
                                </tr>

Open in new window

0
forstersAuthor Commented:
Oh I think this is a rounding thing, if I remove Text="0.2" and set the VATRate to 1 my VAT is populated, if I change it to any figure below 1 then my VAT returns to 0 and my Total is equal to my NET, how can I combat this?
0
käµfm³d 👽Commented:
I noticed earlier that your TryParseDecimal function is using parseInt internally. This doesn't sound right. I would have expected to see parseFloat.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
forstersAuthor Commented:
Ahhh yes I copied the TryParseInt probably forgot to change...that has resolved it.

Fantastic thank you for all your help
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.