Добрый день! помогите пожалуйста исправить макрос, делает вот что:
на листе есть ячейки в которых при определённых условиях формулой пишется "скрыть". Макрос перебирает все строки в рабочем диапазоне и проверяет их на скрытость:
Скрытый текст
------------ смотрит строку: если строка НЕ скрыта смотрит ЕСТЬ ли в ней ячейка с "скрыть" если в строке ЕСТЬ ячейка с "скрыть", то добавляет эту строку в диапазон для дальнейшего скрытия если в строке НЕТ ячейки с "скрыть", то идём дальше если строка СКРЫТА смотрит есть ли в ней ячейка с "скрыть" если в строке НЕТ ячейки с "скрыть", то добавляет эту строку в диапазон для дальнейшего РАСкрытия если в строке ЕСТЬ ячейка с "скрыть", то идём дальше смотрит все остальные строки скрывает накопленный диапазон со строками подлежащими скрытию раскрывает накопленный диапазон со строками подлежащими раскрытию ------------
макрос неправильно ищет (или не ищет вообще) в скрытых строках заранее спасибо за помощь!
Код
Sub hide_unhide()
Dim ra As Range, unhidera As Range, hidera As Range
Application.ScreenUpdating = False
ТекстДляСкрытия = "скрыть"
For Each ra In ActiveSheet.UsedRange.Rows
'MsgBox ra.Row
If ra.EntireRow.Hidden = False Then 'если НЕскрыто, а "скрыть" ЕСТЬ
If Not ra.Find(ТекстДляСкрытия, , xlValues, xlPart) Is Nothing Then
If hidera Is Nothing Then Set hidera = ra Else Set hidera = Union(hidera, ra)
End If
Else 'если СКРЫТО, а "скрыть" НЕТ
If ra.Find(ТекстДляСкрытия, , LookIn:=xlFormulas) Is Nothing Then
If unhidera Is Nothing Then Set unhidera = ra Else Set unhidera = Union(unhidera, ra)
End If
End If
Next
If Not hidera Is Nothing Then hidera.EntireRow.Hidden = True
If Not unhidera Is Nothing Then unhidera.EntireRow.Hidden = False
Application.ScreenUpdating = True
ActiveSheet.Calculate
End Sub
Sub hide_unhide1()
Application.ScreenUpdating = False
ActiveSheet.Range("E1:E10").EntireRow.Hidden = False
For i = 1 To 10
If Cells(i, 4) = "скрыть" Then
Cells(i, 4).EntireRow.Hidden = True
End If
Next
Application.ScreenUpdating = True
ActiveSheet.Calculate
End Sub
У меня этот макрос повешен на активацию листа. На листе очень много формул, факторы скрытия/раскрытия строк постоянно меняются. перераскрывать каждый раз все строки листа очень долго. Предложенный мной алгоритм (как мне кажется) должен работать значительно быстрее. Проблема одна - поиск "скрыть" в скрытой строке. Причем нужно чтобы поиск был по значениям ячеек, а не по тексту в них, т.к. При нахождении "скрыть" в условии формулы ячейки будет ошибочное срабатывание макроса.
перераскрывать каждый раз все строки листа очень долго
Тогда так.
Код
Sub hide_unhide1()
Application.ScreenUpdating = False
For i = 1 To 10
If Cells(i, 4) = "скрыть" Then Cells(i, 4).EntireRow.Hidden = True
If Cells(i, 4) <> "скрыть" Then Cells(i, 4).EntireRow.Hidden = False
Next
Application.ScreenUpdating = True
ActiveSheet.Calculate
End Sub
Цитата
Причем нужно чтобы поиск был по значениям ячеек, а не по тексту в них,
gling, Максим правильно сказал, - если по одной строке скрывать / отображать, это очень медленно работает. И отключении перерисовки экрана особо не помогает (ускоряет, но несильно) Потому этот макрос сначала ищет все подходящие строки, а потом разом скрывает \ отображает их.
Максим, учтите, что Union может переполниться, если строк очень много. там какое-то ограничение на количество несмежных диапазонов, около 1000) т.е. при количестве строк в таблице порядка 3-4 тыс, уже могут начаться проблемы
По вашему вопросу: я бы сделал отдельную функцию для поиска, в которой считывал бы строку в массив, и в массиве перебором бы искал нужное значение
примерно так: (в Usedrange должно быть БОЛЕЕ одного столбца - минимум два)
Код
Function check(ByRef ra As Range) As Boolean
On Error Resume Next: arr = ra.Value
For i = LBound(arr, 2) To UBound(arr, 2)
If arr(1, i) = "скрыть" Then check = True: Exit Function
Next i
End Function
и потом бы заменил строку
Код
If Not ra.Find(ТекстДляСкрытия, , xlValues, xlPart) Is Nothing Then
Протестировал - получилось скрыть 45 строк, дальше ошибка Ограничение длинны строки: 255 символов (тут об этом написано) Видимо альтернативы Union по скорости нет Простите за офф
gling пишет: Немного не понятно, что в макросе не так?
в предложенном Вами макросе всё работает применительно к примеру. Я возможно не совсем правильно объяснил в своём втором посте, и что потом пояснил Игорь, - поочерёдное скрытие/раскрытие происходит очень долго применительно к листу с сотнями или тысячами строк, к тому же перегруженных формулами.
спасибо за ссылку посмотрю обязательно, возможно его действительно можно применить в моём случае
SAS888, Ваш вариант работает корректно,но он, если я правильно понял, совсем заточен под мой пример. В желаемом мной макросе не должно быть привязок к конкретным ячейкам и диапазонам - только рабочий диапазон. Мне не хватило знаний переделать его под ActiveSheet.UsedRange. И ещё если повесить его на событие Worksheet_Change, то эксель намертво вешается.
Цитата
gling пишет: А так... Строку с фильтром можно скрыть.
предложенный вами макрос у меня работает не корректно. Вообще я допускаю что возможно решение моего вопроса с помощью фильтров (или расширенных фильтров), но я как-то уж решил идти по пути скрытия по условию и не хочу бросать этот вариант на полпути, но обещаю поразбираться с таким вариантом решения
Игорь, Ваш вариант мне полностью подошёл! Действительно представленный мной макрос вырос из того на который вы сослались и я долгое время пользовался именно им, но сейчас мне подумалось что для моих целей его можно было бы оптимизировать. С Вашей помощью вышло вот что:
Код
Sub hide_unhide()
Dim ra As Range, unhidera As Range, hidera As Range
Application.ScreenUpdating = False
ТекстДляСкрытия = "скрыть"
For Each ra In ActiveSheet.UsedRange.Rows
If check(ra) Then 'если "скрыть" нашлось и строка РАСкрыта
If ra.EntireRow.Hidden = False Then If hidera Is Nothing Then Set hidera = ra Else Set hidera = Union(hidera, ra)
Else 'если "скрыть" не нашлось и строка скрыта
If ra.EntireRow.Hidden = True Then If unhidera Is Nothing Then Set unhidera = ra Else Set unhidera = Union(unhidera, ra)
End If
Next
If Not hidera Is Nothing Then hidera.EntireRow.Hidden = True
If Not unhidera Is Nothing Then unhidera.EntireRow.Hidden = False
Application.ScreenUpdating = True
End Sub
Function check(ByRef ra As Range) As Boolean
On Error Resume Next: arr = ra.Value
For i = LBound(arr, 2) To UBound(arr, 2)
If arr(1, i) = "скрыть" Then check = True: Exit Function
Next i
End Function
нашёл ошибку - при наличии в ячейке ошибки, отрабатывает строку "под скрытие". вроде исправил, но чувствую что как-то тупо...
Код
Function check(ByRef ra As Range) As Boolean
arr = ra.Value
For i = LBound(arr, 2) To UBound(arr, 2)
If IsError(arr(1, i)) Then GoTo дальше
If arr(1, i) = "скрыть" Then check = True: Exit Function
дальше:
Next i
End Function