Текстовое поле учитывается только для одной переменной вместо суммирования обеих

#vb.net

#vb.net

Вопрос:

Я создаю программу, которая вычисляет счет пользователя за электроэнергию. Однако есть проблема, мне удается вычислять их только по одному, но когда я пытаюсь их суммировать, это не сработало, отображается только общая сумма одной переменной вместо суммирования обеих.

Изображение

Вот код, это не полный код, так как он очень длинный, так как мне нужно рассчитать с марта по декабрь, поэтому я взял только март и апрель.

(Это для определения цены на основе использования)

Налог на обслуживание составляет 6%, я уже ввел его в переменную налога на обслуживание.

     Select Case True
        Case mar >= 1 To mar <= 200
            unitsConsumedMar = mar
            marTotalAmount = (unitsConsumedMar * 0.109)
            serviceTax = marTotalAmount * serviceTax
            marTotalAmount  = serviceTax
            TextBox16.Text = marTotalAmount.ToString("C2")


        Case apr >= 1 To apr <= 200
            unitsConsumedApr = apr
            aprTotalAmount = (unitsConsumedApr * 0.109)
            serviceTax = aprTotalAmount * serviceTax
            aprTotalAmount  = serviceTax
            TextBox16.Text = aprTotalAmount.ToString("C2")
        End Select

    Select Case True

        Case mar > "200" And mar <= "300"
            unitsConsumedMar = mar
            marTotalAmount = (unitsConsumedMar * 0.153)
            serviceTax = marTotalAmount * serviceTax
            marTotalAmount  = serviceTax
            TextBox16.Text = marTotalAmount.ToString("C2")


        Case apr > "200" And apr <= "300"
            unitsConsumedApr = apr
            aprTotalAmount = (unitsConsumedApr * 0.153)
            serviceTax = aprTotalAmount * serviceTax
            aprTotalAmount  = serviceTax
            TextBox16.Text = aprTotalAmount.ToString("C2")
        End Select

      totalBill = Val(marTotalAmount)   Val(aprTotalAmount)
      textbox20.Text = totalBill.ToString("C2")
  

Все это работает, если в марте 200, а в апреле 201, но тогда textbox16 возвращает какую-то странную сумму, похоже, что она суммирует как сумму за март, так и за апрель, вместо того, чтобы добавлять ее к textbox20.

Изображение

по какой-то причине, если я помещаю 200 в одно текстовое поле и 201 в другое, оно вычисляется правильно, поскольку 70.98 23.11 равно 94.09, но общая сумма за месяц не должна составлять 70.98, поскольку 23.11 32.60 даже близко не 70…

Комментарии:

1. Вам нужно отладить свой код, т. Е. Установить точку останова вверху, а затем пошагово просмотреть код построчно, проверяя состояние на каждом шаге. Вы знаете, что, как вы ожидаете, произойдет перед каждым шагом, и вы можете сравнить это с тем, что на самом деле происходит впоследствии. Как только они не совпадают, вы нашли свою проблему и можете исследовать ее конкретно, а не соглашаться на «по какой-то причине» . Даже если вы все еще не можете решить проблему, по крайней мере, вы можете предоставить нам всю необходимую информацию.

2. Вы имеете в виду, что за первые 200 единиц будет выставлен счет в размере $ 0,109, а за все, что превышает 200 единиц, будет выставлен счет в размере $ 0,153? Или все использование оплачивается по более высокой ставке, когда оно превышает 200 единиц?

3. правильно. но 1 единица = 0,109, а если оно превышает 200, то 1 единица = 0,153

Ответ №1:

Я бы предложил создать пользовательскую функцию для расчета ежемесячной суммы:

 Function GetMonthlyAmount(energyUsage As Double) As Double
    Dim discount As Double = 0.0
    Dim serviceTax As Double = 0.06
    Dim total As Double = 0.0
    
    Select Case energyUsage
        Case 1.0 To 200.00
            discount = 0.109
        Case 200.01 To 300.0
            discount = 0.153
        Case > 300.00
            discount = 0.169
        Case Else
            discount = 0.0100
    End Select
    
    total = energyUsage * discount
    total  = (total * serviceTax)
    
    Return total
End Function
  

