Почему мой VBA UDF для подсчета не работает? - PullRequest
0 голосов
/ 04 июля 2019

Я пытался создать в VBA пользовательскую функцию, которая выполняет подсчет уникальных значений в диапазоне; поэтому я использую метод Excel-функции в качестве основы.

Функция Excel будет выглядеть примерно так:

{= SUM(1/COUNTIF(range,range))}   

Итак, моя попытка воспроизвести это в VBA выглядит следующим образом:

Public Function f_COUNTDISTINCT(rng_range As Range)
With Application.WorksheetFunction
    f_COUNTDISTINCT = .Sum(1 / .CountIf(rng_range, rng_range))
End With
End Function

У меня нет успеха! Я подозреваю, что это потому, что я должен сказать VBA сделать эквивалент формулы массива, но я не уверен, как. Я пробовал использовать квадратные скобки в разных конфигурациях, но безрезультатно.

Как мне это сделать?

NB: я понимаю, что есть более элегантные способы сделать это, используя другой метод, например, здесь https://excelchamps.com/blog/count-unique-values-excel/#6, однако я хотел бы изучить технику, с помощью которой я мог бы сделать метод, который я использую Работа. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 04 июля 2019

Как уже упоминалось @SJR, вы можете использовать метод Evaluate ...

Public Function f_COUNTDISTINCT(rng_range As Range)
    With rng_range
        f_COUNTDISTINCT = Evaluate("SUM(1/COUNTIF(" & .Address(External:=True) & ", " & .Address(External:=True) & "))")
    End With
End Function

Обратите внимание, что в этом примере .Address был настроен на возврат внешней ссылки. Это позволит вам ввести формулу на листе, отличном от того, который содержит данные. Однако, если ваш диапазон включает пустые / пустые ячейки, функция вернет ошибку #DIV/0!. Чтобы исключить пустые / пустые ячейки, попробуйте следующее ...

Public Function f_COUNTDISTINCT(rng_range As Range)
    With rng_range
        f_COUNTDISTINCT = Evaluate("SUMPRODUCT((" & .Address(External:=True) & "<>"""")/COUNTIF(" & .Address(External:=True) & "," & .Address(External:=True) & "&""""))")
    End With
End Function
0 голосов
/ 04 июля 2019

Не уверен, что вы можете сделать это таким образом.Альтернативой является использование Evaluate:

Public Function f_COUNTDISTINCT(rng_range As Range)

f_COUNTDISTINCT = Evaluate("Sum(1 / CountIf(" & rng_range.Address & "," & rng_range.Address & "))")

End Function
...