Возврат константы массива Excel из пользовательской функции VBA - PullRequest
2 голосов
/ 16 мая 2019

У меня есть такая электронная таблица:

A1: APPLE
A2: BANANA
A3: ORANGE
A4: APPLE
A5: BANANA
A6: ORANGE

(повторяется до A20)

Таким образом, эта формула будет подсчитывать все экземпляры "APPLE":

=COUNTIF(A1:A20, "APPLE")

И эта формула делает то же самое, за исключением несмежного диапазона:

=SUM(COUNTIF(INDIRECT({"A1:A6", "A8:A20"}), "APPLE"))

INDIRECT функция принимает константу массива сдиапазоны, определенные как строки.Обратите внимание на фигурные скобки и кавычки вокруг каждого диапазона.(Это основано на методике, описанной здесь .)

Однако, если я определю функцию VBA, которая возвращает массив строк и передает , в INDIRECT,кажется, что соблюдается только первый диапазон.

Это моя функция VBA:

Function TestFn() As Variant
    TestFn = Array("A1:A6", "A8:A20")
End Function

Это моя формула:

=SUM(COUNTIF(INDIRECT(TestFn()), "APPLE"))

Если я использую Excel "Кнопка «Оценить формулу», я вижу, что TestFn() разрешается в одну строку «B1: B6».Однако, если я использую отладчик VBA, я вижу, что обе строки находятся там.

Expression      Value       Type
TestFn                      Variant/Variant(0 to 1)
 - TestFn(0)    "B1:B6"     Variant/String
 - TestFn(1)    "B8:B20"    Variant/String

Как я могу вернуть массив строк из функции Excel VBA, который можно передать в INDIRECT вТаким же образом?

Я думаю, это сводится к следующему: какой внутренний объект создается с помощью фигурных скобок при построении формулы без VBA, и могу ли я создать этот же внутренний объект из VBA?


Я также попытался вернуть массив строк, а не вариант, содержащий массив строк.

Function TestFn() As String()
    TestFn = Split("B1:B6,B8:B20", ",")
End Function

Это типы в отладчике:

Expression      Value       Type
TestFn                      String(0 to 1)
 - TestFn(0)    "B1:B6"     String
 - TestFn(1)    "B8:B20"    String

Норезультат тот же.Я думаю, что мне нужно использовать какой-то тип контейнера, но я не уверен, что использовать или как выяснить, что использовать.


Мне на самом деле не нужно использовать SUM ... INDIRECT хак, если есть лучший способ, и я был бы рад использовать формулу массива, если это уместно.

Если бы я мог позволить моей функции возвращать диапазоны напрямую, а не строки, представляющиедиапазоны, это было бы даже лучше, чем мой текущий подход.

Если бы я мог настроить формулу массива примерно так (не обязательно должно быть так):

{=COUNTIF(TestFn(), "APPLE")}

Тогда пусть мой UDF будет выглядеть примерно так:

Function TestFn() As Range()
    TestFn = Array(Range("A1:A6"), Range("A8:A20"))
End Function

Или, может быть, что-то вроде этого:

Function TestFn() As Range
    TestFn = Union(Range("A1:A6"), Range("A8:A20"))
End Function

Это будет соответствовать моим потребностям.

Ключ в том, чтоЯ просто хочу, чтобы мой VBA только определял, над какими ячейками оперируют, а не с какой операцией, и я хочу иметь дело с несмежными диапазонами.Я хочу, чтобы фактические операции были определены в формулах Excel, потому что они будут изменены людьми, которые не должны понимать, как читать и писать код VBA.(Черт, я тоже не хочу больше смотреть на код VBA.) В этом случае я использую COUNTIF, но моя функция VBA будет использоваться и с другими функциями формулы Excel.

1 Ответ

3 голосов
/ 16 мая 2019

Конечно, кто-то может объяснить это лучше, но позвольте мне попробовать.Вы использовали оба:

=SUM(COUNTIF(INDIRECT({"A1:A6","A8:A20"}), "APPLE"))

И ...

=SUM(COUNTIF(INDIRECT(TestFn()), "APPLE"))

О первой формуле;вы в основном использовали функции INDIRECT() для перевода текстовых строк в реальный диапазон.На самом деле это очень хорошее использование INDIRECT() Я должен сказать:).

Но, используя фигурные скобки, которые вы сказали Excel, что это больше, чем просто одна строка, вы накормили функцию несколькими данными,массив!Как правило, массив в Excel представляет собой простой набор данных.Эти данные могут быть текстом, числами или обоими.Вы использовали текст.

Во второй формуле вы задали формулу массивом через UDF, но в ней отсутствуют фигурные скобки.Excel не знает, что вы хотите сравнить несколько диапазонов, и будет оценивать только первый элемент в вашем массиве.

Однако, используя Ctrl Shift Enter вы говорите Excel, что хотите добавить формулу в массив, представляющий собой набор данных / диапазонов для сравнения.

Итак:

{=SUM(COUNTIF(INDIRECT(TestFn()), "APPLE"))}

Будет работать:)

Я уверен, что кто-то еще лучше объяснит;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...