Редактировать:
Я подумал о другом способе справиться с этим - возможно, ближе к тому, что вы искали.,,
![img](https://i.stack.imgur.com/w0YPn.gif)
Это просто расширение базовой паузы , которую яиспользовать время от времени.
Это моя "обычная" Pause
процедура (с использованием функции Timer
):
Sub Pause(seconds As Single)
Dim startTime As Single
startTime = Timer 'get current timer count
Do
DoEvents 'let Windows "catch up"
Loop Until Timer > startTime + seconds 'repeat until time's up
End Sub
... такДала мне идею.
Честно говоря, я был немного удивлен, обнаружив, что это работает, поскольку он в основном выполняет две секции кода одновременно .
Код для WaitForUserActivity
:
Вот код, который я использовал в приведенной выше демонстрации:
Option Explicit
Public isPaused As Boolean
Sub WaitForUserActivity() 'THE 'RUN DEMO' BUTTON runs this sub.
Dim origSheet As String
isPaused = True 'flag "pause mode" as "on"
origSheet = ActiveSheet.Name 'remember current worksheet name
MsgBox "This will 'pause' code execution until you" & vbLf & _
"click the 'Continue' button, or select a different a worksheet."
Application.StatusBar = "PAUSED: Click ""Continue"", or select a worksheet."
Do 'wait for button click or ws change
DoEvents 'yield execution so that the OS can process other events
Loop Until (Not isPaused) Or (ActiveSheet.Name <> origSheet)
If isPaused Then 'the active worksheet was changed
MsgBox "Worksheet '" & ActiveSheet.Name & "' was selected." _
& vbLf & vbLf & "Now the program can continue..."
Else 'the button was clicked
MsgBox "The 'Continue' button was clicked." _
& vbLf & vbLf & "Now the program can continue..."
End If
Application.StatusBar = "Ready"
End Sub
Sub btnContinue() 'THE 'CONTINUE' BUTTON runs this sub.
isPaused = False 'flag "pause mode" as "off"
End Sub
Для запуска демонстрации :
- поместите вышеуказанный код вобычный модуль
- убедитесь, что в книге есть как минимум две таблицы
- , создайте две кнопки управления:
- одну для кнопки " Run Demo ",назначьте макрос:
WaitForUserActivity
- один для кнопки " Продолжить ", назначьте макрос:
btnContinue
- нажмите "Кнопка запуска демонстрации"
Ключевой командой в коде является DoEvents
Функция , которая" приводит к выполнению, так что операционная система может обрабатывать другиесобытия. "
DoEvents
передает управление операционной системе.Управление возвращается после того, как операционная система завершила обработку событий в своей очереди и все ключи в очереди SendKeys были отправлены.
DoEvents
наиболее полезен для простых вещей, таких как разрешение пользователю отменить процесс после его запуска, например, поиск файла.Для длительных процессов выход из процессора лучше выполнить с помощью таймера или делегирования задачи компоненту ActiveX
EXE
, а операционная система позаботится о многозадачности и сокращении времени.
Каждый раз, когда вы временно отдаете процессор в рамках процедуры события, убедитесь, что процедура не выполняется снова из другой части вашего кода, прежде чем первый вызов вернет ;это может привести к непредсказуемым результатам.
Дополнительные сведения (и предупреждения) в источнике .
Оригинальный ответ:
Некоторые предлагаемые решения:
Вместо "остановки" кода вы можете предложить пользователю указать, какой лист.
Самый простой способ - использовать InputBox
, где пользователь вводит идентификационный номер или иным образом идентифицирует рабочий лист.
Более сложный, но более надежныйи профессионально выглядящий будет настраиваемое диалоговое окно с помощью пользовательской формы.В Интернете есть несколько примеров и учебных пособий, таких как этот .
Вы можете "приостановить" выполнение , чтобы датьпользователь устанавливает количество времени для выбора листа с помощью простого цикла таймера , и вы даже можете проверить имя листа, чтобы увидеть, выбрал ли пользователь новый, что-то вроде этого:
Dim startTime As Single, shtName As String
If ThisWorkbook.Worksheets.Count = 1 Then
MsgBox "There is only one worksheet in this workbook."
Else
shtName = ActiveSheet.Name 'get name of active sheet
MsgBox "You have 5 seconds to select a worksheet after clicking OK.", _
vbOKOnly + vbInformation, "Select a worksheet... fast!"
startTime = Timer
Do
DoEvents
Loop Until Timer > startTime + 5
'check if user picked a new worksheet
If ActiveSheet.Name = shtName Then
MsgBox "You didn't select a new worksheet!"
Else
MsgBox "Thanks for selecting a new worksheet!"
End If
End If
Это немного глупо, но может сработать, особенно если правильно проверить, чтобы убедиться, что вы получили правильный лист сейчас.
Полагаю, вы могли бы создать процедура события рабочего листа , которая запускается при активации рабочего листа, и проверяет глобальную переменную, чтобы проверить, была ли запущена ваша "процедура импорта" , и если да, возобновить ваш код... но это было бы грязно и запутанно и потребовало бы наличия кода в рабочей книге, которую вы "импортируете".
или лучше, чем любой из этих будет программно / логически определять, какая работалист вам нужно в зависимости от содержимого листа.Есть ли название?Определенная дата?Может быть, самый новый лист?Что-то в определенной клетке?Должно быть что-то, что отличает это от других.
Надеюсь, это даст вам некоторые идеи для нелинейного решения.?