Цель: подсчитать количество уникальных значений в ячейках, отобранных с помощью фильтра (или нескольких). Пример во вложении, поиск уникальных значений осуществляется в столбце "В". Для подсчёта используется следующая формула: =СУММПРОИЗВ((ЧАСТОТА(ПОИСКПОЗ(B2:B10&"";B2:B10&"";0);ПОИСКПОЗ(B2:B10&"";B2:B10&"";0))>0)*ПРОМЕЖУТОЧНЫЕ.ИТОГИ(3;СМЕЩ(A2;СТРОКА(A2:A11)-СТРОКА(A2);))) Работает хорошо, за исключением одной детали: при отдельных условиях фильтрации в столбце "D" выдаёт ложный результат. Во вложенном файле попробуйте в этом столбце отфильтровать ячейки по критерию "сдан" - результат будет 2 (вместо 3). Насколько понял, эта ошибка связана с тем, что формула работает следующим образом: - ячейки просматриваются сверху вниз - в качестве уникального учитывается первое найденное среди повторяющихся значений - если ячейка, содержащая такое значение, скрывается в результате фильтрации, формула выдаёт 0 - в том числе, и в случаях, когда остаются видимыми остальные повторяющиеся значения На примере из вложения: - значение "5А" встречается в ячейках "В3", "В7", "В10" - в качестве уникального учитывается значение в ячейке "В3" - если в столбце "D" фильтровать по критерию "не сдан", формула выдаст верный результат, т. к. ячейка "В3" осталась видимой - если в столбце "D" фильтровать по критерию "сдан", формула выдаст неверный результат, т. к. ячейка "В3" перестала быть видимой
Можно ли как-то исправить недостаток имеющейся формулы? Если да, что именно следует изменить. Если нет, подскажите, пожалуйста, какую формулу можно использовать для решения вопроса..
Не уверен, что можно настроить зависимость формулы от фильтра. Я бы использовал UDF (пользовательская функция)
Код
Function СЧЁТУНИКЕСЛИ(rng1 As Range, rng2 As Range, kr As Variant) As Double
'аргументы:
'rng1 - диапазон отбора уникальных значений, обязательный
'rng2 - диапазон условий, обязательный
'kr - условие (критерий), обязательный
СЧЁТУНИКЕСЛИ = 0
On Error Resume Next
With New Collection
For Each cl In rng1
If rng2.Parent.Cells(cl.Row, rng2.Column) Like kr Then
.Add cl, CStr(cl)
If Err = 0 Then
СЧЁТУНИКЕСЛИ = СЧЁТУНИКЕСЛИ + 1
Else
Err.Clear
End If
End If
Next
End With
End Function
Sanja, огромное спасибо за совет и код. Но, возможно, я недостаточно явно выразил цель в первом посте: необходим подсчёт уникальных значений в видимом с учётом фильтрации диапазоне, с фильтрацией по любому количеству критериев. Но предложенный Вами код считает по всему диапазону, без учёта фильтрации, по заранее заданному критерию. Нашёл вариант, который, судя по описанию, выглядит подходящим. У функции два аргумента - "ДИАПАЗОН" и "ТолькоВидимые". Первый задаёт диапазон отбора уникальных значений, второй принимает значения "0" или "1" и, соответственно, учитывает или не учитывает скрытые ячейки диапазона. Выглядит это так: Но работает не совсем так, как сказано в описании - у функции нет аргумента "ТолькоВидимые". Или я что-то делаю не так, или автор из коммерческих соображений опубликовал только часть кода. Посмотрите, пожалуйста, и подтвердите/опровергните мою догадку. P.S.: указание на работоспособность кода видел в этом сообщении,
Отфильтрованный диапазон - это просто скрытые строки (Height = 0). В приведённом Вами макросе производится проверка на пустоту, а проверка на отфильтрованность - нет. Вам надо использовать SpecialCells вместе с Areas (так как могут быть несвязанные диапазоны).
Function СЧЁТУНИКЕСЛИ(rng1 As Range, rng2 As Range, kr As Variant, Optional vis As Boolean = False) As Double
'аргументы:
'rng1 - диапазон отбора уникальных значений, обязательный
'rng2 - диапазон условий, обязательный
'kr - условие (критерий), обязательный
'vis - отбирать только в видимых ячейках, не обязательный, 0(False) - во всех (по умолчанию), 1(True) - только в видимых
СЧЁТУНИКЕСЛИ = 0
If vis Then Set rng1 = rng1.SpecialCells(xlCellTypeVisible)
On Error Resume Next
With New Collection
For Each cl In rng1.Cells
If rng2.Parent.Cells(cl.Row, rng2.Column) Like kr Then
.Add cl, CStr(cl)
If Err = 0 Then
СЧЁТУНИКЕСЛИ = СЧЁТУНИКЕСЛИ + 1
Else
Err.Clear
End If
End If
Next
End With
End Function
Приложите более информативный файл, с большим количеством данных. Или я чего-то не понимаю. Вам нужно количество уникальных НЕ зависимо от условия? Потому что
Цитата
Boggy написал: попробуйте в этом столбце отфильтровать ячейки по критерию "сдан" - результат будет 2 (вместо 3)
результат работы моей функции, что до, что после фильтрации равен 3, т.е. она не зависит от фильтра
Согласие есть продукт при полном непротивлении сторон
Function СЧЁТУНИКВИД(rng1 As Range, Optional vsb As Boolean = False) As Double
'аргументы:
'rng1 - диапазон отбора уникальных значений, обязательный
'vsb - отбирать только в видимых ячейках, не обязательный, 0(False) - во всех (по умолчанию), 1(True) - только в видимых
Dim cl As Range
СЧЁТУНИКВИД = 0
On Error Resume Next
With New Collection
For Each cl In rng1
If vsb Then
If cl.Rows.Hidden Then GoTo 1
End If
.Add cl, CStr(cl)
If Err = 0 Then
СЧЁТУНИКВИД = СЧЁТУНИКВИД + 1
Else
Err.Clear
End If
1 Next
End With
End Function
Sanja, нужным результатом был подсчёт количества значений с диапазоне, образованном фильтром/фильтрами. Да и Вы вроде всё правильно поняли, если судить по формуле - иначе зачем было вводить параметр
Цитата
'vis - отбирать только в видимых ячейках, не обязательный, 0(False) - во всех (по умолчанию), 1(True) - только в видимых
Так или иначе, нашёл подходящее решение, делюсь им. Вот ссылка на автора, от себя добавил одну строку (на игнорирование пустых ячеек). Код:
Код
Function CountUnicalVisible (ByVal RangeArea As Range) As Long
Dim objDict As Variant
Set objDict = CreateObject("Scripting.Dictionary")
For Each TheCell In RangeArea
If Not TheCell.Parent.Rows(TheCell.Row).Hidden And _
Not TheCell.Parent.Columns(TheCell.Column).Hidden And _
Not IsEmpty(TheCell) And _
Not objDict.exists(TheCell.Value) Then _
objDict.Add TheCell.Value, ""
Next
CountUnicalVisible = objDict.Count
objDict = Empty
End Function