Как остановить выполнение кода VBA? - PullRequest
14 голосов
/ 20 октября 2010

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

Private Sub CommandButton1_Click()
    SomeVBASub
End Sub

Private Sub SomeVBASub
    DoStuff
    DoAnotherStuff
    AndFinallyDothis
End Sub

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

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

Спасибо.

Ответы [ 7 ]

20 голосов
/ 20 октября 2010

Добавьте еще одну кнопку с именем «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
9 голосов
/ 20 октября 2010

Как насчет 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 голосов
/ 25 марта 2014

Или, если вы хотите избегать использования глобальной переменной , вы можете использовать редко используемое свойство .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 голосов
/ 19 июня 2019

Это старая запись, но, учитывая заголовок этого вопроса, опция END должна быть описана более подробно.Это можно использовать для остановки ВСЕ ПРОЦЕДУРЫ (не только для запуска подпрограммы).Его также можно использовать в функции для остановки других подпрограмм (что я считаю полезным для некоторых надстроек, с которыми я работаю).

Как заявляет Microsoft :

Прекращает выполнение немедленно.Сам по себе никогда не требуется, но может быть помещен в любое место процедуры для завершения выполнения кода, закрытия файлов, открытых с помощью оператора Open, и очистки переменных *.Я заметил, что метод END не описан в деталях.Это можно использовать для остановки ВСЕХ ПРОЦЕДУР (не только запуска подпрограммы).

Вот иллюстративный пример:

Sub RunSomeMacros()

    Call FirstPart
    Call SecondPart

    'the below code will not be executed if user clicks yes during SecondPart.
    Call ThirdPart
    MsgBox "All of the macros have been run."

End Sub

Private Sub FirstPart()
    MsgBox "This is the first macro"

End Sub

Private Sub SecondPart()
    Dim answer As Long
    answer = MsgBox("Do you want to stop the macros?", vbYesNo)

    If answer = vbYes Then
        'Stops All macros!
        End
    End If

    MsgBox "You clicked ""NO"" so the macros are still rolling..."
End Sub

Private Sub ThirdPart()
    MsgBox "Final Macro was run."
End Sub
0 голосов
/ 01 апреля 2015

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

Private Sub CommandButton1_Click()

DoCmd.Close acForm, Me.Name
End

End Sub
0 голосов
/ 16 июля 2014

Я много этим занимаюсь. Много. : -)

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

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

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

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

K

0 голосов
/ 20 октября 2010

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

Private Sub SomeVBASub
    Cancel=False
    DoStuff
    If not Cancel Then DoAnotherStuff
    If not Cancel Then AndFinallyDothis
End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...