Макрос hide row требует много времени для выполнения

Есть ли способ заставить этот код работать быстрее? Я пытаюсь скрыть пустые строки на нескольких листах.

Option Explicit

Private Sub HideRows_Click()

Dim ws As Worksheet, c As Range

    Application.ScreenUpdating = False
    On Error Resume Next

    For Each ws In ThisWorkbook.Worksheets
        Select Case ws.Name
        Case "Sheet1", "Sheet2", "Sheet3"
        'sheets to exclude
            'do nothing

        Case Else 'hide rows on these sheets
            For Each c In ws.Range("AJ16:AJ153,AJ157:AJ292")
                c.EntireRow.Hidden = c.Value = 0
            Next c
        End Select
    Next ws

    Application.ScreenUpdating = True

End Sub

Отключите вычисления и события.

Scott Craner 10.08.2018 17:31

Это интересная строчка c.EntireRow.Hidden = c.Value = 0, что она должна делать?

Marcucciboy2 10.08.2018 17:32

@ Marcucciboy2 Range.Hidden хочет TRUE/FALSE, поэтому, если c.Value <> 0, он вернет FALSE и TRUE, когда это произойдет.

Scott Craner 10.08.2018 17:33

@ScottCraner ох, это действительно очень умно ...

Marcucciboy2 10.08.2018 17:34

Вы можете объединить диапазоны и скрыть их все сразу, например: stackoverflow.com/questions/8740424/…. Нет необходимости в цикле!

JvdV 10.08.2018 17:34

@ScottCraner, который решает это, мне нужно немного отдохнуть от этого, ха-ха

Marcucciboy2 10.08.2018 17:35

@ Marcucciboy2, как мне изменить его, чтобы он перебирал строку, а не каждую ячейку? Спасибо!

tangkt 10.08.2018 17:35

не беспокойтесь об этом, я ошибся :)

Marcucciboy2 10.08.2018 17:37

Когда вы говорите Macro Taking Long Time, сколько времени это займет? Также обратите внимание на первый комментарий @ScottCraner

Zac 10.08.2018 17:38

@JvdV Я бы подумал, что для создания союза потребуется цикл. Но использование объединения, чтобы скрыть сразу все строки, определенно быстрее.

Scott Craner 10.08.2018 17:44

Еще одно замечание: удалите On Error Resume Next, он скроет ошибки, которые необходимо исправить, а не игнорировать. есть время и место для его использования, но это не должно быть действием по умолчанию. только около 1% кода нуждается в этом.

Scott Craner 10.08.2018 17:45

Установка printArea может значительно замедлить ваш код

FunThomas 10.08.2018 17:46

Вот хороший пример кода, который вы можете использовать для остановки событий приложения vba codereview.stackexchange.com/a/200023/155816

Marcucciboy2 10.08.2018 17:47

@ScottCraner, поэтому кажется, что решение состоит в том, чтобы 1) перебирать диапазон и объединять, когда пустой 2) скрывает объединенный диапазон, а не скрывает строку за строкой

Marcucciboy2 10.08.2018 17:50

@ Marcucciboy2 да.

Scott Craner 10.08.2018 17:50

@ScottCraner, я упустил из виду, что в указанном диапазоне нужно искать пустые строки. Так что да, понадобится одна петля.

JvdV 10.08.2018 17:50

кажется, что улучшение может быть незначительным, но мысли о том, чтобы сначала захватить диапазон в виде массива для прокрутки?

Marcucciboy2 10.08.2018 17:52

@ Marcucciboy2, это не повредит, просто убедитесь, что вы правильно выровняли номера строк. Вам понадобятся два цикла или логика, чтобы пропустить 3 строки, которые не нужны в тесте, поскольку вы не можете загрузить один массив с несвязанным диапазоном.

Scott Craner 10.08.2018 17:53

@ScottCraner выбрал решение без массива ниже.

Marcucciboy2 10.08.2018 18:14
2
19
151
1

Ответы 1

Вот некоторые из изменений, внесенных в ваш код с целью его ускорения:

  • Отключение вычислений, событий и строки состояния
  • Сначала группировка всех значений в AJ без значений с помощью функции Union() и потом, вызывающего EntireRow.Hide в этом объединенном диапазоне

Честно говоря, для начала это был довольно чистый код!

Option Explicit

Private Sub HideRows_Click()

    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
        .DisplayStatusBar = False
        .EnableEvents = False
    End With

    'On Error Resume Next

    Dim ws As Worksheet
    For Each ws In Worksheets

        Select Case ws.name
            Case "Sheet1", "Sheet2", "Sheet3" 'sheets to exclude
                'do nothing

            Case Else 'hide rows on these sheets
                Dim unioned As Range
                Set unioned = Nothing

                Dim c As Range
                For Each c In ws.Range("AJ16:AJ153,AJ157:AJ292")
                    If Len(c.Value2) = 0 Then
                        If unioned Is Nothing Then
                            Set unioned = c
                        Else
                            Set unioned = Union(unioned, c)
                        End If
                    End If
                Next c

                unioned.EntireRow.Hidden = True
        End Select

    Next ws

    With Application
        .Calculation = xlCalculationAutomatic
        .ScreenUpdating = True
        .DisplayStatusBar = True
        .EnableEvents = True
    End With

End Sub

Я действительно не чувствовал, что несу ответственность за то, чтобы собрать это вместе, поэтому я ответил на это как вики сообщества

Marcucciboy2 10.08.2018 18:21

Спасибо за помощь! есть проблема, когда я пытаюсь запустить код со строкой "set unioned = Union (unioned, c)

tangkt 10.08.2018 18:52

ошибка времени выполнения "1004". метод 'union' объекта'_global 'завершился неудачно

tangkt 10.08.2018 18:59

@tangkt попробуйте добавить в "Приложение": Set unioned = Application.Union(unioned, c)

Marcucciboy2 10.08.2018 19:08

@tangkt, ладно, похоже, проблема в том, что Excel хочет быть уверенным, что оба диапазона, которые вы объединяете, находятся на одном листе. Итак, у меня есть две идеи, но сейчас я не могу их проверить, так как я «мобильный». 1) попробуйте set unioned = nothing сразу после того, как он затемнен, или 2) посмотрите, работает ли просто указание рабочего листа как Union(ws.unioned, c)

Marcucciboy2 10.08.2018 19:38

похоже, не сработало с моей стороны. дайте мне знать, если вы попробуете, и если это сработает для вас. Спасибо еще раз за помощь!

tangkt 10.08.2018 20:35

@tangkt извиняюсь за то, что вы заблудились на выходных, надеюсь, вы не отказались от этого! Мне удалось воспроизвести вашу ошибку, и на моей машине добавление Set unioned = Nothing сработало. Не могли бы вы скопировать его из отредактированной версии выше и попробовать еще раз?

Marcucciboy2 14.08.2018 21:32

Другие вопросы по теме