Но приведенная выше функция возвращает только ежемесячную сумму. Насколько я вижу, вы хотите получить (и отобразить) другие значения, такие как: скидка, налог на обслуживание и т.д. Итак, я бы предложил создать пользовательский класс:

 Public Class BillOfEnergyUsage
    Private st As Double = 0.06
    Private eu As Double = 0.0
    Private di AS Double = 0.0
    Private dia AS Double = 0.0
    Private ta As Double = 0.0
    
    Public Sub New(energyUsage As Double)
        eu = energyUsage
        di = Discount
        dia = DiscountAmount
        ta = TotalAmount
    End Sub
    
    Public ReadOnly Property ServiceTax As Double
        Get 
            Return st
        End Get
    End Property
    
    Public Property EnergyUsage As Double
        Get 
            Return eu
        End Get
        Set (value As Double)
            eu = value
        End Set
    End Property
    
    Public ReadOnly Property Discount As Double
        Get 
            Select Case eu
                Case 1.0 To 200.00
                    di = 0.109
                Case 200.01 To 300.0
                    di = 0.153
                Case > 300.00
                    di = 0.169
                Case Else
                    di = 0.0
            End Select
            Return di
        End Get
    End Property

    Public ReadOnly Property DiscountAmount As Double
        Get 
            dia = eu * di
            Return dia
        End Get
    End Property

    Public ReadOnly Property TotalAmount As Double
        Get 
            ta = dia
            ta  = (ta * st)
            Return ta
        End Get
    End Property
    
    Public Overrides Function ToString() AS String
        Return $"Usage: {eu.ToString("C2")}, Service Tax: {st.ToString("P2")}, Discount: {di.ToString("P2")} - {dia.ToString("C2")}, Total: {ta.ToString("C2")}"
    End Function
    
End Class
  

Использование:

 Sub Main
    Dim usages As Double() = {120.00, 200.00, 252.00, 300.00, 305.00} 'you have to init your data from textboxes
    Dim beulist As List(Of BillOfEnergyUsage) = New List(Of BillOfEnergyUsage)
    
    For Each usage As Double In usages
        Dim beu As BillOfEnergyUsage = New BillOfEnergyUsage(usage)
        beulist.Add(beu)
        Console.WriteLine(beu.ToString())
    Next
    
    Dim totalAmount = beulist.Sum(Function(x) x.TotalAmount)
    Console.WriteLine($"Total amount: {totalAmount.ToString("C2")}")
End Sub
  

Результат:

 Usage: RM120.00, Service Tax: 6.00%, Discount: 10.90% - RM13.08, Total: RM13.86
Usage: RM200.00, Service Tax: 6.00%, Discount: 10.90% - RM21.80, Total: RM23.11
Usage: RM252.00, Service Tax: 6.00%, Discount: 15.30% - RM38.56, Total: RM40.87
Usage: RM300.00, Service Tax: 6.00%, Discount: 15.30% - RM45.90, Total: RM48.65
Usage: RM305.00, Service Tax: 6.00%, Discount: 16.90% - RM51.55, Total: RM54.64
Total amount: RM181.13
  

Обратите внимание, что вы можете получить любой счет из списка и получить доступ к его свойствам следующим образом:

 Dim bb As BillOfEnergyUsage = beulist(0) 'get first bill from list
Console.WriteLine("{0} | {1} | {2} | {3}", bb.EnergyUsage, bb.ServiceTax, bb.Discount, bb.TotalAmount)
  

Удачи!

Комментарии:

1. Проблема в том, что я считаю ежемесячно и с помощью кнопки. У меня есть только одно текстовое поле для хранения значения текущей переменной, которое является месячным итогом. Допустим, что март равен textbox5, а апрель равен textbox6, если я введу число в textbox5, оно вычислит все в месячную сумму, но когда я введу число в апрель, число будет складываться, и если я сделаю для любого из них значение только для чтения = true, то как я смогучтобы суммировать их…

2. Извините, я вас не понимаю… Количество текстовых полей, размещенных в форме, и их статус «включено» не важны! Я предполагаю, что вы не знаете, как перебирать коллекцию текстовых полей. Я прав?

Ответ №2:

Я создал класс для данных, связанных с энергетическим полем. Общие поля содержат значения, используемые во всех экземплярах класса. Эти значения устанавливаются в Form.Load методе путем вызова SetRates метода. Поскольку это общий метод, вам не нужно создавать экземпляр класса. Используется MonthNumber для упорядочения списка счетов за электроэнергию. Возможно, вам потребуется изменить CalculateGrossMonthlyBill метод, потому что я предполагал градуированную скорость. Этот ToString метод используется полем со списком для определения отображения.

В дизайне формы я назвал каждое из текстовых полей в группе MonthlyEnergyUse месяцем, который они представляют. Вероятно, вы хотите начать со .Text свойства 0. .Tag Свойство каждого месяца — это число, представляющее месяц. Март — 3, апрель — 4 и т.д. Это число будет использоваться для упорядочения списка.

