【问题标题】:Why is my loop not going through all values?为什么我的循环没有遍历所有值?
【发布时间】:2020-11-25 20:35:48
【问题描述】:

我正在尝试让 Excel vba 宏工作。我使用的代码如下:


Dim foo, bar, toto As Double
Dim nb As Integer
nb = 1

For bar = 1 To 1 Step 0.2
For toto = 1 To 4 Step 0.2
For foo = 1 To 2 Step 0.2
    Cells(nb, 1).Value = CStr("bar " & bar & " toto " & toto & " foo " & foo)
    nb = nb + 1
Next foo
Next toto
Next bar
End Sub

我希望看到 toto=4 的案例被打印出来。我得到的最终结果是:

bar 1 toto 1 foo 1
bar 1 toto 1 foo 1.2
bar 1 toto 1 foo 1.4
[....]
bar 1 toto 3.8 foo 1.6
bar 1 toto 3.8 foo 1.8
bar 1 toto 3.8 foo 2

变量 foo 按预期从 1 变为 2,并且每次递增 0.2。 另一方面,变量 toto 从 1 变为 3.8,而不是上升到 4。

如何更改我的代码以使 toto 达到 4 ? 我尝试将我的 for 循环的上限值更改为 (max + 1 step),并且 for toto 它工作但对于 foo 和 bar 它们是一个“额外”循环。

我尝试将代码更改为基于一段时间的方法,但也没有成功。

bar = 1
toto = 1
foo = 1
nb = 1

While (bar <= 1)
toto = 1
    While (toto <= 4)
    foo = 1
        While (foo <= 2)
        
        Cells(nb, 4).Value = CStr("bar " & bar & " toto " & toto & " foo " & foo)
        nb = nb + 1
        foo = foo + 0.2
        Wend
    toto = toto + 0.2
    Wend
bar = bar + 0.2
Wend

【问题讨论】:

标签: excel vba for-loop


【解决方案1】:

这是由于浮点错误。我会避免使用Step 0.2,而是在循环内将foobartoto 乘以0.2,同时在循环时只使用整数:

Dim foo As Long, bar As Long, toto As Long, nb As Long

nb = 1

For bar = 1 To 5
    For toto = 1 To 20
        For foo = 1 To 10
            Cells(nb, 1).Value = CStr("bar " & bar * 0.2 & " toto " & toto * 0.2 & " foo " & foo * 0.2)
            nb = nb + 1
        Next
    Next
Next

另请注意,在 中,Dim foo, bar, toto As Double 仅将toto 声明为DoublefoobarVariants。

【讨论】:

  • 看来确实是浮点错误。我尝试在每个 for 循环的上限中添加一个小值(1E-7),并且进展顺利。我会等待其他答案,但我想我明天可以接受你的答案。
【解决方案2】:

您错误地声明了变量。您需要在每个声明中添加 As 声明。你这样做的方式使foobar 的类型为Variant,这可能是VBA 当时想要的任何东西。最好每行有一个声明。如果我们让鞋面稍微大于 4,比如 4.01,那么它就可以工作。我不知道为什么。

Dim foo As Double
Dim bar As Double 
Dim toto As Double
Dim nb As Integer
nb = 1

For bar = 1 To 1 Step 0.2
    For toto = 1 To 4.01 Step 0.2
        For foo = 1 To 2 Step 0.2
            Cells(nb, 1).Value = CStr("bar " & bar & " toto " & toto & " foo " & foo)
            nb = nb + 1
        Next foo
    Next toto
Next bar

如果您不喜欢在toto 的上限上添加一些斜率,您也可以使用Round 强制有效数字。

这个按你预期的方式工作:

Sub test()
    Dim foo As Single
    Dim bar As Single
    Dim toto As Single
    Dim nb As Integer
    nb = 1
    
    For bar = 1 To 1 Step 0.2
        For toto = 1 To 4 Step 0.2
            toto = Round(toto, 1)
            For foo = 1 To 2 Step 0.2
                Debug.Print CStr("bar " & bar & " toto " & toto & " foo " & foo)
                nb = nb + 1
            Next foo
        Next toto
    Next bar
End Sub

【讨论】:

  • 答案是浮点错误。我们不能保证步进 0.2 会让我们精确到 4。
  • 更改为数据类型Single 我看到了错误。它报告这个:bar 1 toto 3.800001 foo 1.8 这使它溢出 4 到 4.00000001 并结束。
  • 这也可以用Round 修复。当数学是计算机擅长的一件事时,这似乎很奇怪。为什么VBA会这么马虎?
  • 我根本不会称这为“草率”。
  • 浮点错误比 VBA 更广泛。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 2017-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多