Private Sub Worksheet_Calculate()
Application.EnableEvents = False
Me.[E3] = CountOfRows(Me)
Application.EnableEvents = True
End Sub
События в Excel
событием для листа не являются (по крайней
мере - процедура Worksheet_Change() не
срабатывает). Тем не менее при закрытии
книги, система понимает, что с данными на
странице были какие-то манипуляции, выдавая
вопрос типа "сохранить изменения али нет".
Так вот как отловить данное событие (смену
условия фильтрации) на уровне VBA??
После изменения критерия автофильтра выполняется событие Worksheet_Calculate()(см.
отслеживать смену значения критерия фильтра,
достаточно отловить с помощью данной функции
сам факт подобной попытки - все остальное сделает
пользовательская процедура...
Если Вам необходимо узнать когда произошёл пересчёт формул, то отслеживать изменение критерия необязательно, если же нужен "контроль" над фильтром, то всё-таки нужно.
событие смены условия фильтрации:
Private Sub Worksheet_Calculate()
Range("E3").Value = SpecDataView
End Sub
Как видим никаких параметров у процедуры нет, а значит
вызов пользовательской функции SpecDataView происходит
при проверке необходимости пересчета формул в каждой
(надеюсь только задействованной) ячейке листа. В результате
сильно заметна задержка выхода в режим готовности после
любого изменения на листе. На моем компе с процем на 2,5ГГц
задержка доходит до 1,5-2 секунд при размере таблицы всего
в 100 строк (задействованных пока). Если строк будет больше,
то и задержка видимо будет расти...
Я так понимаю, с этим придется мириться, ибо в самой функции
SpecDataView, на мой взгляд, особых наворотов нет:
Function SpecDataView() As Variant
Dim xW As Worksheet, xT As Range, nT As Integer, nQ As Integer
Set xW = Worksheets("Реестр")
nQ = 0
With xW
If .FilterMode Then
cP = xW.AutoFilter.Range.Address
Set xT = .Range("G7")
Do While xT.Row < .UsedRange.Rows.Count - 6
If Not .Rows(xT.Row).Hidden _
And xT.Interior.ColorIndex <> xlNone Then
nQ = nQ + 1
End If
Set xT = xT.Offset(1, 0)
Loop
SpecDataView = "из них срочно:" + Str(nQ)
Else
SpecDataView = ""
End If
End With
End Function
Код:
Стандартный модуль
Код:
Function CountOfRows$(iWSource As Worksheet) ' As String
With iWSource
If .FilterMode = True Then
Dim iCell As Range
For Each iCell In .Range(.[G7], .[G65536].End(xlUp))
If iCell.Interior.ColorIndex <> xlNone And _
Not iCell.Rows.Hidden Then iCount& = iCount& + 1
Next
CountOfRows$ = "Из них срочно : " & iCount&
End If
End With
End Function
With iWSource
If .FilterMode = True Then
Dim iCell As Range
For Each iCell In .Range(.[G7], .[G65536].End(xlUp))
If iCell.Interior.ColorIndex <> xlNone And _
Not iCell.Rows.Hidden Then iCount& = iCount& + 1
Next
CountOfRows$ = "Из них срочно : " & iCount&
End If
End With
End Function
Хотя и не понял за счет чего. Манипуляции со свойством EnableEvents
(про него в справке толком ничего не сказано), или простой отказ от
команды Set xT = xt.Offset(1, 0)
Ваш пример я слегка модифицировал:
Function SpecDataView(xW As Worksheet) As Variant
Dim xT As Range, nT As Integer, nQ As Integer
nQ = 0
With xW
If .FilterMode Then
cP = Replace(.AutoFilter.Range.Address, "A", "G")
' автофильтр устанавливается на колонки от A до G
' смена условия фильтра идет в колонке A, там работает
' другая функция в паре с функцией листа SubTotal() или
' ПРОМЕЖУТОЧНЫЕ.ИТОГИ() если угодно,
' а в колонке G идет дополнительный подсчет видимых строк
' ибо SubTotal() там уже не срабатывает по причине того, что
' у функции Worksheet_Change() только один параметр...
For Each xT In .Range(cP)
If xT.Interior.ColorIndex <> xlNone And Not xT.Rows.Hidden Then
nQ = nQ + 1
End If
Next
SpecDataView = "из них срочно: " + Str(nQ)
Else
SpecDataView = ""
End If
End With
End Function