VB.NET如何循环文本框实现多订单录入并自动累加应付金额?
VB.NET 同一客户多订单录入与金额累加实现方案
核心解决思路
- 自定义类封装订单数据:将每笔订单的饮品、数量、金额等信息统一封装,便于存储和计算
- List集合管理多笔订单:在窗体级别声明
List(Of OrderItem)存储同一客户的所有订单,规避循环文本框的繁琐操作 - 实时计算累计金额:每次添加订单后,遍历集合汇总所有订单金额(注意配送费仅收取一次)
具体实现步骤
1. 定义订单数据类
在窗体代码的最上方(类外部)添加以下代码,用于封装单条订单的核心信息:
Public Class OrderItem Public Property DrinkName As String Public Property Quantity As Integer Public Property SizeName As String Public Property SizePrice As Double Public Property AddOns As String Public Property AddOnsTotal As Double Public Property FinalPricePerItem As Double Public Property SubTotal As Double ' 单订单小计(不含配送费) End Class
2. 声明窗体级别变量
在窗体类内部添加变量,用于存储订单集合和累计金额:
Private customerOrders As New List(Of OrderItem)() Private totalDeliveryFee As Double = 0 ' 配送费仅首次添加订单时设置 Private totalPayable As Double = 0
3. 修改添加订单按钮事件
替换原有的BtnAddOrder_Click代码,实现多订单添加、详情累加和金额计算:
Private Sub BtnAddOrder_Click(sender As Object, e As EventArgs) Handles BtnAddOrder.Click ' 必填字段校验 If String.IsNullOrEmpty(TxtCustomername.Text) OrElse String.IsNullOrEmpty(TxtPhone.Text) OrElse TxtPhone.Text = "Invalid! Phone Number" OrElse String.IsNullOrEmpty(TxtDiscount.Text) OrElse String.IsNullOrEmpty(TxtDeliveryFee.Text) OrElse String.IsNullOrEmpty(CboDrink.Text) OrElse String.IsNullOrEmpty(CboQuantity.Text) OrElse String.IsNullOrEmpty(TxtSizeprice.Text) Then MessageBox.Show("请填写必填字段!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error) Return End If Try ' 处理附加配料 Dim addOnsList As New List(Of String)() If ChkBoxBlackPearl.Checked Then addOnsList.Add("Black Pearl") If ChkBoxOreo.Checked Then addOnsList.Add("Oreo") If ChkBoxNata.Checked Then addOnsList.Add("Nata De Coco") If ChkBoxCoffeeJelly.Checked Then addOnsList.Add("Coffee Jelly") If ChkboxCreamCheese.Checked Then addOnsList.Add("CreamCheese") Dim addOnsText As String = If(addOnsList.Count > 0, String.Join(", ", addOnsList), "无") ' 处理支付方式 Dim paymentText As String = "" If RbtnGcash.Checked Then paymentText = "Gcash" If RbtnDebit.Checked Then paymentText = "Debit Card" If RbtnCoins.Checked Then paymentText = "Coins.ph" If RbtnCash.Checked Then paymentText = "Cash" ' 处理折扣率 Dim discountRate As Double = 0 If RbtnPWD.Checked Then discountRate = 0.05 If RbtnSenior.Checked Then discountRate = 0.1 If RbtnStudent.Checked Then discountRate = 0.03 ' 数值类型转换(用TryParse避免格式错误) Dim quantity As Integer Dim sizePrice As Double Dim addOnsTotal As Double Dim deliveryFee As Double If Not Integer.TryParse(CboQuantity.Text, quantity) OrElse Not Double.TryParse(TxtSizeprice.Text, sizePrice) OrElse Not Double.TryParse(TxtTotalAddOn.Text, addOnsTotal) OrElse Not Double.TryParse(TxtDeliveryFee.Text, deliveryFee) Then MessageBox.Show("数值格式错误!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error) Return End If ' 计算单订单金额 Dim totalPreDelivery As Double = addOnsTotal + sizePrice Dim discountPrice As Double = totalPreDelivery * discountRate Dim finalPricePerItem As Double = totalPreDelivery - discountPrice Dim subTotal As Double = finalPricePerItem * quantity ' 初始化配送费(仅首次添加订单时设置) If customerOrders.Count = 0 Then totalDeliveryFee = deliveryFee End If ' 创建订单对象并加入集合 Dim newOrder As New OrderItem() With { .DrinkName = CboDrink.Text, .Quantity = quantity, .SizeName = Sizename, .SizePrice = sizePrice, .AddOns = addOnsText, .AddOnsTotal = addOnsTotal, .FinalPricePerItem = finalPricePerItem, .SubTotal = subTotal } customerOrders.Add(newOrder) ' 计算总应付金额 totalPayable = customerOrders.Sum(Function(o) o.SubTotal) + totalDeliveryFee ' 更新订单详情文本框 UpdateOrderDetails() ' 更新应付金额显示 TxtAmountPayable.Text = $"Php {totalPayable.ToString("N2")}" ' 清空当前订单输入控件,方便添加下一笔 ClearOrderInputs() Catch ex As Exception MessageBox.Show($"添加订单失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub ' 更新订单详情的辅助方法 Private Sub UpdateOrderDetails() Dim sb As New StringBuilder() ' 客户信息(仅显示一次) sb.AppendLine($"客户姓名:{TxtCustomername.Text}") sb.AppendLine($"联系电话:{TxtPhone.Text}") sb.AppendLine($"地址:{If(String.IsNullOrEmpty(TxtAddress.Text), "无", TxtAddress.Text)}") sb.AppendLine("***********************************************************") ' 遍历所有订单添加详情 For i As Integer = 0 To customerOrders.Count - 1 Dim order = customerOrders(i) sb.AppendLine($"订单 {i + 1}:") sb.AppendLine($" 饮品:{order.DrinkName}") sb.AppendLine($" 数量:{order.Quantity}") sb.AppendLine($" 规格:{order.SizeName}") sb.AppendLine($" 规格单价:Php {order.SizePrice.ToString("N2")}") sb.AppendLine($" 附加配料:{order.AddOns}") sb.AppendLine($" 配料总价:Php {order.AddOnsTotal.ToString("N2")}") sb.AppendLine($" 单杯实价:Php {order.FinalPricePerItem.ToString("N2")}") sb.AppendLine($" 订单小计:Php {order.SubTotal.ToString("N2")}") sb.AppendLine("-----------------------------------------------------------") Next ' 汇总信息 sb.AppendLine($"配送费:Php {totalDeliveryFee.ToString("N2")}") sb.AppendLine($"支付方式:{GetPaymentText()}") sb.AppendLine($"折扣率:{TxtDiscount.Text}") sb.AppendLine("***********************************************************") sb.AppendLine(" 感谢您的订单") sb.AppendLine("***********************************************************") sb.AppendLine($"交易日期:{DateTimePicker1.Text}") TxtOrderDetails.Text = sb.ToString() End Sub ' 获取支付方式文本的辅助方法 Private Function GetPaymentText() As String If RbtnGcash.Checked Then Return "Gcash" If RbtnDebit.Checked Then Return "Debit Card" If RbtnCoins.Checked Then Return "Coins.ph" If RbtnCash.Checked Then Return "Cash" Return "未选择" End Function ' 清空订单输入控件的辅助方法 Private Sub ClearOrderInputs() CboDrink.SelectedIndex = -1 CboQuantity.SelectedIndex = -1 TxtSizeprice.Text = "" ' 清空配料复选框 ChkBoxBlackPearl.Checked = False ChkBoxOreo.Checked = False ChkBoxNata.Checked = False ChkBoxCoffeeJelly.Checked = False ChkboxCreamCheese.Checked = False TxtTotalAddOn.Text = "" ' 折扣单选框保持不变(同一客户折扣通常一致) End Sub
关键优化说明
- 规避控件循环:用
List(Of OrderItem)存储订单数据,无需遍历控件读取信息,代码更易维护 - 准确金额累加:通过
Sum方法汇总所有订单小计,加上仅收取一次的配送费,避免重复计费 - 输入安全:用
TryParse替代Val,防止非法数值导致程序崩溃 - 用户体验:添加输入控件清空逻辑,支持连续添加多笔订单
内容的提问来源于stack exchange,提问作者Johane Grei Dingding
相关产品推荐
相关产品推荐

