Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Оптимизация кода макроса по скрытию строк - Мир MS Excel

Старая форма входа
  • Страница 1 из 2
  • 1
  • 2
  • »
Модератор форума: китин, _Boroda_  
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Оптимизация кода макроса по скрытию строк (Макросы/Sub)
Оптимизация кода макроса по скрытию строк
Fencer Дата: Четверг, 18.01.2018, 19:20 | Сообщение № 1
Группа: Пользователи
Ранг: Новичок
Сообщений: 10
Репутация: 0 ±
Замечаний: 0% ±

Excel 2010
Доброго времени суток.
Написал код для скрытия строк (если значение в ячейке нулевое, то строку скрыть), но т.к. этот код действует на десятки тысяч строк в объемном файле, то он считает в течение длительного времени (3-4 минуты). Помогите в оптимизации кода.
В примере код конечно намного быстрее действует, но все равно 3-5 секунд.
[vba]
Код
Sub Скругленныйпрямоугольник1_Щелчок()
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Application.DisplayStatusBar = False
Dim i
For i = 16 To 38715
If Cells(i, 14).Value = 0 Then
Rows(i).EntireRow.Hidden = True
Else: Rows(i).EntireRow.Hidden = False '
End If
Next i
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Application.DisplayStatusBar = True
End Sub
[/vba]
К сообщению приложен файл: 2614200.xlsm (16.6 Kb)


Сообщение отредактировал Fencer - Четверг, 18.01.2018, 20:42
 
Ответить
СообщениеДоброго времени суток.
Написал код для скрытия строк (если значение в ячейке нулевое, то строку скрыть), но т.к. этот код действует на десятки тысяч строк в объемном файле, то он считает в течение длительного времени (3-4 минуты). Помогите в оптимизации кода.
В примере код конечно намного быстрее действует, но все равно 3-5 секунд.
[vba]
Код
Sub Скругленныйпрямоугольник1_Щелчок()
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Application.DisplayStatusBar = False
Dim i
For i = 16 To 38715
If Cells(i, 14).Value = 0 Then
Rows(i).EntireRow.Hidden = True
Else: Rows(i).EntireRow.Hidden = False '
End If
Next i
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Application.DisplayStatusBar = True
End Sub
[/vba]

Автор - Fencer
Дата добавления - 18.01.2018 в 19:20
Fencer Дата: Четверг, 18.01.2018, 20:52 | Сообщение № 2
Группа: Пользователи
Ранг: Новичок
Сообщений: 10
Репутация: 0 ±
Замечаний: 0% ±

Excel 2010
Pelena,
Fencer, код нужно оформлять тегами с помощью кнопки #, а не цитатой. Исправьте

Глюк какой то при предпросмотре сообщения тэг [vba] нормально не отображает
 
Ответить
СообщениеPelena,
Fencer, код нужно оформлять тегами с помощью кнопки #, а не цитатой. Исправьте

Глюк какой то при предпросмотре сообщения тэг [vba] нормально не отображает

Автор - Fencer
Дата добавления - 18.01.2018 в 20:52
Mikael Дата: Четверг, 18.01.2018, 22:08 | Сообщение № 3
Группа: Пользователи
Ранг: Участник
Сообщений: 80
Репутация: 31 ±
Замечаний: 0% ±

Excel 2010
Fencer, Все потому, что у Вас обрабатывается очень большое кол-во строк, не зависимо от наличия в них значений.
Сделайте неопределенный диапазон. В Вашем случае 38715 нужно заменить на Activesheet.UsedRange.Rows.Count
[vba]
Код
For i = 16 To ActiveSheet.UsedRange.Rows.Count
[/vba]

Я обычно использую вот такую конструкцию:
[vba]
Код
Dim rCell As Range
With ActiveSheet
    For Each rCell In .Cells(.UsedRange.Row, 14).Resize(.UsedRange.Rows.Count)
        If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
    Next rCell
End With
[/vba]
 
Ответить
СообщениеFencer, Все потому, что у Вас обрабатывается очень большое кол-во строк, не зависимо от наличия в них значений.
Сделайте неопределенный диапазон. В Вашем случае 38715 нужно заменить на Activesheet.UsedRange.Rows.Count
[vba]
Код
For i = 16 To ActiveSheet.UsedRange.Rows.Count
[/vba]

