【问题标题】:VBA do loop issueVBA做循环问题
【发布时间】:2017-09-25 15:19:26
【问题描述】:

我正在努力完成一个学校项目。它使用用户表单并要求输入来创建三明治。我的问题是循环完成一次后,我无法让变量增加一。 每次用户输入一个子时,我希望用户表单返回为空,并将他们的选择输入到 Excel 表上。这就是我目前所拥有的

Private Sub btnAdd_Click()
Dim m As Integer

m = 1

    Do

        Select Case True

            Case optBreadRye.Value
                Range("C2").Offset(m, 0).Value = FormatCurrency(6)
                Range("D2").Offset(m, 0).Value = FormatCurrency(0)
                Range("E2").Offset(m, 0).Value = FormatCurrency(0)

            Case optBreadWheat.Value
                Range("D2").Offset(m, 0).Value = FormatCurrency(5)
                Range("C2").Offset(m, 0).Value = FormatCurrency(0)
                Range("E2").Offset(m, 0).Value = FormatCurrency(0)

            Case optBreadWhite.Value
               Range("E2").Offset(m, 0).Value = FormatCurrency(4)
               Range("C2").Offset(m, 0).Value = FormatCurrency(0)
               Range("D2").Offset(m, 0).Value = FormatCurrency(0)

        End Select

        If chkRoastBeef = True Then
             Range("F2").Offset(m, 0).Value = FormatCurrency(0.5)
                ElseIf chkRoastBeef = False Then
                    Range("F2").Offset(m, 0).Value = FormatCurrency(0)
        End If

        If chkChickenBreast = True Then
             Range("G2").Offset(m, 0).Value = FormatCurrency(0.5)
                ElseIf chkChickenBreast = False Then
                    Range("G2").Offset(m, 0).Value = FormatCurrency(0)
        End If

        If chkTurkeyBreast = True Then
             Range("H2").Offset(m, 0).Value = FormatCurrency(0.5)
                ElseIf chkTurkeyBreast = False Then
                    Range("h2").Offset(m, 0).Value = FormatCurrency(0)
        End If

        If chkHam = True Then
             Range("I2").Offset(m, 0).Value = FormatCurrency(0.5)
                ElseIf chkHam = False Then
                    Range("I2").Offset(m, 0).Value = FormatCurrency(0)
        End If

        If chkCheese = True Then
             Range("J2").Offset(m, 0).Value = FormatCurrency(0.5)
                ElseIf chkCheese = False Then
                    Range("j2").Offset(m, 0).Value = FormatCurrency(0)
        End If

        If chkVeggie = True Then
             Range("K2").Offset(m, 0).Value = FormatCurrency(0.5)
                ElseIf chkVeggie = False Then
                    Range("k2").Offset(m, 0).Value = FormatCurrency(0)
        End If

      Range("l2").Offset(m, 0).Value = lblPrice.Caption

    With frmOrder
        .chkCheese.Value = False
        .chkChickenBreast.Value = False
        .chkHam.Value = False
        .chkRoastBeef.Value = False
        .chkTurkeyBreast.Value = False
        .chkVeggie.Value = False
        .optBreadRye.Value = False
        .optBreadWheat.Value = False
        .optBreadWhite.Value = False
        .lblPrice.Caption = Format(0, "$0.00")

    End With


m = m + 1
Exit Do
Loop

End Sub

我知道这不是最好的格式或最有效的方法,但我的教授无论如何都不是帮助。我一直在通过我们的课本和谷歌学习一切。

我就是不能让 m 每次都加一。我认为这与“Exit Do”“Loop”或“m = m + 1”的位置有关

形式:

工作表:

【问题讨论】:

  • 我相信它会上升 1,但是在此之后退出,您的循环只运行 1 次?您是否在m = m + 1 之前收到错误,我会将 Exit Do 放在循环应该过早结束的地方,如果这有意义的话?
  • Rubberduck 可以帮助您处理缩进......和其他事情。 (免责声明:我管理那个 OSS 项目)
  • 我没有收到错误 - 第一次按“添加”可以正常工作。但是当我进入第二个时,它只是写在第一个之上 - 这就是我认为变量 m 没有上升的原因(因为如果理论上 Offset 会使它连续下降。)我有 Exit Do那里是因为我在没有无限循环时遇到了麻烦。谢谢你告诉我 Rubberduck 的事,我一定会去看看的。
  • 我尝试将变量 m 公开,但它没有改变。对不起,我忘了包括潜艇名称。它是在用户窗体中编写的,由附加到按钮顺序的主模块显示。
  • @alexredskisn96 感谢您的勾选 - 如果您对此有任何疑问,请务必询问:您完全了解正在发生的事情比 此程序 有效更重要。

