Почему мой l oop не проходит через все значения? - PullRequest
2 голосов
/ 05 августа 2020

Я пытаюсь заставить работать макрос 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

Я ожидаю увидеть напечатанный case 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 шаг), и для toto это сработало, но для foo и bar они были «лишними» l oop.

Я попытался изменить код для подхода, основанного на времени, но безуспешно.

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

Ответы [ 2 ]

4 голосов
/ 05 августа 2020

Это связано с ошибкой с плавающей запятой. Я бы избегал использования Step 0.2 и вместо этого умножал foo, bar и toto на 0.2 внутри l oop, используя только целые числа при цикле:

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 как Double. foo и bar - это Variant s.

0 голосов
/ 05 августа 2020

Вы неправильно указали свои переменные. В каждом объявлении необходимо указать As. То, как вы это сделали, делает foo и bar типа 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
...