В Form.Load Shared задаются ставки. Хотя я жестко запрограммировал значения, они могут быть извлечены из текстового файла или базы данных. Если их нужно изменить, вам не придется перекомпилировать программу.

После заполнения текстовых полей месяца нажимается кнопка 1. Сначала ввод пользователя проверяется с .TryParse помощью функции. Мы создаем список EnergyBill , затем перебираем каждое текстовое поле, вызывая конструктор of EnergyBill , передавая значения из свойств текстового поля. Конструктор устанавливает Read Only свойства класса. Затем это новое EnergyBill добавляется в список.

Далее список упорядочивается MonthNumber с помощью магии Linq. Затем оно привязывается к выпадающему списку (это заменяет текстовое поле, которое вы отметили Месяц в правой части вашей формы.

Общий итог вычисляется с использованием .Sum метода списка и отображается в текстовом поле.

Вы можете просмотреть данные за каждый месяц, выбрав месяц в поле со списком. Элементы выпадающего списка являются объектами, но базовый тип таков EnergyBill , что мы можем привести элемент и получить доступ ко всем свойствам.

 Public Class EnergyBill
    Private _MonthlyChargeWithTax As Decimal
    Private _DiscountAmount As Decimal
    Private _TotalAmount As Decimal
    Private Shared LowUsageRate As Decimal
    Private Shared HighUsageRate As Decimal
    Private Shared DiscountRate As Decimal
    Private Shared TaxRate As Decimal
    Public Property Month As String
    Public Property MonthNumber As Integer
    Public Property EnergyUsage As Double
    Public ReadOnly Property MonthChargeWithTax As Decimal
        Get
            Return _MonthlyChargeWithTax
        End Get
    End Property
    Public ReadOnly Property DiscountAmount As Decimal
        Get
            Return _DiscountAmount
        End Get
    End Property
    Public ReadOnly Property TotalAmount As Decimal
        Get
            Return _TotalAmount
        End Get
    End Property

    Public Sub New(BillingMonth As String, MonthNum As Integer, Usage As Integer)
        Month = BillingMonth
        EnergyUsage = Usage
        MonthNumber = MonthNum
        _MonthlyChargeWithTax = CalculateGrossMonthlyBill(Usage)
        _DiscountAmount = _MonthlyChargeWithTax * DiscountRate
        _TotalAmount = _MonthlyChargeWithTax - _DiscountAmount
    End Sub

    Private Function CalculateGrossMonthlyBill(usage As Integer) As Decimal
        Dim MonthCharge As Decimal
        Select Case usage
            Case <= 200
                MonthCharge = usage * LowUsageRate
            Case Else
                MonthCharge = 200 * LowUsageRate
                MonthCharge  = (usage - 200) * HighUsageRate
        End Select
        Return MonthCharge * 1.06D
    End Function

    Public Shared Sub SetRates(LowUsage As Decimal, HighUsage As Decimal, Discount As Decimal, Tax As Decimal)
        LowUsageRate = LowUsage
        HighUsageRate = HighUsage
        DiscountRate = Discount
        TaxRate = Tax
    End Sub

    Public Overrides Function ToString() As String
        Return Month
    End Function
End Class
  

Форма…

 Public Class UtilityBills

    Private Sub UtilityBills_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        EnergyBill.SetRates(0.109D, 0.153D, 0.5D, 0.06D)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not ValidateUsage() Then
            MessageBox.Show("All text boxes must have a valid number.")
            Exit Sub
        End If
        Dim lst As New List(Of EnergyBill)
        For Each tb In GroupBox1.Controls.OfType(Of TextBox)
            Dim eb As New EnergyBill(tb.Name, CInt(tb.Tag), CInt(tb.Text))
            lst.Add(eb)
        Next
        Dim orderedList = (lst.OrderBy(Function(eb) eb.MonthNumber)).ToList
        ComboBox1.DataSource = orderedList
        Dim TotalMonths = lst.Sum(Function(eb) eb.TotalAmount)
        TextBox5.Text = TotalMonths.ToString("C2")
    End Sub

    Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
        Dim eb = DirectCast(ComboBox1.SelectedItem, EnergyBill)
        TextBox1.Text = eb.MonthChargeWithTax.ToString("C2")
        TextBox2.Text = eb.DiscountAmount.ToString("C2")
        TextBox3.Text = eb.TotalAmount.ToString("C2")
    End Sub

    Private Function ValidateUsage() As Boolean
        Dim usage As Integer
        For Each tb In GroupBox1.Controls.OfType(Of TextBox)
            If Not Integer.TryParse(tb.Text, usage) Then
                Return False
            End If
        Next
        Return True
    End Function
End Class