У меня есть такая электронная таблица:
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.