Я обычно использую вот такую конструкцию:
[vba]
Код
Dim rCell As Range
With ActiveSheet
    For Each rCell In .Cells(.UsedRange.Row, 14).Resize(.UsedRange.Rows.Count)
        If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
    Next rCell
End With
[/vba]

Автор - Mikael
Дата добавления - 18.01.2018 в 22:08
Mikael Дата: Четверг, 18.01.2018, 22:16 | Сообщение № 4
Группа: Пользователи
Ранг: Участник
Сообщений: 80
Репутация: 31 ±
Замечаний: 0% ±

Excel 2010
В Вашем случае 38715 нужно заменить на Activesheet.UsedRange.Rows.Count
For i = 16 To ActiveSheet.UsedRange.Rows.Count

Простите, напортачил, это у меня будет не последняя строка, а кол-во использованных, нужно нет так. dont
В Вашем случае нужно ввести переменную, которая будет содержать номер последней строки:
[vba]
Код
Dim i, lR As Long
lR = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
For i = 16 To lR
[/vba]
Ну или использовать код, который предложил в предыдущем посту.

[offtop]Все нужно идти отдыхать, голова не варит %) [/offtop]
 
Ответить
Сообщение
В Вашем случае 38715 нужно заменить на Activesheet.UsedRange.Rows.Count
For i = 16 To ActiveSheet.UsedRange.Rows.Count

Простите, напортачил, это у меня будет не последняя строка, а кол-во использованных, нужно нет так. dont
В Вашем случае нужно ввести переменную, которая будет содержать номер последней строки:
[vba]
Код
Dim i, lR As Long
lR = ActiveSheet.UsedRange.Row + ActiveSheet.UsedRange.Rows.Count - 1
For i = 16 To lR
[/vba]
Ну или использовать код, который предложил в предыдущем посту.

[offtop]Все нужно идти отдыхать, голова не варит %) [/offtop]

Автор - Mikael
Дата добавления - 18.01.2018 в 22:16
RAN Дата: Четверг, 18.01.2018, 22:22 | Сообщение № 5
Группа: Друзья
Ранг: Экселист
Сообщений: 5660
Репутация: 1163 ±
Замечаний: 0% ±

2010
В Вашем случае 38715 нужно заменить на Activesheet.UsedRange.Rows.Count

Mikael, а кто сказал, что Activesheet.UsedRange.Rows.Count < 1 000 000 ? <_<


Быть или не быть, вот в чем загвоздка!
 
Ответить
Сообщение
В Вашем случае 38715 нужно заменить на Activesheet.UsedRange.Rows.Count

Mikael, а кто сказал, что Activesheet.UsedRange.Rows.Count < 1 000 000 ? <_<

Автор - RAN
Дата добавления - 18.01.2018 в 22:22
Fencer Дата: Четверг, 18.01.2018, 22:35 | Сообщение № 6
Группа: Пользователи
Ранг: Новичок
Сообщений: 10
Репутация: 0 ±
Замечаний: 0% ±

Excel 2010
Dim rCell As Range
With ActiveSheet
    For Each rCell In .Cells(.UsedRange.Row, 14).Resize(.UsedRange.Rows.Count)
        If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
    Next rCell
End With

Mikael, спасибо. Этот код сократил время где то в 5 раз. Как еще можно оптимизировать?)
 
Ответить
Сообщение
Dim rCell As Range
With ActiveSheet
    For Each rCell In .Cells(.UsedRange.Row, 14).Resize(.UsedRange.Rows.Count)
        If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
    Next rCell
End With

Mikael, спасибо. Этот код сократил время где то в 5 раз. Как еще можно оптимизировать?)

Автор - Fencer
Дата добавления - 18.01.2018 в 22:35
bmv98rus Дата: Четверг, 18.01.2018, 23:12 | Сообщение № 7
Группа: Друзья
Ранг: Участник клуба
Сообщений: 4106
Репутация: 768 ±
Замечаний: 0% ±

