2010-10-20 4 views
13

Скажем, у меня есть кнопка, встроенная в мою электронную таблицу, которая запускает некоторую функцию VBA.Как остановить код VBA?

Private Sub CommandButton1_Click() 
    SomeVBASub 
End Sub 

Private Sub SomeVBASub 
    DoStuff 
    DoAnotherStuff 
    AndFinallyDothis 
End Sub 

Я хотел бы иметь возможность иметь какую-то кнопку «отмена», что бы остановить SomeVBASub выполнение в произвольный момент, и я не в с участием Ctrl+Break здесь, потому что я бы как сделать это тихо.

Я предполагаю, что это должна быть довольно распространенная проблема, любые идеи?

Спасибо.

ответ

18

Добавить еще одну кнопку под названием «CancelButton», которая устанавливает флаг, а затем проверяет этот флаг.

Если у вас длинные петли в «материале», проверьте и там, и выйдите, если он установлен. Используйте DoEvents внутри длинных циклов, чтобы убедиться, что пользовательский интерфейс работает.

Bool Cancel 
Private Sub CancelButton_OnClick() 
    Cancel=True 
End Sub 
... 
Private Sub SomeVBASub 
    Cancel=False 
    DoStuff 
    If Cancel Then Exit Sub 
    DoAnotherStuff 
    If Cancel Then Exit Sub 
    AndFinallyDothis 
End Sub 
+2

у меня была идея реализовать такую ​​логику, но это совсем смущает меня поставить 'DoEvents-Check flag' в КАЖДОЙ точке выхода возможной процедуры (буквально после каждой строки). –

+2

Описанный ниже метод @Faheemitian позволяет избежать этого, но это работает почти так же, как Ctrl + Break. Это зависит от того, какой контроль вы хотите использовать над пользовательским интерфейсом (например,кнопку) и где вы можете позволить вашему коду выйти. Если пользовательский интерфейс не имеет значения, и выходы кода могут быть произвольными (например, никаких проблем с зависимостями, откатами и т. Д.), Это было бы проще всего. Обычно добавление ловушек для флага отмены не является слишком обременительным, поскольку большая часть времени выполнения будет потрачена на циклы, но, возможно, это не так в вашей ситуации. –

+2

Позвольте мне также добавить, что если вы беспокоитесь о том, что процедура не прекращается немедленно, когда они нажимают «отменить» (отсюда нужно добавить столько проверок), то, что я обычно делаю, это отключить кнопку «Отмена» и изменить текст на «Подождите ...» или что-то в процедуре Click, поэтому пользователь знает, что приложение действительно рассматривает их запрос. –

0

, что jamietre сказал, но

Private Sub SomeVBASub 
    Cancel=False 
    DoStuff 
    If not Cancel Then DoAnotherStuff 
    If not Cancel Then AndFinallyDothis 
End Sub 
9

Как насчет Application.EnableCancelKey - С помощью кнопки Esc

On Error GoTo handleCancel 
Application.EnableCancelKey = xlErrorHandler 
MsgBox "This may take a long time: press ESC to cancel" 
For x = 1 To 1000000 ' Do something 1,000,000 times (long!) 
    ' do something here 
Next x 

handleCancel: 
If Err = 18 Then 
    MsgBox "You cancelled" 
End If 

сниппет из http://msdn.microsoft.com/en-us/library/aa214566(office.11).aspx

2

Или, если вы хотите избегайте использования использования глобальная переменная можно использовать редко используется .Tag свойства пользовательской формы:

Private Sub CommandButton1_Click() 
    Me.CommandButton1.Enabled = False 'Disabling button so user cannot push it 
             'multiple times 
    Me.CommandButton1.caption = "Wait..." 'Jamie's suggestion 
    Me.Tag = "Cancel" 
End Sub 

Private Sub SomeVBASub 
    If LCase(UserForm1.Tag) = "cancel" Then 
     GoTo StopProcess 
    Else 
     'DoStuff 
    End If 

Exit Sub 
StopProcess: 
    'Here you can do some steps to be able to cancel process adequately 
    'i.e. setting collections to "Nothing" deleting some files... 
End Sub 
0

Я делаю это много. Много. :-)

Я привык использовать «DoEvents» чаще, но все же стараюсь, чтобы все работало, даже не проверяя верный метод остановки.

Затем, сегодня, повторив это, я подумал: «Ну, просто подождите, когда закончится через 3 часа», и начал грести в ленте. Раньше я заметил в разделе «Вид» ленту «Макросы», и я подумал, что я вижу, могу ли я видеть, что мой бесконечный макрос работает ...

Теперь я понимаю, что вы можете также получите это, используя Alt-F8.

Тогда я подумал, ну а что, если я «сделаю шаг» в другом Макро, это меня спасет? Он сделал :-) Он также работает, если вы переходите в свой бегущий макрос (но вы все равно теряете, где находитесь вверх), если вы не ленивый программист вроде меня и не объявляете множество «глобальных» переменных, и в этом случае Глобальные данные сохраняются :-)

K

0

~ для тех, кто использует пользовательские поле ввода

Private Sub CommandButton1_Click() 

DoCmd.Close acForm, Me.Name 
End 

End Sub 
Смежные вопросы