Link to home
Start Free TrialLog in
Avatar of forsters
forstersFlag for United Kingdom of Great Britain and Northern Ireland

asked on

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
SOLUTION
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of forsters

ASKER

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!
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

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.
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

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

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?
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ahhh yes I copied the TryParseInt probably forgot to change...that has resolved it.

Fantastic thank you for all your help