Excel 2013/2016
ну может чуток подсократит время.

[vba]
Код
With ActiveSheet
    Set Wrange = .Cells(.UsedRange.Row, 14).Resize(.UsedRange.Rows.Count)
    Set RS = .Cells.SpecialCells(xlCellTypeConstants, xlNumbers)
    Set Rf = .Cells.SpecialCells(xlCellTypeFormulas, xlNumbers)
    For Each rCell In Union(Intersect(Wrange, RS), Intersect(Wrange, Rf))
        If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
    Next rCell
End With
[/vba]


Замечательный Временно просто медведь , процентов на 20.
 
Ответить
Сообщениену может чуток подсократит время.

[vba]
Код
With ActiveSheet
    Set Wrange = .Cells(.UsedRange.Row, 14).Resize(.UsedRange.Rows.Count)
    Set RS = .Cells.SpecialCells(xlCellTypeConstants, xlNumbers)
    Set Rf = .Cells.SpecialCells(xlCellTypeFormulas, xlNumbers)
    For Each rCell In Union(Intersect(Wrange, RS), Intersect(Wrange, Rf))
        If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
    Next rCell
End With
[/vba]

Автор - bmv98rus
Дата добавления - 18.01.2018 в 23:12
Mikael Дата: Четверг, 18.01.2018, 23:20 | Сообщение № 8
Группа: Пользователи
Ранг: Участник
Сообщений: 80
Репутация: 31 ±
Замечаний: 0% ±

Excel 2010
RAN, простите, не очень понял о чем Вы)) Если в 1 000 000 строк есть "0" и "1", то их нужно обработать, и это будет долго.
bmv98rus, подскажите, что означают эти строчки
[vba]
Код
    Set RS = .Cells.SpecialCells(xlCellTypeConstants, xlNumbers)
    Set Rf = .Cells.SpecialCells(xlCellTypeFormulas, xlNumbers)
[/vba]
В смысле, для чего они.


Сообщение отредактировал Mikael - Четверг, 18.01.2018, 23:23
 
Ответить
СообщениеRAN, простите, не очень понял о чем Вы)) Если в 1 000 000 строк есть "0" и "1", то их нужно обработать, и это будет долго.
bmv98rus, подскажите, что означают эти строчки
[vba]
Код
    Set RS = .Cells.SpecialCells(xlCellTypeConstants, xlNumbers)
    Set Rf = .Cells.SpecialCells(xlCellTypeFormulas, xlNumbers)
[/vba]
В смысле, для чего они.

Автор - Mikael
Дата добавления - 18.01.2018 в 23:20
bmv98rus Дата: Пятница, 19.01.2018, 00:02 | Сообщение № 9
Группа: Друзья
Ранг: Участник клуба
Сообщений: 4106
Репутация: 768 ±
Замечаний: 0% ±

Excel 2013/2016
https://msdn.microsoft.com/ru-ru....d-excel
но это даст эффект только если данных много с пропуском, текст в перемешкус числами. И не числа обрабатывать не надо.

есть ли смысл
[vba]
Код
If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
[/vba]
может надо сперва все открыть а после скрыть
[vba]
Код
usedrange.EntireRow.Hidden = false
.....
If rCell.Value = 0 Then rCell.EntireRow.Hidden =  True
[/vba]


Замечательный Временно просто медведь , процентов на 20.

Сообщение отредактировал bmv98rus - Пятница, 19.01.2018, 00:03
 
Ответить
Сообщениеhttps://msdn.microsoft.com/ru-ru....d-excel
но это даст эффект только если данных много с пропуском, текст в перемешкус числами. И не числа обрабатывать не надо.

есть ли смысл
[vba]
Код
If Not IsEmpty(rCell) Then rCell.EntireRow.Hidden = IIf(rCell.Value = 0, True, False)
[/vba]
может надо сперва все открыть а после скрыть
[vba]
Код
usedrange.EntireRow.Hidden = false
.....
If rCell.Value = 0 Then rCell.EntireRow.Hidden =  True
[/vba]