标签: vba loops userform


【解决方案1】:

更新电子表格与表单无关。表单的工作是收集用户输入,句号。

你的循环没有退出条件,在第一次迭代结束时无条件退出:没用,删除它。

您需要一种方法让表单告诉其调用者“嘿,我有新数据给你”。最好的方法是通过一个事件:

Public Event NewOrderLine(ByVal bread As BreadType, ByVal contents As Stuffing)

...和枚举:

Public Enum BreadType
    BreadType_None
    BreadType_Rye
    BreadType_Wheat
    BreadType_White
End Enum

Public Enum Stuffing
    Stuffing_None = 0
    Stuffing_RoastBeef = 2 ^ 0
    Stuffing_ChickenBreast = 2 ^ 1
    Stuffing_TurkeyBreast = 2 ^ 2
    Stuffing_Ham = 2 ^ 3
    Stuffing_Cheese = 2 ^ 4
    Stuffing_Veggie = 2 ^ 5
End Enum

现在,当单击表单的 [添加] 按钮时,它会运行 引发事件 并将参数传递给调用者:

Private Sub AddButton_Click()

    Dim bread As BreadType
    bread = SelectedBreadType

    Dim contents As Stuffing
    contents = SelectedStuffings

    RaiseEvent NewOrderLine(bread, contents)
    ClearFormFields

End Sub

Private Property Get SelectedBreadType() As BreadType
    Select Case True
        Case optBreadRye.Value
            SelectedBreadType = BreadType_Rye
        Case optBreadWheat.Value
            SelectedBreadType = BreadType_Wheat
        Case optBreadWhite.Value
            SelectedBreadType = BreadType_White
        Case Else
            SelectedBreadType = BreadType_None
    End Select
End Property

Private Property Get SelectedStuffings() As Stuffing
    Dim result As Stuffing
    If chkRoastBeef.Value Then result = result + Stuffing_RoastBeef
    If chkChickenBreast.Value Then result = result + Stuffing_ChickenBreast
    If chkTurkeyBreast.Value Then result = result + Stuffing_TurkeyBreast
    If chkHam.Value Then result = result + Stuffing_Ham
    If chkCheese.Value Then result = result + Stuffing_Cheese
    If chkVeggie.Value Then result = result + Stuffing_Veggie
    SelectedStuffings = result
End Property

请注意,Stuffing 值是累积的;它们的基础值是 2 的幂。这被称为 flag enum,因为它像位掩码一样工作:您使用按位逻辑来确定值中是否包含“标志”:

Private Function HasFlag(ByVal value As Long, ByVal flag As Long) As Boolean
    HasFlag = (value And flag) = flag
End Function

所以回到工作表的代码隐藏,你可以这样做:

Option Explicit
Private WithEvents orderForm As frmOrder
Private currentOrderLine As Long

并处理NewOrderLine事件:

Private Sub orderForm_NewOrderLine(ByVal bread As BreadType, ByVal contents As Stuffing)
    'update the worksheet at currentOrderLine accordingly
End Sub

[Order] 按钮将负责分配 orderForm 对象引用:

Private Sub OrderButton_Click()
    Set orderForm = New frmOrder
    orderForm.Show
End Sub

我会制作一个专用于计算价格的标准程序模块:

Option Explicit

Public Function GetBreadPrice(ByVal bread As BreadType)
    'you figure that out
End Function

Public Function GetContentsPrice(ByVal contents As Stuffing)
    'you figure that out
End Function

然后表单可以调用这些函数来“预览”订单的价格,工作表可以调用这些函数来计算实际的总订单金额。假设模块名为Prices

Private Sub UpdatePriceLabel()
    breadPrice = Prices.GetBreadPrice(bread)
    contentsPrice = Prices.GetContentsPrice(contents)
    totalPrice = breadPrice + contentsPrice
    lblPrice.Caption = Format(totalPrice, "$0.00")
End Sub

【讨论】:

    猜你喜欢
    • 2013-12-10
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-29
    • 2014-08-15
    • 1970-01-01
    • 2011-09-21
    • 1970-01-01
    相关资源
    最近更新 更多