ОК, нет никакого способа сделать именно то, что вы хотите.Вы не можете использовать в формуле ничего, кроме синтаксиса Excel, поэтому такие вещи, как 'A1 = 1 до 9', просто невозможны.
Вы могли бы написать довольно сложную подпрограмму VBA, которая потребовалаСтроки или что-то в этом роде и проанализировали их, но на самом деле это сводится к разработке и реализации полного небольшого языка.И ваш «код» не будет хорошо работать с Excel.Например, если вы вызвали что-то вроде
=cases("{A1="""",""there is nothing""},{else,A1}")
(обратите внимание на экранированные кавычки), Excel не обновит вашу ссылку A1, когда она будет перемещена или формула скопирована.Итак, давайте отбросим весь вариант «синтаксиса».
Однако, оказывается, вы можете получить большую часть поведения, которое, я думаю, вам действительно нужно с обычными формулами Excel плюс один крошечный VBA UDF.Сначала UDF:
Public Function arr(ParamArray args())
arr = args
End Function
Это позволяет нам создать массив из набора аргументов.Поскольку аргументы могут быть выражениями, а не просто константами, мы можем вызвать их из формулы, подобной этой:
=arr(A1=42, A1=99)
и получить обратно массив логических значений.
С этим небольшим UDF,Теперь вы можете использовать обычные формулы для «выбора дел».Они бы выглядели так:
=CHOOSE(MATCH(TRUE, arr(A1>5, A1<5, A1=5), 0), "gt 5", "lt 5", "eq 5")
Что происходит, так это то, что 'arr' возвращает логический массив, 'MATCH' находит позицию первого ИСТИНА, а 'CHOOSE' возвращает соответствующий «регистр».
Вы можете эмулировать предложение "else", заключив все это в 'IFERROR':
=IFERROR(CHOOSE(MATCH(TRUE, arr(A1>5, A1<5), 0), "gt 5", "lt 5"), "eq 5")
Если это слишком многословно для вас, вы всегда можете написать другой UBA VBA, который быпоместите MATCH, CHOOSE и т. д. внутрь и назовите его так:
=cases(arr(A1>5, A1<5, A1=5), "gt 5", "lt 5", "eq 5")
Это не далеко от предложенного вами синтаксиса и намного, намного проще.
РЕДАКТИРОВАТЬ:
Я вижу, что вы уже придумали (хорошее) решение, которое ближе к тому, что вы действительно хотите, но я подумал, что все равно добавлю это, так как мое утверждение выше о том, чтобы сделать MATCH, CHOOSE и т. Д. ВнутриUDF сделал его проще, чем он есть на самом деле.
Итак, вот UDF для "случаев":
Public Function cases(caseCondResults, ParamArray caseValues())
On Error GoTo EH
Dim resOfMatch
resOfMatch = Application.Match(True, caseCondResults, 0)
If IsError(resOfMatch) Then
cases = resOfMatch
Else
Call assign(cases, caseValues(LBound(caseValues) + resOfMatch - 1))
End If
Exit Function
EH:
cases = CVErr(xlValue)
End Function
Он использует небольшую вспомогательную подпрограмму 'assign':
Public Sub assign(ByRef lhs, rhs)
If IsObject(rhs) Then
Set lhs = rhs
Else
lhs = rhs
End If
End Sub
Процедура 'назначить' просто облегчает работу с тем, что пользователи могутвызывать UDF со значениями или ссылками на диапазон.Поскольку мы хотим, чтобы наша UDF «дела» работала так же, как «CHOOSE» в Excel, мы хотели бы при необходимости возвращать обратные ссылки.
По сути, в новой UDF «дела» мы выполняем часть «выбор»мы сами, индексируя в массив параметров значения регистра.Я включил обработчик ошибок, поэтому базовые вещи, такие как несоответствие между результатами условий случая и значениями случая, приведут к возвращаемому значению #VALUE !.Вы, вероятно, добавите больше проверок в реальную функцию, например, убедитесь, что результаты условия были логическими, и т. Д.
Я рад, что вы достигли даже лучшего решения для себя!Это было интересно.
БОЛЬШЕ О 'назначить':
В ответ на ваш комментарий, здесь больше о том, почему это является частью моего ответа.VBA использует другой синтаксис для назначения объекта переменной, чем для назначения простого значения.Посмотрите на справку VBA или посмотрите на этот вопрос stackoverflow и другие подобные ему: Что на самом деле делает ключевое слово Set в VBA?
Это важно, потому что, когда вы вызываете функцию VBA из Excelформула, параметры могут быть объектами типа Range, в дополнение к числам, строкам, логическим значениям, ошибкам и массивам.(См. Может ли пользовательская функция Excel VBA, вызванная из рабочего листа, когда-либо передаваться экземпляру какого-либо класса объектной модели Excel VBA, кроме 'Range'? * )
Ссылки на диапазоны - это то, что вы описываете, используя синтаксис Excel, такой как A1: Q42.Когда вы передаете его в Excel UDF в качестве параметра, он отображается как объект Range.Если вы хотите вернуть объект Range из UDF, вы должны сделать это явно с ключевым словом VBA 'Set'.Если вы не используете «Set», Excel вместо этого примет значение , содержащееся в Range, и вернет его.В большинстве случаев это не имеет значения, но иногда вам нужен фактический диапазон, например, когда у вас есть именованная формула, которая должна соответствовать диапазону, поскольку она используется в качестве источника для списка проверки.