Автор - bmv98rus
Дата добавления - 19.01.2018 в 00:02
Mikael Дата: Пятница, 19.01.2018, 00:46 | Сообщение № 10
Группа: Пользователи
Ранг: Участник
Сообщений: 80
Репутация: 31 ±
Замечаний: 0% ±

Excel 2010
может надо сперва все открыть а после скрыть

Согласен, так будет быстрее - не нужно открывать единички. Я это понял пока работал идеей, осенивший на ночь глядя:

[vba]
Код
    Dim r As Range, rFind As Range
    Dim s
    s = Timer
    With ActiveSheet.UsedRange
        Set r = ActiveSheet.Cells(.Row - 1, 14).Resize(.Rows.Count + 1)
    End With
    r.EntireRow.Hidden = False
    Set rFind = r.Find(What:="0", After:=r.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
    If rFind Is Nothing Then Exit Sub
    Do
        rFind.EntireRow.Hidden = True
        Set rFind = r.Find(What:="0", After:=rFind, LookIn:=xlValues, LookAt:=xlWhole)
    Loop While Not rFind Is Nothing
    Debug.Print Timer - s
[/vba]

На 20 000 строк прирост в скорости 3,47998 против 5,432129
 
Ответить
Сообщение
может надо сперва все открыть а после скрыть

Согласен, так будет быстрее - не нужно открывать единички. Я это понял пока работал идеей, осенивший на ночь глядя:

[vba]
Код
    Dim r As Range, rFind As Range
    Dim s
    s = Timer
    With ActiveSheet.UsedRange
        Set r = ActiveSheet.Cells(.Row - 1, 14).Resize(.Rows.Count + 1)
    End With
    r.EntireRow.Hidden = False
    Set rFind = r.Find(What:="0", After:=r.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
    If rFind Is Nothing Then Exit Sub
    Do
        rFind.EntireRow.Hidden = True
        Set rFind = r.Find(What:="0", After:=rFind, LookIn:=xlValues, LookAt:=xlWhole)
    Loop While Not rFind Is Nothing
    Debug.Print Timer - s
[/vba]

На 20 000 строк прирост в скорости 3,47998 против 5,432129

Автор - Mikael
Дата добавления - 19.01.2018 в 00:46
bmv98rus Дата: Пятница, 19.01.2018, 08:03 | Сообщение № 11
Группа: Друзья
Ранг: Участник клуба
Сообщений: 4106
Репутация: 768 ±
Замечаний: 0% ±

Excel 2013/2016
Mikael, Если замените r.Find на загрузку в массив, перебор и удаление будет еще быстрее, а если скрыть в конце ( то есть накопить что скрывать и разом удалить ,может выйти еще лучше.


Замечательный Временно просто медведь , процентов на 20.
 
Ответить
СообщениеMikael, Если замените r.Find на загрузку в массив, перебор и удаление будет еще быстрее, а если скрыть в конце ( то есть накопить что скрывать и разом удалить ,может выйти еще лучше.

Автор - bmv98rus
Дата добавления - 19.01.2018 в 08:03
Karataev Дата: Пятница, 19.01.2018, 09:47 | Сообщение № 12
Группа: Проверенные
Ранг: Старожил
Сообщений: 1334
Репутация: 533 ±
Замечаний: 0% ±

Excel
Mikael, Find медленно работает при многократном запуске, нужно использовать что-нибудь другое, например массив (в посте 11 об этом ужу упоминалось):
 
Ответить
СообщениеMikael, Find медленно работает при многократном запуске, нужно использовать что-нибудь другое, например массив (в посте 11 об этом ужу упоминалось):

Автор - Karataev
Дата добавления - 19.01.2018 в 09:47
SLAVICK Дата: Пятница, 19.01.2018, 10:06 | Сообщение № 13
Группа: Модераторы
Ранг: Старожил
Сообщений: 2290
Репутация: 766 ±
Замечаний: 0% ±

2019
Если замените r.Find на загрузку в массив,

будет быстрее, но в скрытии строк самое долгое - скрытие строки :) - все остальное относительно быстро.
Ускорить можно одновременным скрытием массива строк.
Например так:
[vba]
Код
Sub d()
Dim r As Range, c As Range, RH As Range
Dim i&, n&, arr
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual

n = Cells(Rows.Count, 14).End(xlUp).Row
Set r = Range("n2:n" & n)

For Each c In r
    If c = 1 Then
        If RH Is Nothing Then Set RH = c Else Set RH = Union(RH, c)
'        =====check count===============
        i = i + 1
        If i = 8000 Then i = 0: RH.EntireRow.Hidden = True: Set RH = Nothing
'        ====================
    End If
Next
RH.EntireRow.Hidden = True

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
End Sub
[/vba]

В файле сделал сравнение 3-х вариантов.
На 2-х тыс. получилось:
[vba]
Код
Slavick 0,40625
Mikael 9,773438
bmv98rus 5,449219
[/vba]
К сообщению приложен файл: TestHideRows-2-.xlsm (38.0 Kb)


Иногда все проще чем кажется с первого взгляда.
 
Ответить
Сообщение
Если замените r.Find на загрузку в массив,

будет быстрее, но в скрытии строк самое долгое - скрытие строки :) - все остальное относительно быстро.
Ускорить можно одновременным скрытием массива строк.
Например так:
[vba]
Код
Sub d()
Dim r As Range, c As Range, RH As Range
Dim i&, n&, arr
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual

n = Cells(Rows.Count, 14).End(xlUp).Row
Set r = Range("n2:n" & n)

For Each c In r
    If c = 1 Then
        If RH Is Nothing Then Set RH = c Else Set RH = Union(RH, c)
'        =====check count===============
        i = i + 1
        If i = 8000 Then i = 0: RH.EntireRow.Hidden = True: Set RH = Nothing
'        ====================
    End If
Next
RH.EntireRow.Hidden = True

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
End Sub
[/vba]

В файле сделал сравнение 3-х вариантов.
На 2-х тыс. получилось:
[vba]
Код
Slavick 0,40625
Mikael 9,773438
bmv98rus 5,449219
[/vba]

Автор - SLAVICK
Дата добавления - 19.01.2018 в 10:06
Fencer Дата: Пятница, 19.01.2018, 12:05 | Сообщение № 14
Группа: Пользователи
Ранг: Новичок
Сообщений: 10
Репутация: 0 ±
Замечаний: 0% ±

Excel 2010
SLAVICK, спасибо!

Вставил ваш код в мою программу, код не проходит и vba ругается на эту строку
[vba]
Код
RH.EntireRow.Hidden = True
[/vba]
Пишет Run-time error '91'
В чем может быть проблема? Я только заменил номер столбца
 
Ответить
СообщениеSLAVICK, спасибо!

Вставил ваш код в мою программу, код не проходит и vba ругается на эту строку
[vba]
Код
RH.EntireRow.Hidden = True
[/vba]
Пишет Run-time error '91'
В чем может быть проблема? Я только заменил номер столбца

Автор - Fencer
Дата добавления - 19.01.2018 в 12:05
SLAVICK Дата: Пятница, 19.01.2018, 12:11 | Сообщение № 15
Группа: Модераторы
Ранг: Старожил
Сообщений: 2290
Репутация: 766 ±
Замечаний: 0% ±

2019
а вы объявили переменную? и есть ли хоть одна ячейка, подходящая под условия?
если нет таких ячеек то самый простой вариант добавить строку
[vba]
Код
On Error Resume Next
[/vba]
Попробуйте в моем примере подставить нужные данные - так сложно сказать


Иногда все проще чем кажется с первого взгляда.
 
Ответить
Сообщениеа вы объявили переменную? и есть ли хоть одна ячейка, подходящая под условия?
если нет таких ячеек то самый простой вариант добавить строку
[vba]
Код
On Error Resume Next
[/vba]
Попробуйте в моем примере подставить нужные данные - так сложно сказать

Автор - SLAVICK
Дата добавления - 19.01.2018 в 12:11
bmv98rus Дата: Пятница, 19.01.2018, 12:13 | Сообщение № 16
Группа: Друзья
Ранг: Участник клуба
Сообщений: 4106
Репутация: 768 ±
Замечаний: 0% ±

Excel 2013/2016
SLAVICK,
Ускорить можно одновременным скрытием массива строк
именно это я и имел в виду
о есть накопить что скрывать и разом удалить ,может выйти еще лучше

но что-то с мобилки написалось не так как хотел сказать :-) но если все готово и стаймером, то просто попробуйте через перебор масива с Union строк совместить. Там изменений не много, разве что предусмотреть сдвиг на начальную строку


Замечательный Временно просто медведь , процентов на 20.
 
Ответить
СообщениеSLAVICK,
Ускорить можно одновременным скрытием массива строк
именно это я и имел в виду
о есть накопить что скрывать и разом удалить ,может выйти еще лучше

но что-то с мобилки написалось не так как хотел сказать :-) но если все готово и стаймером, то просто попробуйте через перебор масива с Union строк совместить. Там изменений не много, разве что предусмотреть сдвиг на начальную строку

