Solved

Text Box Calculations - handling empty fields

Posted on 2013-11-12
9
393 Views
Last Modified: 2013-11-13
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
0
Comment
Question by:forsters
  • 6
  • 3
9 Comments
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
ID: 39642740
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
 

Author Comment

by:forsters
ID: 39644115
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
 

Author Comment

by:forsters
ID: 39644287
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
 

Author Comment

by:forsters
ID: 39644576
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39644642
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
 

Author Comment

by:forsters
ID: 39644674
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
 

Author Comment

by:forsters
ID: 39644701
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
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
ID: 39644826
I noticed earlier that your TryParseDecimal function is using parseInt internally. This doesn't sound right. I would have expected to see parseFloat.
0
 

Author Comment

by:forsters
ID: 39644877
Ahhh yes I copied the TryParseInt probably forgot to change...that has resolved it.

Fantastic thank you for all your help
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now