Как остановить код VBA?
Скажем, у меня есть кнопка, встроенная в мою электронную таблицу, которая запускает некоторую функцию VBA.
Private Sub CommandButton1_Click()
SomeVBASub
End Sub
Private Sub SomeVBASub
DoStuff
DoAnotherStuff
AndFinallyDothis
End Sub
Мне бы хотелось иметь какую-то кнопку "отменить", которая остановит выполнение SomeVBASub
в любой момент, и я не буду включать Ctrl+Break
здесь, потому что я бы как сделать это тихо.
Я предполагаю, что это должна быть довольно распространенная проблема, любые идеи?
Спасибо.
Ответы
Ответ 1
Добавьте еще одну кнопку под названием "CancelButton", которая устанавливает флаг, а затем проверяет этот флаг.
Если у вас есть длинные петли в "stuff", тогда проверьте его там и выйдите, если он установлен. Используйте 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
Как насчет 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
Ответ 3
Или, если вы хотите избежать использования глобальной переменной , вы можете использовать редко используемое свойство .Tag
пользовательской формы:
Private Sub CommandButton1_Click()
Me.CommandButton1.Enabled = False 'Disabling button so user cannot push it
'multiple times
Me.CommandButton1.caption = "Wait..." 'Jamie 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
Ответ 4
что сказал jamietre, но
Private Sub SomeVBASub
Cancel=False
DoStuff
If not Cancel Then DoAnotherStuff
If not Cancel Then AndFinallyDothis
End Sub
Ответ 5
Я делаю это много. Много.: -)
Я привык чаще использовать "DoEvents", но все же имею в виду, что все работает, не проверяя при этом верный метод остановки.
Затем, сегодня, повторив это, я подумал: "Ну, просто дождись до конца через 3 часа" и начал кататься на ленте. Раньше я заметил в разделе "Вид" ленты теги "Макросы", и я подумал, что посмотрю, могу ли я увидеть, как мой бесконечный макрос работает....
Теперь я понимаю, что вы также можете использовать это с помощью Alt-F8.
Тогда я подумал: "Что, если я" сделаю шаг "в другом Макро, это спасет меня? Он сделал:-)
Он также работает, если вы входите в свой бегущий макрос (но вы все равно теряете то, что у вас есть), если вы не ленивый программист вроде меня и не объявляете множество "глобальных" переменных, и в этом случае сохраняются глобальные данные: )
К
Ответ 6
~ Для тех, кто использует настраиваемое поле ввода
Private Sub CommandButton1_Click()
DoCmd.Close acForm, Me.Name
End
End Sub
Ответ 7
Это старая запись, но, учитывая название вопроса, опция 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