Автор - bmv98rus
Дата добавления - 19.01.2018 в 12:13
Mikael Дата: Пятница, 19.01.2018, 12:32 | Сообщение № 17
Группа: Пользователи
Ранг: Участник
Сообщений: 80
Репутация: 31 ±
Замечаний: 0% ±

Excel 2010
bmv98rus, Karataev, SLAVICK, вау, круто, очень много интересных приемов! Спасибо :)
SLAVICK, все дело было в не выключенном обновлении экрана, я в постах оставлял только исполняющий код, а у ТСа были все отключения обновления экрана, калькуляции и прочее. У меня получилось:
[vba]
Код
Slavick  0,4140625
Mikael  0,2890625
bmv98rus  0,4296875
Karataev  0,234375
ArrayUnion  0,3828125
[/vba]
Метод с массивом, показывает ошеломляющую скорость, но когда пытаюсь добавить Union, результат ухудшается.

А при увеличении строк до 6 тыс (лист2), результат с Union значительно ухудшается относительно остальных:
[vba]
Код
Slavick  10,42578125
Mikael  0,765625
bmv98rus  1,332031
Karataev  0,6367188
ArrayUnion  10,12891
[/vba]
К сообщению приложен файл: TestHideRows2.xlsm (88.3 Kb)
 
