Всем привет! Подскажите пожалуйста, как можно ускорить работу макроса: [vba]
Код
Sub СкрытьСтроки_х() If ActiveSheet.ListObjects.Count = 0 Then Exit Sub Application.ScreenUpdating = False ActiveSheet.UsedRange.EntireRow.Hidden = False Dim tb As ListObject For Each tb In ActiveSheet.ListObjects JobTb tb Next Application.ScreenUpdating = True End Sub
Private Sub JobTb(tb As ListObject) Dim flag As Boolean Dim cl As Range For Each cl In tb.DataBodyRange.Columns(1).Cells flag = False If cl.Cells(1, 17).Value = "скрыть" Then flag = True End If Select Case cl.Interior.Color Case 11389944, 14277081 Case Else flag = True End Select
If flag Then cl.EntireRow.Hidden = True Next End Sub
[/vba] Суть вопроса заключается в том, что при наличии в "умной таблице" более 3 500 тыс. строк он, макрос, очень долго скрывает строки - более 5 минут. Файл не выкладываю, т.к. его объем велик, а если прикрепить урезанный вариант, то скорость работы макроса сложно будет оценить. Спасибо.
Всем привет! Подскажите пожалуйста, как можно ускорить работу макроса: [vba]
Код
Sub СкрытьСтроки_х() If ActiveSheet.ListObjects.Count = 0 Then Exit Sub Application.ScreenUpdating = False ActiveSheet.UsedRange.EntireRow.Hidden = False Dim tb As ListObject For Each tb In ActiveSheet.ListObjects JobTb tb Next Application.ScreenUpdating = True End Sub
Private Sub JobTb(tb As ListObject) Dim flag As Boolean Dim cl As Range For Each cl In tb.DataBodyRange.Columns(1).Cells flag = False If cl.Cells(1, 17).Value = "скрыть" Then flag = True End If Select Case cl.Interior.Color Case 11389944, 14277081 Case Else flag = True End Select
If flag Then cl.EntireRow.Hidden = True Next End Sub
[/vba] Суть вопроса заключается в том, что при наличии в "умной таблице" более 3 500 тыс. строк он, макрос, очень долго скрывает строки - более 5 минут. Файл не выкладываю, т.к. его объем велик, а если прикрепить урезанный вариант, то скорость работы макроса сложно будет оценить. Спасибо.graff9540
. Данную тему я читал. На ее основе набросал свой макрос: [vba]
Код
Sub СкрытьБелыхИ_х()
Dim с As Date Dim d As Single 'Больше не обновляем страницы после каждого действия Application.ScreenUpdating = False 'Отключаем события Application.EnableEvents = False 'Расчёты переводим в ручной режим Application.Calculation = xlCalculationManual c = Time If ActiveSheet.ListObjects.Count = 0 Then Exit Sub
Application.ScreenUpdating = False ActiveSheet.UsedRange.EntireRow.Hidden = False Dim tb As ListObject For Each tb In ActiveSheet.ListObjects JobTb tb Next Application.ScreenUpdating = True d = (Time - c) * 24 * 60 * 60 'Расчёты переводим в автоматический режим Application.Calculation = xlCalculationAutomatic 'Включаем события Application.EnableEvents = True 'Включаем обновление страниц после каждого действия Application.ScreenUpdating = True
MsgBox "Время выполения макроса составило: " & d & " c.", vbInformation, "Отчет" End Sub Private Sub JobTb(tb As ListObject) Dim flag As Boolean Dim cl As Range For Each cl In tb.DataBodyRange.Columns(1).Cells flag = False If cl.Cells(1, 14).Value = "х" Then flag = True End If Select Case cl.Interior.Color Case 11389944, 14277081 Case Else flag = True End Select
If flag Then cl.EntireRow.Hidden = True Next End Sub
[/vba] Вот результаты: число строк 3616: - время выполнения доработанного макроса 3 с. - время выполнения без доработки Excel после 5 минут обработки не отвечает И ВОТ РЕЗУЛЬТАТ - 85757 с
Но вот еще что меня волнует: 1. Как привязать макрос на работу в с "умной таблицей"? 2. Возможно ли сделать так, чтобы столбец, в котором имеется значение "скрыть" был постоянно скрыт от глаз пользователя? 3. Возможно ли сделать так, чтобы строки 5-9 были постоянно скрыты от глаз пользователя?
Буду признателен за оказанную помощь.
PS: Файл немного уменьшил в объеме - убрал строки, дабы попасть в размер.
. Данную тему я читал. На ее основе набросал свой макрос: [vba]
Код
Sub СкрытьБелыхИ_х()
Dim с As Date Dim d As Single 'Больше не обновляем страницы после каждого действия Application.ScreenUpdating = False 'Отключаем события Application.EnableEvents = False 'Расчёты переводим в ручной режим Application.Calculation = xlCalculationManual c = Time If ActiveSheet.ListObjects.Count = 0 Then Exit Sub
Application.ScreenUpdating = False ActiveSheet.UsedRange.EntireRow.Hidden = False Dim tb As ListObject For Each tb In ActiveSheet.ListObjects JobTb tb Next Application.ScreenUpdating = True d = (Time - c) * 24 * 60 * 60 'Расчёты переводим в автоматический режим Application.Calculation = xlCalculationAutomatic 'Включаем события Application.EnableEvents = True 'Включаем обновление страниц после каждого действия Application.ScreenUpdating = True
MsgBox "Время выполения макроса составило: " & d & " c.", vbInformation, "Отчет" End Sub Private Sub JobTb(tb As ListObject) Dim flag As Boolean Dim cl As Range For Each cl In tb.DataBodyRange.Columns(1).Cells flag = False If cl.Cells(1, 14).Value = "х" Then flag = True End If Select Case cl.Interior.Color Case 11389944, 14277081 Case Else flag = True End Select
If flag Then cl.EntireRow.Hidden = True Next End Sub
[/vba] Вот результаты: число строк 3616: - время выполнения доработанного макроса 3 с. - время выполнения без доработки Excel после 5 минут обработки не отвечает И ВОТ РЕЗУЛЬТАТ - 85757 с
Но вот еще что меня волнует: 1. Как привязать макрос на работу в с "умной таблицей"? 2. Возможно ли сделать так, чтобы столбец, в котором имеется значение "скрыть" был постоянно скрыт от глаз пользователя? 3. Возможно ли сделать так, чтобы строки 5-9 были постоянно скрыты от глаз пользователя?
Буду признателен за оказанную помощь.
PS: Файл немного уменьшил в объеме - убрал строки, дабы попасть в размер.graff9540
Но вот еще что меня волнует: 2. Возможно ли сделать так, чтобы столбец, в котором имеется значение "скрыть" был постоянно скрыт от глаз пользователя? 3. Возможно ли сделать так, чтобы строки 5-9 были постоянно скрыты от глаз пользователя?
Вот добавил макрос в корень "Эта книга": [vba]
Код
Sub HideColumnsRows() With Worksheets("Литс 1") .Columns(14).Hidden = True .Rows("5:9").Hidden = True End With End Sub
[/vba]
Вроде все стартует. Но не могу понять, как сделать так, чтобы он реагировал на автоматическое скрытие даже тогда, когда пользователь их "покажет".
Но вот еще что меня волнует: 2. Возможно ли сделать так, чтобы столбец, в котором имеется значение "скрыть" был постоянно скрыт от глаз пользователя? 3. Возможно ли сделать так, чтобы строки 5-9 были постоянно скрыты от глаз пользователя?
Вот добавил макрос в корень "Эта книга": [vba]
Код
Sub HideColumnsRows() With Worksheets("Литс 1") .Columns(14).Hidden = True .Rows("5:9").Hidden = True End With End Sub
[/vba]
Вроде все стартует. Но не могу понять, как сделать так, чтобы он реагировал на автоматическое скрытие даже тогда, когда пользователь их "покажет".graff9540
Сообщение отредактировал graff9540 - Четверг, 06.04.2023, 00:36
Здравствуйте. Так вам же дали ответ на другом форуме! Поделитесь кодом здесь и закрыли тему с дублями на разных форумах.
Добрый день/вечер. Да, действительно, уважаемый МатросНаЗебре с planetaexcel любезно предложил код макроса. За что ему огромное спасибо.
Я его протестировал. И если Вы внимательно читали тему на том форуме, то должны были увидеть результаты.
Насчет закрытия темы, вопрос интересный, так как при большом количестве строк в умной таблице макрос не такой шустрый. Возможно, найдутся пользователи форума, которым будет интересно подкинуть идей по поводу оптимизации макроса.
Здравствуйте. Так вам же дали ответ на другом форуме! Поделитесь кодом здесь и закрыли тему с дублями на разных форумах.
Добрый день/вечер. Да, действительно, уважаемый МатросНаЗебре с planetaexcel любезно предложил код макроса. За что ему огромное спасибо.
Я его протестировал. И если Вы внимательно читали тему на том форуме, то должны были увидеть результаты.
Насчет закрытия темы, вопрос интересный, так как при большом количестве строк в умной таблице макрос не такой шустрый. Возможно, найдутся пользователи форума, которым будет интересно подкинуть идей по поводу оптимизации макроса.graff9540
- время выполнения доработанного макроса 3 с. - время выполнения без доработки Excel после 5 минут обработки не отвечает
3 секунды - это много, что ли? Чем не устраивает?
[p.s.]Если много, то вот вариант на 1 секунду ("1С" практически :)):[/p.s.] [vba]
Код
Private Sub JobTurbo(tb As ListObject) Dim wks As Worksheet, rng As Range, colA As Range, column As Range Dim val As Variant, t As Variant, i As Long
t = Timer Set colA = tb.DataBodyRange.Columns(1) 'колонка цвета Set column = tb.DataBodyRange.Columns(14) 'колонка крестиков
Set wks = tb.Parent Set rng = wks.UsedRange.Columns(wks.UsedRange.Columns.Count).Offset(0, 2) Set rng = Intersect(rng, column.EntireRow) 'временная колонка отметок (единичек) val = rng.Value For i = 1 To column.Cells.Count 'отмечаем скрываемые строки единичками If column.Cells(i) = "х" Then val(i, 1) = 1 'здесь по крестику Select Case colA.Cells(i).Interior.Color Case 11389944, 14277081 Case Else val(i, 1) = 1 'и здесь по цвету End Select Next i rng.Value = val
On Error Resume Next rng.SpecialCells(xlCellTypeConstants, 1).EntireRow.Hidden = True '1 = Числа On Error GoTo 0 rng.EntireColumn.Delete 'удаление временной колонки отметок (единичек)
Debug.Print Timer - t End Sub
[/vba] Обратите внимание, что название процедуры изменено: JobTurbo вместо JobTb. Поэтому в главной программе Sub СкрытьБелыхИ_х() нужно будет закомментировать вызов JobTb и добавить вызов JobTurbo в этом фрагменте: [vba]
Код
For Each tb In ActiveSheet.ListObjects 'JobTb tb JobTurbo tb Next
- время выполнения доработанного макроса 3 с. - время выполнения без доработки Excel после 5 минут обработки не отвечает
3 секунды - это много, что ли? Чем не устраивает?
[p.s.]Если много, то вот вариант на 1 секунду ("1С" практически :)):[/p.s.] [vba]
Код
Private Sub JobTurbo(tb As ListObject) Dim wks As Worksheet, rng As Range, colA As Range, column As Range Dim val As Variant, t As Variant, i As Long
t = Timer Set colA = tb.DataBodyRange.Columns(1) 'колонка цвета Set column = tb.DataBodyRange.Columns(14) 'колонка крестиков
Set wks = tb.Parent Set rng = wks.UsedRange.Columns(wks.UsedRange.Columns.Count).Offset(0, 2) Set rng = Intersect(rng, column.EntireRow) 'временная колонка отметок (единичек) val = rng.Value For i = 1 To column.Cells.Count 'отмечаем скрываемые строки единичками If column.Cells(i) = "х" Then val(i, 1) = 1 'здесь по крестику Select Case colA.Cells(i).Interior.Color Case 11389944, 14277081 Case Else val(i, 1) = 1 'и здесь по цвету End Select Next i rng.Value = val
On Error Resume Next rng.SpecialCells(xlCellTypeConstants, 1).EntireRow.Hidden = True '1 = Числа On Error GoTo 0 rng.EntireColumn.Delete 'удаление временной колонки отметок (единичек)
Debug.Print Timer - t End Sub
[/vba] Обратите внимание, что название процедуры изменено: JobTurbo вместо JobTb. Поэтому в главной программе Sub СкрытьБелыхИ_х() нужно будет закомментировать вызов JobTb и добавить вызов JobTurbo в этом фрагменте: [vba]
Код
For Each tb In ActiveSheet.ListObjects 'JobTb tb JobTurbo tb Next
Уважаемый Gustav. Спасибо!! Реально скорость возросла. Перекинул на рабочий файл и, по сравнению с моим кодом, скорость обработки увеличилась существенно. Спасибо!!!
Уважаемый Gustav. Спасибо!! Реально скорость возросла. Перекинул на рабочий файл и, по сравнению с моим кодом, скорость обработки увеличилась существенно. Спасибо!!!graff9540
Будучи раскочегаренным на своей реализации плюс ссылки от RAN поизучал - в общем, выкатываю еще две реализации на базе своей исходной: JobTurbo2 и JobTurbo3.
Что изменил? Во 2-й версии стал читать сразу массив ячеек из колонки N и анализировать его уже в массиве. Обращение к ячейкам в цикле осталось только для получения цвета заливки, причём число таких обращений тоже сократилось - обращаюсь к анализу цвета только если значение ячейки не "крестик" (делю в IFе). Потому что если оно уже и так "крестик" (т.е. надо скрывать строку), то анализ цвета в этом случае будет излишним. Запуски версии 2 в разное время дали разные результаты с довольно заметной погрешностью, но общее ощущение - по сравнению с 1-й версией стало немного пошустрее.
В 3-й версии пошёл дальше. В условиях того, что по условиям задачи надо скрыть почти все строки, оставив отображаться совсем немногие, попробовал сделать наоборот - скрыл вообще все, а затем отобразил те немногие, которые скрывать не надо. Не могу сказать, что стало еще быстрее, чем в версии 2. Скажем так, в тестах обе версии лидировали попеременно в пределах погрешности. Но версию 3, тем не менее, тоже захотелось показать.
[vba]
Код
Private Sub JobTurbo2(tb As ListObject) Dim wks As Worksheet, rng As Range, colA As Range, column As Range Dim val As Variant, t As Variant, valCol As Variant, i As Long, iMax As Long
t = Timer Set colA = tb.DataBodyRange.Columns(1) 'колонка цвета Set column = tb.DataBodyRange.Columns(14) 'колонка крестиков
Set wks = tb.Parent Set rng = wks.UsedRange.Columns(wks.UsedRange.Columns.Count).Offset(0, 2) Set rng = Intersect(rng, column.EntireRow) 'временная колонка отметок (единичек) val = rng.Value valCol = column.Value iMax = column.Cells.Count For i = 1 To iMax 'отмечаем скрываемые строки единичками If valCol(i, 1) = "х" Then val(i, 1) = 1 'здесь по крестику Else Select Case colA.Cells(i).Interior.Color Case 11389944, 14277081 Case Else val(i, 1) = 1 'и здесь по цвету End Select End If Next i rng.Value = val
On Error Resume Next rng.SpecialCells(xlCellTypeConstants, xlNumbers).EntireRow.Hidden = True On Error GoTo 0 rng.EntireColumn.Delete 'удаление временной колонки отметок (единичек)
Debug.Print Timer - t End Sub
Private Sub JobTurbo3(tb As ListObject) Dim wks As Worksheet, rng As Range, colA As Range, column As Range Dim val As Variant, t As Variant, valCol As Variant, i As Long, iMax As Long
t = Timer Set colA = tb.DataBodyRange.Columns(1) 'колонка цвета Set column = tb.DataBodyRange.Columns(14) 'колонка крестиков
Set wks = tb.Parent Set rng = wks.UsedRange.Columns(wks.UsedRange.Columns.Count).Offset(0, 2) Set rng = Intersect(rng, column.EntireRow) 'временная колонка отметок (единичек) val = rng.Value valCol = column.Value iMax = column.Cells.Count For i = 1 To iMax 'отмечаем скрываемые строки единичками If valCol(i, 1) = "х" Then val(i, 1) = 1 'здесь по крестику Else Select Case colA.Cells(i).Interior.Color Case 11389944, 14277081 Case Else val(i, 1) = 1 'и здесь по цвету End Select End If Next i rng.Value = val
rng.EntireRow.Hidden = True 'сначала скрываем просто ВСЁ сразу On Error Resume Next 'и потом некоторые (меньшую часть) показываем rng.SpecialCells(xlCellTypeBlanks).EntireRow.Hidden = False On Error GoTo 0 rng.EntireColumn.Delete 'удаление временной колонки отметок (единичек)
Debug.Print Timer - t End Sub
[/vba]
И в целом мне понравилась общая идея - в процессе обработки делать вспомогательные вычисления за пределами UsedRange обрабатываемого листа и затем подчищать этот временный материал, восстанавливая исходный UsedRange. Т.е. как будто бы ничего и не было, а результат, тем не менее, имеется. Как-то раньше побаивался колбасить что-то лишнее на "боевом" рабочем листе, и, думаю, я совсем не одинок в числе таких побаивающихся. А тут, как говорится (в фильме "Весна"), "присел, задумался, открыл". Единственным ограничением подхода является условие неиспользования двух крайних правых колонок рабочего листа XFC и XFD (я временно "расширяюсь" вправо через столбец от UsedRange, чтобы при последующем удалении временного столбца никак не "зацепить" форматирование последнего столбца UsedRange - вот какой я деликатный! ).
Будучи раскочегаренным на своей реализации плюс ссылки от RAN поизучал - в общем, выкатываю еще две реализации на базе своей исходной: JobTurbo2 и JobTurbo3.
Что изменил? Во 2-й версии стал читать сразу массив ячеек из колонки N и анализировать его уже в массиве. Обращение к ячейкам в цикле осталось только для получения цвета заливки, причём число таких обращений тоже сократилось - обращаюсь к анализу цвета только если значение ячейки не "крестик" (делю в IFе). Потому что если оно уже и так "крестик" (т.е. надо скрывать строку), то анализ цвета в этом случае будет излишним. Запуски версии 2 в разное время дали разные результаты с довольно заметной погрешностью, но общее ощущение - по сравнению с 1-й версией стало немного пошустрее.
В 3-й версии пошёл дальше. В условиях того, что по условиям задачи надо скрыть почти все строки, оставив отображаться совсем немногие, попробовал сделать наоборот - скрыл вообще все, а затем отобразил те немногие, которые скрывать не надо. Не могу сказать, что стало еще быстрее, чем в версии 2. Скажем так, в тестах обе версии лидировали попеременно в пределах погрешности. Но версию 3, тем не менее, тоже захотелось показать.
[vba]
Код
Private Sub JobTurbo2(tb As ListObject) Dim wks As Worksheet, rng As Range, colA As Range, column As Range Dim val As Variant, t As Variant, valCol As Variant, i As Long, iMax As Long
t = Timer Set colA = tb.DataBodyRange.Columns(1) 'колонка цвета Set column = tb.DataBodyRange.Columns(14) 'колонка крестиков
Set wks = tb.Parent Set rng = wks.UsedRange.Columns(wks.UsedRange.Columns.Count).Offset(0, 2) Set rng = Intersect(rng, column.EntireRow) 'временная колонка отметок (единичек) val = rng.Value valCol = column.Value iMax = column.Cells.Count For i = 1 To iMax 'отмечаем скрываемые строки единичками If valCol(i, 1) = "х" Then val(i, 1) = 1 'здесь по крестику Else Select Case colA.Cells(i).Interior.Color Case 11389944, 14277081 Case Else val(i, 1) = 1 'и здесь по цвету End Select End If Next i rng.Value = val
On Error Resume Next rng.SpecialCells(xlCellTypeConstants, xlNumbers).EntireRow.Hidden = True On Error GoTo 0 rng.EntireColumn.Delete 'удаление временной колонки отметок (единичек)
Debug.Print Timer - t End Sub
Private Sub JobTurbo3(tb As ListObject) Dim wks As Worksheet, rng As Range, colA As Range, column As Range Dim val As Variant, t As Variant, valCol As Variant, i As Long, iMax As Long
t = Timer Set colA = tb.DataBodyRange.Columns(1) 'колонка цвета Set column = tb.DataBodyRange.Columns(14) 'колонка крестиков
Set wks = tb.Parent Set rng = wks.UsedRange.Columns(wks.UsedRange.Columns.Count).Offset(0, 2) Set rng = Intersect(rng, column.EntireRow) 'временная колонка отметок (единичек) val = rng.Value valCol = column.Value iMax = column.Cells.Count For i = 1 To iMax 'отмечаем скрываемые строки единичками If valCol(i, 1) = "х" Then val(i, 1) = 1 'здесь по крестику Else Select Case colA.Cells(i).Interior.Color Case 11389944, 14277081 Case Else val(i, 1) = 1 'и здесь по цвету End Select End If Next i rng.Value = val
rng.EntireRow.Hidden = True 'сначала скрываем просто ВСЁ сразу On Error Resume Next 'и потом некоторые (меньшую часть) показываем rng.SpecialCells(xlCellTypeBlanks).EntireRow.Hidden = False On Error GoTo 0 rng.EntireColumn.Delete 'удаление временной колонки отметок (единичек)
Debug.Print Timer - t End Sub
[/vba]
И в целом мне понравилась общая идея - в процессе обработки делать вспомогательные вычисления за пределами UsedRange обрабатываемого листа и затем подчищать этот временный материал, восстанавливая исходный UsedRange. Т.е. как будто бы ничего и не было, а результат, тем не менее, имеется. Как-то раньше побаивался колбасить что-то лишнее на "боевом" рабочем листе, и, думаю, я совсем не одинок в числе таких побаивающихся. А тут, как говорится (в фильме "Весна"), "присел, задумался, открыл". Единственным ограничением подхода является условие неиспользования двух крайних правых колонок рабочего листа XFC и XFD (я временно "расширяюсь" вправо через столбец от UsedRange, чтобы при последующем удалении временного столбца никак не "зацепить" форматирование последнего столбца UsedRange - вот какой я деликатный! ).Gustav