Остановите предыдущие циклы и запустите только последний - PullRequest
0 голосов
/ 23 марта 2020

У меня есть следующий макрос. В качестве краткого описания, каждый раз, когда вы выбираете новую ячейку, она помещает текст ссылки в строке состояния в виде текста с прокруткой. Я делаю так, чтобы он не нарушал пользовательский ввод, используя «Do ... Пока l oop» с «Do events», поделится кодом ниже. Проблема в том, что если я быстро щелкаю несколько ячеек, они запоминают предыдущие циклы и запускают их все. Как настроить макрос так, чтобы он перестал запускать все циклы, кроме последнего?

Option Explicit

Public STATUSTEXT As String
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  STATUSTEXT = "Some text valid only for current selection"
  'FILL THE TEXT AND GOTO EXIT SUB TO SKIP RELEASING STATUSBAR
  charTotal = Len(STATUSTEXT)
  charI = 1

  Do
    charI = charI + 1
    Application.statusBar = Right(STATUSTEXT, charI)
    DoEvents    '@ IMPORTANT
  Loop Until charI >= charTotal

  Application.statusBar = STATUSTEXT

End Sub

1 Ответ

1 голос
/ 23 марта 2020

Хорошо, я пытаюсь лучше объяснить, что на самом деле происходит.

Ваша стрелка вниз вызывает событие Worksheet_SelectionChange. Затем этот макрос запускается и попадает в l oop с DoEvents. Это DoEvents позволяет снова перемещать курсор и выполнять другие события. Это означает, что ваш первый SelectionChange фактически останавливается на DoEvents, а второй SelectionChange срабатывает. После того, как это второе событие завершится, вы вернетесь к DoEvents первого SelectionChange события, и оно будет продолжаться до конца.

Итак, что происходит, ваши события суммируются, потому что VBA не может многопоточным. Он просто останавливает первый макрос в DoEvents, запускает следующее событие и продолжает первое событие после:

1. SelectionChange
   2. SelectionChange
      3. SelectionChange
         …
      3. SelectionChange Ends
   2. SelectionChange Ends
1. SelectionChange Ends

Таким образом, похоже, что первое SelectionChange событие запускается последним, просто потому, что оно запускает другие между , Обратите внимание, что это не многопоточность, код был остановлен.

Фактическая проблема возникла у вашего DoEvents, если вы удалите его. Excel блокирует пользовательский интерфейс до тех пор, пока первое событие SelectionChange не завершено, и не позволяет запустить другое событие, пока не завершится первое. И, к сожалению, вы увидите, что он заканчивается там, где остановился ваш курсор. Но он медленный, потому что он ожидает события, пока не выполнит следующую стрелку вниз.

Так что на самом деле вам просто нужно отменить первое событие в случае запуска другого события. Попробуйте следующее:

Option Explicit

Public GlobalStatusText As String

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim PrivateStatusText As String
    PrivateStatusText = "Some text valid only for current selection " & Target.Address
    GlobalStatusText = PrivateStatusText

    Dim charTotal As Long, charI As Long
    charTotal = Len(GlobalStatusText)
    charI = 1

    Do
        charI = charI + 1
        Application.StatusBar = Right(GlobalStatusText, charI)
        DoEvents    '@ IMPORTANT
        If GlobalStatusText <> PrivateStatusText Then Exit Sub 'cancel because another event run inbetween
    Loop Until charI >= charTotal

    Application.StatusBar = GlobalStatusText
End Sub

Это отменит предыдущие события, если другое событие изменило текст состояния между ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...