Ответить
Сообщениеbmv98rus, Karataev, SLAVICK, вау, круто, очень много интересных приемов! Спасибо :)
SLAVICK, все дело было в не выключенном обновлении экрана, я в постах оставлял только исполняющий код, а у ТСа были все отключения обновления экрана, калькуляции и прочее. У меня получилось:
[vba]
Код
Slavick  0,4140625
Mikael  0,2890625
bmv98rus  0,4296875
Karataev  0,234375
ArrayUnion  0,3828125
[/vba]
Метод с массивом, показывает ошеломляющую скорость, но когда пытаюсь добавить Union, результат ухудшается.

А при увеличении строк до 6 тыс (лист2), результат с Union значительно ухудшается относительно остальных:
[vba]
Код
Slavick  10,42578125
Mikael  0,765625
bmv98rus  1,332031
Karataev  0,6367188
ArrayUnion  10,12891
[/vba]

Автор - Mikael
Дата добавления - 19.01.2018 в 12:32
bmv98rus Дата: Пятница, 19.01.2018, 12:55 | Сообщение № 18
Группа: Друзья
Ранг: Участник клуба
Сообщений: 4106
Репутация: 768 ±
Замечаний: 0% ±

Excel 2013/2016
Mikael,
[vba]
Код
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
[/vba]
Последние два тоже не лишние

[vba]
Код
            If rHide Is Nothing Then Set rHide = rng.Cells(i, 1) Else _
                    Set rHide = Union(rHide, rng.Cells(i, 1))
[/vba] попробывать бы упростить, например проверку не через rHide Is Nothing а через тригер, без обращения к объекту то есть [vba]
Код
If not trig then
rHide = rng.Cells(i, 1) : Trig=true
else
Set rHide = Union(rHide, rng.Cells(i, 1))
end if
[/vba]
но допускаю что сам Union жрет время.


Замечательный Временно просто медведь , процентов на 20.
 
Ответить
СообщениеMikael,
[vba]
Код
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
[/vba]
Последние два тоже не лишние

