VBA перемещение определенного листа до / после выбранного листа занимает слишком много времени — почему?

#excel #vba

#excel #vba

Вопрос:

У меня есть простой код, который перемещает данные рабочего листа на лист после активации.

 Sub Workbook_SheetActivate(ByVal Sh As Object)
  Worksheets("Data").Move After:=Worksheets(Sh.Name)
  Worksheets(Sh.Name).Activate
End Sub
 

Я использую

 Worksheets(Sh.Name).Activate
 

потому что без этой строки «Данные» рабочего листа остаются выбранными после перемещения, что не является намерением.

Проблема, с которой я сталкиваюсь, заключается в том, что при запуске этого кода Excel требуется около 2-3 секунд, чтобы подумать об этом, прежде чем увидеть результат.

Я не понимаю, почему. Без объединения этих 2 операций вместе это занимает миллисекунды. Не мог бы кто-нибудь объяснить, как это улучшить и почему это происходит?

Комментарии:

1. Причин такого поведения может быть несколько, например: другой макрос, который используется для вычисления некоторых значений. Я бы проверил, активен ли Data лист, а затем изменил порядок листов. Кстати: можете ли вы уточнить, почему Data лист должен быть неактивным?

2. Или почему вам нужно, чтобы Sh был активным? Если у вас используется другой код ActiveSheet , вы можете заменить его различными способами…

3. Ваш код войдет в бесконечный цикл — более 2-3 секунд, я бы подумал. Перед его запуском необходимо отключить события.

4. Кстати Worksheets(Sh.Name) , эквивалентно sh .

Ответ №1:

Это должно быть быстрее:

 Sub Workbook_SheetActivate(ByVal Sh As Object)
    Dim nam As String

    nam = Sh.Name
    Application.EnableEvents = False
        Worksheets("Data").Move After:=Worksheets(nam)
        Worksheets(nam).Activate
    Application.EnableEvents = True
End Sub
 

Ответ №2:

Это происходит из-за рекурсивного вызова: когда вы используете .Activate , ваш Sub Workbook_SheetActivate вызывается снова, и вы застреваете в бесконечном цикле.

Если вы просто хотите отменить выбор диапазона данных, вы можете использовать Cells(1,1).Select , и вы можете напрямую использовать Sh вместо использования Worksheets(Sh.Name) , поскольку они эквивалентны.

Итак, ваш окончательный код будет:

 Sub Workbook_SheetActivate(ByVal Sh As Object)
   Worksheets("Data").Move After:=Sh
   Cells(1,1).Select
End Sub
 

Надеюсь, это поможет.

Ответ №3:

Спасибо за ваш вклад, ребята. Отключение / включение событий помогло выйти из цикла.

     Application.EnableEvents = False
    Worksheets("Data").Move After:=Sh
    sh.Activate
    Application.EnableEvents = True
 

Вероятно, я должен был объяснить, для чего использовался код в моем вопросе.

У пользователя было более 50 листов в рабочей книге (пожалуйста, не спрашивайте меня, почему :)). У них был один конкретный («Данные»), который они хотели иметь возможность нажимать и выключать во время работы с другими листами. Итак, этот код просто заставлял «Данные» рабочего листа «следовать за ними»

Строка:

 sh.Activate
 

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