0

I am creating a program that calculates the monthly electricity bill based on usage. The codes are not neat and does not look very...concise, but it works. I tried using an array (have not learned that in my course yet) because when I searched around for answers, arrays will usually be the solution to it. However, when I use it in my code, it only calculates for the second statement, like if I have If...Else If, it'll only check for Else If and ignore the initial If.

I have created another project to resemble the problem. As you'll see below, the month is only until May, and I have to get it to October...

Option Strict On Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim marTA, aprTA, mayTA As Single Dim mar, apr, may As Decimal Decimal.TryParse(TextBox1.Text, mar) : Decimal.TryParse(TextBox2.Text, apr) Decimal.TryParse(TextBox3.Text, may) Select Case True Case mar = 0 marTA = 3D + (3D * 0.06) TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ") Case mar >= 1 And mar < 201 marTA = CSng(mar * 0.109) TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ") Case mar >= 201 And mar < 301 marTA = CSng((200 * 0.109) + ((mar - 200) * 0.153)) TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ") Case mar >= 301 And mar < 601 marTA = CSng((200 * 0.109) + (100 * 0.153) + ((mar - 300) * 0.172)) TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ") Case mar >= 601 And mar < 901 marTA = CSng((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + ((mar - 600) * 0.182)) TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ") Case mar >= 901 marTA = CSng((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + (300 * 0.182) + ((mar - 900) * 0.215)) TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ") End Select Select Case True Case apr = 0 aprTA = 3 + (3 * 0.06) TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ") Case apr >= 1 And apr < 201 aprTA = CSng(apr * 0.109) TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ") Case apr >= 201 And apr < 301 aprTA = CSng((200 * 0.109) + ((apr - 200) * 0.153)) TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ") Case apr >= 301 And apr < 601 aprTA = CSng((200 * 0.109) + (100 * 0.153) + ((apr - 300) * 0.172)) TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ") Case apr >= 601 And apr < 901 aprTA = CSng((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + ((apr - 600) * 0.182)) TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ") Case apr >= 901 aprTA = CSng((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + (300 * 0.182) + ((apr - 900) * 0.215)) TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ") End Select Select Case True Case may = 0 mayTA = 3 + (3 * 0.06) TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ") Case may >= 1 And may < 201 mayTA = CSng(may * 0.109) TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ") Case may >= 201 And may < 301 mayTA = CSng((200 * 0.109) + ((may - 200) * 0.153)) TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ") Case may >= 301 And may < 601 mayTA = CSng((200 * 0.109) + (100 * 0.153) + ((may - 300) * 0.172)) TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ") Case may >= 601 And may < 901 mayTA = CSng((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + ((may - 600) * 0.182)) TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ") Case may >= 901 mayTA = CSng((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + (300 * 0.182) + ((may - 900) * 0.215)) TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ") End Select End Sub End Class 

Design View:

Design View

1 Answer 1

1

There is an acronym in programming, DRY. It stands for Don't Repeat Yourself. A few reasons for this are...

  1. Easier to debug.
  2. Easier to change - just one spot instead of several.
  3. Easier to read and understand.
  4. Less error prone. If you try to write the same code several times you will make a mistake in the rewriting.

There are several ways to achieve DRY. One is to move repetative code to a separate function. See GetUsageCharge for a example of this.

Another way is to create a collection of like objects. Then use a loop to apply the repetitive code to each item in the collection. See TextBoxes and the For Each.

Private Function GetUsageCharge(usage As Integer) As Decimal Select Case usage Case 0 Return CDec(3 + (3 * 0.06)) Case 1 To 200 Return CDec(usage * 0.109) Case 201 To 300 Return CDec((200 * 0.109) + ((usage - 200) * 0.153)) Case 301 To 600 Return CDec((200 * 0.109) + (100 * 0.153) + ((usage - 300) * 0.172)) Case 601 To 900 Return CDec((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + ((usage - 600) * 0.182)) Case >= 901 Return CDec((200 * 0.109) + (100 * 0.153) + (300 * 0.172) + (300 * 0.182) + ((usage - 900) * 0.215)) End Select Return 0 End Function Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim TotalCost As Decimal Dim usage As Integer Dim TextBoxes As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3} For Each tb In TextBoxes If Integer.TryParse(tb.Text, usage) Then TotalCost += GetUsageCharge(usage) End If Next TextBox4.Text = TotalCost.ToString("C2").Replace("$", "RM ") End Sub 

As you can see this code is much simpler, fewer variables etc.

Note: You can get rid of .Replace("$", "RM ") if you add...

CultureInfo.DefaultThreadCurrentCulture = New CultureInfo("ms-MY") 

in the Form.Load

Sign up to request clarification or add additional context in comments.

3 Comments

This works wonder! However, there's a bug - the amount of total cost will increase continuously if the user keeps clicking on the button, hence the my messy codes. It's also why I separate them to avoid this issue, but that's for another question and this can be sorted out. Thank you @Mary
TotalCost is a local variable that start as 0 each time the button is clicked.
Oh my god, I am dumb..I declare it as Public because I have another groupbox to sum the total cost for each month, and also to add them into a ListBox to print a receipt. I am sorry, my fault.