【问题标题】:VBA for loop ending earlyVBA for 循环提前结束
【发布时间】:2015-08-19 18:07:26
【问题描述】:

如果我将 k = 1 迭代到 100,有时如果不满足条件,我需要重新启动迭代。在本例中,我创建了一个介于 1 和 100 之间的随机数,但如果该数字低于 51,我希望重新开始迭代。

现在代码正在返回可变数量的值。有时是 1,有时是 90。

有什么想法吗?

Public k as long
Sub Example()

For k = 1 To 100
    Call ExampleExtended
Next k

End Sub


Sub ExampleExtended()
Dim Val As Integer

Val = Int((100 - 1 + 1) * Rnd)

If Val < 51 Then
    k = k - 1
    Exit Sub
End If

Debug.Print Val

End Sub

【问题讨论】:

  • 这是一个相当简单的程序流程。你尝试调试什么程序?
  • 我将 k 设为公共变量,但由于某种原因我仍然遇到同样的问题。

标签: vba excel loops for-loop


【解决方案1】:

k 在您的示例中被视为两个 subs 的局部变量,因此您不会像您认为的那样更新 k 。要么增加 k 的范围(我不建议这样做),要么使 ExampleExtended() 成为一个函数,该函数返回您可以在调用 sub 中使用的内容。

这是一种方法。显然该函数有点矫枉过正,但试图展示如何使用函数将值返回给调用子:

    Sub Example()
    Dim counter     As Integer, _
        randNumber   As Integer

    For counter = 1 To 100

        randNumber = RandomBetween(50, 100)
        Debug.Print randNumber

    Next counter

    End Sub


    Function RandomBetween(lowerBound As Integer, upperBound As Integer) As Integer
        RandomBetween = Application.WorksheetFunction.RandBetween(lowerBound, upperBound)
    End Function

这更近了吗?

Option Explicit

Sub Example()
Dim counter     As Integer, _
    randNumber   As Integer

For counter = 1 To 100

    randNumber = RandomBetween(1, 100)


    If randNumber < 50 Then
        counter = counter - 1
    Else ' this is here just as a check...should only print 100 numbers
        Debug.Print randNumber
    End If

Next counter

End Sub

【讨论】:

  • 我的例子不是最好的,但我需要将随机化设置在 1 到 100 之间,但要在 51 到 100 之间进行检查。我不能只在 50,100 之间进行随机化
  • @Fubudis 不确定我的编辑是否是您所追求的……但这将打印 100 个数字,每个数字超过 50 个。
  • 发现了问题:我的代码实际上像我想要的那样循环了 100,000 次,但 debug.print 只说 34464 因为我试图在数组上使用计数函数。显然这些有 65K 的限制。
【解决方案2】:

看起来这更适合使用 Do While 循环。 Do While 使循环不确定,直到满足条件 - 在这种情况下,直到随机数 > 51。像这样:

val = 1
Do While val < 51
    Val = Int((100 - 1 + 1) * Rnd)
Loop

尽管在您的情况下,这可以通过将随机数强制在 51 和 100 之间来进一步简化,就像这样 [取自这里:http://www.cpearson.com/excel/randomNumbers.aspx

Dim Low As Double
Dim High As Double
Low = 51 '<<< CHANGE AS DESIRED
High = 100 '<<< CHANGE AS DESIRED
val = Int((High - Low + 1) * Rnd() + Low)

【讨论】:

    【解决方案3】:

    您的循环至少有 100 次迭代,平均有 150 次迭代!

    但是,Debug.Print Val 平均被调用 50 次。 因此,您几乎总是会在控制台窗口中看到少于 100 个的值。

    2^(-100) 有可能在控制台窗口中看到 100 行)

    如果您将代码更改为:

    Public k as long
    Sub Example()
    
    For k = 1 To 100
        Call ExampleExtended
    Next k
    
    End Sub
    
    
    Sub ExampleExtended()
    Dim Val As Integer
    
    Val = Int((100 - 1 + 1) * Rnd)
    
    Debug.Print Val
    
    If Val < 51 Then
        k = k - 1
        Exit Sub
    End If
    
    End Sub
    

    循环执行的时间与控制台中的行数相同

    【讨论】:

    【解决方案4】:

    你可以使用goto:

    Sub Example()
    
    For k = 1 To 100
    
    Call ExampleExtended
    
    Next k
    
    End Sub
    
    
    Sub ExampleExtended()
    Dim Val As Integer
    start:
    Val = Int((100 - 1 + 1) * Rnd)
    
    If Val < 51 Then
    goto start
    k = k - 1
    Exit Sub
    End If
    
    Debug.Print Val
    
    End Sub
    

    看看有没有效果

    【讨论】:

    • 这段代码肯定会导致无限循环
    • 我不会使用GoTo,除非绝对必要,否则它通常不受欢迎。在这种情况下,没有GoTo 也可以轻松完成解决方案。
    • 我同意,只是认为这将是一个简单的宏和一个简单的解决方案。
    • @UriGoren 不,它不会,只是显示高于 51 的数字
    猜你喜欢
    • 2023-03-22
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多