[vba]
Код
            If rHide Is Nothing Then Set rHide = rng.Cells(i, 1) Else _
                    Set rHide = Union(rHide, rng.Cells(i, 1))
[/vba] попробывать бы упростить, например проверку не через rHide Is Nothing а через тригер, без обращения к объекту то есть [vba]
Код
If not trig then
rHide = rng.Cells(i, 1) : Trig=true
else
Set rHide = Union(rHide, rng.Cells(i, 1))
end if
[/vba]
но допускаю что сам Union жрет время.

Автор - bmv98rus
Дата добавления - 19.01.2018 в 12:55
RAN Дата: Пятница, 19.01.2018, 13:52 | Сообщение № 19
Группа: Друзья
Ранг: Экселист
Сообщений: 5660
Репутация: 1163 ±
Замечаний: 0% ±

2010
Раз пошла такая пьянка, и я мяукну.
Slavick 0,43359375
Mikael 0,546875
bmv98rus 0,9492188
Karataev 0,46875
ArrayUnion 0,4609375
Мяу 0,1054688
[vba]
Код
Sub Мяу()
    Dim oDic As Object, ar1, ar2()
    Dim i&, k&, n&
    Dim t!
    t = Timer
    Cells.EntireRow.Hidden = False
    n = Cells(Rows.Count, 14).End(xlUp).Row
    ar1 = Range("n1:n" & n).Value

    Set oDic = CreateObject("Scripting.Dictionary")
    With oDic
        For i = 1 To UBound(ar1)
            If ar1(i, 1) = 1 Then .Item(ar1(i, 1)) = .Item(ar1(i, 1)) & "," & "A" & i
            If Len(.Item(ar1(i, 1))) > 200 Then
                ReDim Preserve ar2(k)
                ar2(k) = Mid(.Item(ar1(i, 1)), 2)
                .Item(ar1(i, 1)) = ""
                k = k + 1
            End If
        Next
    End With
    Application.ScreenUpdating = False
    For i = LBound(ar2) To UBound(ar2)
        Range(ar2(i)).EntireRow.Hidden = True
    Next
    Debug.Print "Мяу "; Timer - t

End Sub
[/vba]
На Лист2
Slavick 9,109375
Mikael 1,625
bmv98rus 2,9375
Karataev 1,417969
ArrayUnion 8,917969
Мяу 0,3164063


Быть или не быть, вот в чем загвоздка!

Сообщение отредактировал RAN - Пятница, 19.01.2018, 14:04
 
Ответить
СообщениеРаз пошла такая пьянка, и я мяукну.
Slavick 0,43359375
Mikael 0,546875
bmv98rus 0,9492188
Karataev 0,46875
ArrayUnion 0,4609375
Мяу 0,1054688
[vba]
Код
Sub Мяу()
    Dim oDic As Object, ar1, ar2()
    Dim i&, k&, n&
    Dim t!
    t = Timer
    Cells.EntireRow.Hidden = False
    n = Cells(Rows.Count, 14).End(xlUp).Row
    ar1 = Range("n1:n" & n).Value

    Set oDic = CreateObject("Scripting.Dictionary")
    With oDic
        For i = 1 To UBound(ar1)
            If ar1(i, 1) = 1 Then .Item(ar1(i, 1)) = .Item(ar1(i, 1)) & "," & "A" & i
            If Len(.Item(ar1(i, 1))) > 200 Then
                ReDim Preserve ar2(k)
                ar2(k) = Mid(.Item(ar1(i, 1)), 2)
                .Item(ar1(i, 1)) = ""
                k = k + 1
            End If
        Next
    End With
    Application.ScreenUpdating = False
    For i = LBound(ar2) To UBound(ar2)
        Range(ar2(i)).EntireRow.Hidden = True
    Next
    Debug.Print "Мяу "; Timer - t

End Sub
[/vba]
На Лист2
Slavick 9,109375
Mikael 1,625
bmv98rus 2,9375
Karataev 1,417969
ArrayUnion 8,917969
Мяу 0,3164063

