2015-08-19 4 views
0

Если я повторяю k = 1 до 100, мне нужно перезапустить итерацию, если критерии не выполняются. В этом случае я создаю случайное число от 1 до 100, но если это число меньше 51, я хочу, чтобы итерация начала.VBA for loop end early

В настоящий момент код возвращает переменное количество значений. Иногда 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 
+0

Это довольно простой программный поток. Что вы пытались отладить программу? – moffeltje

+0

Я сделал k общедоступной переменной, и по какой-то причине по-прежнему получаю ту же проблему. – Fubudis

ответ

4

к считается локальной переменной для обоих сабвуферов в вашем примере, так что вы не обновляя K, как вы думаете ты. Либо увеличьте масштаб k (что я не рекомендую), либо сделайте ExampelExtended() функцию, которая возвращает что-то, что вы можете использовать в вызывающем суб.

Это один из способов. Очевидно, что функция является своего рода излишним, но пытается показать, как вы можете использовать функцию возвращать значение вызывающей подпрограмме:

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 
+0

Мой пример не самый лучший, но мне нужно, чтобы рандомизация составляла от 1 до 100, но проверила отметку между 51 и 100.Я не могу просто randbetween 50,100 – Fubudis

+0

@Fubudis не уверен, что мое редактирование - это то, что вы после ... но это будет печатать 100 номеров, каждая по 50. – sous2817

+0

Обнаружена проблема: Мой код фактически перебирался через 100 000 раз, как я этого хотел, но debug.print говорил только 34464, потому что я пытался использовать функцию count в массиве. По-видимому, есть ограничение на 65 тысяч. – Fubudis

0

Вы можете использовать Гото:

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 

посмотреть, если он работает

+0

Этот код вызовет бесконечный цикл, для определенного –

+0

Я бы не использовал 'GoTo', он, как правило, нахмурился, если это абсолютно необходимо. В этом случае решения легко выполняются без 'GoTo'. – BruceWayne

+0

Согласен, просто подумал, что это простой макрос с простым решением. – MVAmorim

2

Похоже, что это было бы лучше, если использовать цикл Do While. Do While делает indefinate петли, пока условие не будет выполнено - в данном случае, пока случайное число не является> 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) 
1

Ваш цикл имеет, по меньшей мере, 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 

Количество времени цикла выполняется будет таким же, как количество линий у вас на консоли

+0

Спасибо, это то, что я искал. У меня все еще есть проблемы с моим фактическим кодом, хотя, несмотря на использование этого метода. Я повторяю 100 000 раз, но я последовательно получаю 34 464 выхода. Возможно, это проблема памяти? – Fubudis

+0

@Fubudis - Попробуйте изменить 'Val как целое 'на' Val as Long'. ... Edit: Err, может быть, не 'Val', но я уверен, что ваша проблема связана с использованием' Integer', [«Целочисленная переменная не хранит дробные значения, содержит целые числа от -32,768 до 32,767 ...» ] (http://spreadsheetsuperstar.com/vba-integer-variable-data-type/) – BruceWayne