Автор - RAN
Дата добавления - 19.01.2018 в 13:52
SLAVICK Дата: Пятница, 19.01.2018, 14:35 | Сообщение № 20
Группа: Модераторы
Ранг: Старожил
Сообщений: 2290
Репутация: 766 ±
Замечаний: 0% ±

2019
А при увеличении строк до 6 тыс (лист2),

там у меня сбрасыватель стоит на 8000 - если его уменьшить до 500 - то мой вариант на порядок шустрее :) .
А вариант с ArrayUnion - не на много будет шустрее первого(если также поставить сбросы).

Раз пошла такая пьянка,

ну тогда еще вариант от меня :)
[vba]
Код
Sub Slavick_ArrayAndDic()
    Dim rng As Range, rHide As Range, arr(), i As Long
    Dim s, dic As Object, n&
    Dim rrr As Ranges
    Set dic = CreateObject("Scripting.Dictionary")
    Cells.EntireRow.Hidden = False
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    s = Timer
    Set rng = ActiveSheet.UsedRange.Columns("N")
    n = rng.Row
    arr() = rng.Value
    For i = 1 To UBound(arr)
        If arr(i, 1) = 0 Then
            dic(i + n - 1) = i + n - 1
    '        =====check count===============
            ii = ii + Len(Format(i + n, 0)) + 2
            If ii >= 250 Then
                ii = 0
                Range("A" & Join(dic.keys, ",A")).EntireRow.Hidden = True
                dic.RemoveAll
            End If
    '        ====================
        End If
    Next i
    Range("A" & Join(dic.keys, ",A")).EntireRow.Hidden = True
    Debug.Print "Slavick_ArrayAndDic "; Format(Timer - s, "0.0000")
    Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
[/vba]

Сравнение 2-го листа(1-й даже не интересно смотреть):
[vba]
Код
Slavick 0,1719
Mikael 0,6133
bmv98rus 0,9844
Karataev 0,4805
ArrayUnion 0,1523
Slavick_ArrayAndDic 0,0313
Мяу 1,1523
[/vba]
К сообщению приложен файл: TestHideRows3.xlsm (64.7 Kb)


Иногда все проще чем кажется с первого взгляда.
 
Ответить
Сообщение
А при увеличении строк до 6 тыс (лист2),

там у меня сбрасыватель стоит на 8000 - если его уменьшить до 500 - то мой вариант на порядок шустрее :) .
А вариант с ArrayUnion - не на много будет шустрее первого(если также поставить сбросы).

Раз пошла такая пьянка,

ну тогда еще вариант от меня :)
[vba]
Код
Sub Slavick_ArrayAndDic()
    Dim rng As Range, rHide As Range, arr(), i As Long
    Dim s, dic As Object, n&
    Dim rrr As Ranges
    Set dic = CreateObject("Scripting.Dictionary")
    Cells.EntireRow.Hidden = False
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    s = Timer
    Set rng = ActiveSheet.UsedRange.Columns("N")
    n = rng.Row
    arr() = rng.Value
    For i = 1 To UBound(arr)
        If arr(i, 1) = 0 Then
            dic(i + n - 1) = i + n - 1
    '        =====check count===============
            ii = ii + Len(Format(i + n, 0)) + 2
            If ii >= 250 Then
                ii = 0
                Range("A" & Join(dic.keys, ",A")).EntireRow.Hidden = True
                dic.RemoveAll
            End If
    '        ====================
        End If
    Next i
    Range("A" & Join(dic.keys, ",A")).EntireRow.Hidden = True
    Debug.Print "Slavick_ArrayAndDic "; Format(Timer - s, "0.0000")
    Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
[/vba]

Сравнение 2-го листа(1-й даже не интересно смотреть):
[vba]
Код
Slavick 0,1719
Mikael 0,6133
bmv98rus 0,9844
Karataev 0,4805
ArrayUnion 0,1523
Slavick_ArrayAndDic 0,0313
Мяу 1,1523
[/vba]

Автор - SLAVICK
Дата добавления - 19.01.2018 в 14:35
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Оптимизация кода макроса по скрытию строк (Макросы/Sub)
  • Страница 1 из 2
  • 1
  • 2
  • »
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!