ИначеЕсли в коде или ВЫБОР КОГДА в запросе: что выбрать в 1С
Содержание
Во встроенном языке 1С ветвление пишут через Если … Тогда … ИначеЕсли … Иначе … КонецЕсли, а слово КОГДА там не существует. «Когда» есть только в языке запросов и в выражениях СКД: ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ. Поэтому выбор между «Иначе» и «Когда» — это по сути выбор места: условие считается в модуле или прямо в запросе к базе.
Правило простое. Значение нужно для каждой строки выборки — ставьте ВЫБОР в запрос. Нужно решить, что делать программе дальше (вызвать процедуру, показать сообщение, прервать запись) — это Если в коде.
Два языка, две конструкции: базовый синтаксис
Условие во встроенном языке
Полная форма оператора выглядит так:
Если Сумма >= 1000000 Тогда
Категория = "Крупная";
ИначеЕсли Сумма >= 100000 Тогда
Категория = "Средняя";
Иначе
Категория = "Мелкая";
КонецЕсли;
Правила, которые проверяет синтаксический контроль:
- ✅
ИначеЕслипишется одним словом и может повторяться сколько угодно раз; - ✅
Иначе— не больше одного раза и только последним блоком; - ✅ каждое
Еслизакрывается своимКонецЕсли; - ✅ ветви проверяются сверху вниз, выполняется первая с истинным условием, остальные пропускаются.
Английские аналоги: If … Then … ElsIf … Else … EndIf. В одном модуле можно смешивать, но читать такой код тяжело — выберите один вариант.
Для коротких случаев есть тернарный оператор ?(Условие, ЗначениеЕслиИстина, ЗначениеЕслиЛожь). Он возвращает значение, а не выполняет действия:
ТекстСальдо = ?(Остаток > 0, "Дебетовое", "Кредитовое");
Условие в языке запросов
В запросе ветвление — это выражение, которое возвращает значение для поля:
ВЫБОР
КОГДА Реализация.СуммаДокумента >= 1000000 ТОГДА "Крупная"
КОГДА Реализация.СуммаДокумента >= 100000 ТОГДА "Средняя"
ИНАЧЕ "Мелкая"
КОНЕЦ КАК Категория
Здесь КОГДА играет роль ИначеЕсли, ИНАЧЕ — роль Иначе, а КОНЕЦ закрывает конструкцию. По-английски: CASE WHEN … THEN … ELSE … END. Порядок тот же: срабатывает первое истинное КОГДА.
| Что нужно | Встроенный язык | Язык запросов |
|---|---|---|
| Первое условие | Если … Тогда | ВЫБОР КОГДА … ТОГДА |
| Следующее условие | ИначеЕсли … Тогда | КОГДА … ТОГДА |
| Всё остальное | Иначе | ИНАЧЕ |
| Закрытие | КонецЕсли; | КОНЕЦ |
| Короткая форма | ?(…, …, …) | нет, только ВЫБОР |
| Без ветки «иначе» | ничего не выполняется | результат NULL |
Когда нужен «КОГДА», а когда «ИначеЕсли»
Решение принимают по трём вопросам.
- Где живут данные? Если значения лежат в таблицах базы и вы их всё равно выбираете запросом, классификацию делайте там же. Тянуть 50 000 строк в код, чтобы потом в цикле проставить каждой категорию через
Если, — лишняя работа. - Что получается в результате?
ВЫБОРдаёт только значение поля. Записать документ, вывести сообщение, вызвать функцию модуля из запроса нельзя. Для действий нуженЕсли. - Нужна ли группировка или отбор по результату? Категорию, посчитанную в запросе, можно сразу сгруппировать и просуммировать. В коде для этого придётся заводить таблицу значений и сворачивать её.
💡 Хорошее разделение: запрос раскладывает строки по категориям через ВЫБОР, код по уже готовой категории решает, что делать, через Если.
Ошибки в условиях с Иначе и Когда и как их избежать
«Иначе Если» в два слова
Конструкция Иначе Если формально допустима, но это уже не продолжение цепочки, а новый вложенный оператор. Ему нужен свой КонецЕсли:
Если А > 0 Тогда
Результат = 1;
Иначе Если А < 0 Тогда // открыт второй оператор Если
Результат = -1;
КонецЕсли;
КонецЕсли; // без этой строки модуль не пройдёт синтаксический контроль
Пишите ИначеЕсли слитно — и лишние КонецЕсли не понадобятся.
Слово «КОГДА» или «ВЫБОР» в модуле
Ещё одна частая путаница — перенести конструкцию из запроса в код. Во встроенном языке нет оператора множественного выбора вроде switch, и ВЫБОР КОГДА в модуле даст синтаксическую ошибку. Обратная ошибка — ИНАЧЕЕСЛИ или ЕСЛИ внутри текста запроса: конструктор запроса такой текст не примет.
Пропущенный ИНАЧЕ в запросе
Если ни одно КОГДА не сработало, а ветки ИНАЧЕ нет, поле получает NULL. В отчёте это пустая ячейка, а в итогах — строка, выпавшая из группы. Задавайте ИНАЧЕ явно, даже если «других случаев не бывает».
Сравнение с NULL через знак «=»
Условие КОГДА Поле = NULL никогда не будет истинным. Проверяйте КОГДА Поле ЕСТЬ NULL или оборачивайте поле в ЕСТЬNULL(Поле, 0) до сравнения. Это особенно важно после левого соединения, где у части строк справа пусто.
Небулево значение в условии
Если Контрагент Тогда для ссылки не работает
. Платформа выдаст ошибку Преобразование значения к типу Булево не может быть выполнено. Для проверки заполненности используйте Если ЗначениеЗаполнено(Контрагент) Тогда.
Неверный порядок веток
Условия проверяются по порядку, поэтому широкое условие сверху «съедает» узкие:
Если Сумма >= 100000 Тогда // сюда попадёт и 2 000 000
Категория = "Средняя";
ИначеЕсли Сумма >= 1000000 Тогда // эта ветка не выполнится никогда
Категория = "Крупная";
КонецЕсли;
Для диапазонов идите от самого строгого порога к самому мягкому. То же правило действует для КОГДА.
Что быстрее: цепочка ИначеЕсли, Соответствие или ВЫБОР в запросе
Сам оператор Если дешёвый. Тормозит не он, а то, что стоит в условиях и сколько раз всё это выполняется.
В коде:
- ⚡ Цепочка проверяется сверху вниз. Ставьте первыми самые частые случаи: если 90% строк попадают в последнюю ветку из десяти, каждая строка проходит девять лишних сравнений.
- ⚡ Не вызывайте одну и ту же функцию в каждом условии. Вычислите значение один раз в переменную, а потом сравнивайте.
- ⚡ Обращение через точку к реквизиту ссылки (
Договор.Организация) в цикле может читать объект из базы. Получите нужные поля заранее одним запросом. - ⚡ Для длинного списка «код → значение» цепочка из 15–20
ИначеЕслипроигрываетСоответствию: поиск по ключу не перебирает варианты по очереди.
В запросе:
- ⚡
ВЫБОРв списке полей выборки считает СУБД построчно, это дёшево. - ⚡
ВЫБОРв условииГДЕили в условии соединения обычно мешает использовать индекс: СУБД вынуждена вычислить выражение для каждой строки. Перепишите такое условие через обычные сравнения сИ/ИЛИ. - ⚡ Если категория из
ВЫБОРнужна в нескольких местах запроса, посчитайте её во временной таблице и дальше работайте с готовым полем.
| Способ | Когда уместен | Слабое место |
|---|---|---|
Если … ИначеЕсли | 2–7 веток, разная логика в каждой | Длинные цепочки трудно читать и править |
Соответствие | Много пар «ключ → значение» | Не подходит для диапазонов («от 100 до 500») |
?(…) | Одно условие, нужно значение | Вложенные ? быстро становятся нечитаемыми |
ВЫБОР КОГДА | Значение для каждой строки выборки | В ГДЕ и соединениях бьёт по индексам |
Примеры для бухгалтеров и администраторов
Разбить реализации по размеру сделки
Запрос для консоли запросов в Бухгалтерии предприятия 3.0. Он считает, сколько отгрузок попало в каждую группу:
ВЫБРАТЬ
ВЫБОР
КОГДА Реализация.СуммаДокумента >= 1000000 ТОГДА "1. От 1 млн"
КОГДА Реализация.СуммаДокумента >= 100000 ТОГДА "2. От 100 тыс. до 1 млн"
ИНАЧЕ "3. До 100 тыс."
КОНЕЦ КАК Группа,
КОЛИЧЕСТВО(Реализация.Ссылка) КАК Документов,
СУММА(Реализация.СуммаДокумента) КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Проведен
И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
ВЫБОР
КОГДА Реализация.СуммаДокумента >= 1000000 ТОГДА "1. От 1 млн"
КОГДА Реализация.СуммаДокумента >= 100000 ТОГДА "2. От 100 тыс. до 1 млн"
ИНАЧЕ "3. До 100 тыс."
КОНЕЦ
Выражение в СГРУППИРОВАТЬ ПО повторено целиком — так надёжнее, чем ссылаться на псевдоним поля. Цифры в начале названий групп нужны, чтобы при сортировке по алфавиту они шли в нужном порядке.
Запросы на чтение безопасны, но любые обработки, которые меняют данные, запускайте сначала в копии базы.
Признак в отчёте без программирования
В отчётах на системе компоновки данных выражения пишутся на том же языке, что и запросы. В полной настройке варианта отчёта есть пользовательские поля: поле-выбор позволяет задать несколько условий и значение для каждого, а поле-выражение — написать ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ вручную. Так бухгалтер может добавить колонку «Просрочено / В срок» без доработки конфигурации.
Если нужно только подсветить строки, а не добавлять колонку, проще использовать условное оформление отчёта: условие задаётся в отборе, цвет — в оформлении.
Проверка перед записью документа
Типичная задача доработчика — запретить запись при неверных данных. Здесь нужен Если, потому что результатом будет действие:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если Не ЗначениеЗаполнено(Договор) Тогда
ОбщегоНазначения.СообщитьПользователю("Не указан договор", , "Договор", "Объект", Отказ);
ИначеЕсли СуммаДокумента <= 0 Тогда
ОбщегоНазначения.СообщитьПользователю("Сумма документа должна быть больше нуля", , "СуммаДокумента", "Объект", Отказ);
КонецЕсли;
КонецПроцедуры
Процедура ОбщегоНазначения.СообщитьПользователю есть в типовых конфигурациях на БСП. В самописной базе используйте Новый СообщениеПользователю и установите Отказ = Истина вручную.
Вложенные условия и чем их заменить
Три уровня вложенности Если — сигнал, что код пора упростить. Есть три проверенных приёма.
Ранний выход из процедуры
Вместо пирамиды условий проверьте «плохие» случаи в начале и выйдите:
Функция СтавкаСкидки(Клиент, Сумма)
Если Не ЗначениеЗаполнено(Клиент) Тогда
Возврат 0;
КонецЕсли;
Если Сумма < 10000 Тогда
Возврат 0;
КонецЕсли;
Возврат ?(Сумма >= 100000, 10, 5);
КонецФункции
Каждое условие читается отдельно, а основная логика не уезжает вправо на четыре отступа.
Соответствие вместо длинной цепочки
Когда ветки отличаются только значением, вынесите пары в Соответствие:
Описания = Новый Соответствие;
Описания.Вставить("Оплачен", "Оплата получена полностью");
Описания.Вставить("Частично", "Есть остаток долга");
Описания.Вставить("НеОплачен", "Оплаты нет");
Описание = Описания.Получить(Статус);
Если Описание = Неопределено Тогда
Описание = "Статус не распознан: " + Статус;
КонецЕсли;
Получить возвращает Неопределено, если ключа нет. Эта единственная проверка заменяет ветку Иначе.
Логические операции вместо вложенных Если
Два вложенных условия без промежуточных действий объединяются через И:
Если ЗначениеЗаполнено(Договор) И Договор.ВалютаВзаиморасчетов <> ВалютаДокумента Тогда
// пересчёт по курсу
КонецЕсли;
Встроенный язык вычисляет И и ИЛИ сокращённо: если ЗначениеЗаполнено(Договор) ложно, вторая часть не проверяется, и обращения к реквизиту пустой ссылки не будет.
Вложенный ВЫБОР в запросе
ВЫБОР внутри ВЫБОР допустим, но почти всегда его можно развернуть в один список КОГДА с условиями через И. Плоский вариант легче проверить глазами и проще поддерживать.
Как писать условия чище: приёмы практика
- 📌 Одно условие — одна мысль. Длинное выражение из пяти сравнений вынесите в переменную с говорящим именем:
ДокументВалютный = …. УсловиеЕсли ДокументВалютный Тогдапонятно без комментария. - 📌 Не сравнивайте с Истиной.
Если Флаг = Истина Тогдаработает, ноЕсли Флаг Тогдакороче. Для отрицания —Если Не Флаг Тогда. - 📌 Скобки при смешении И и ИЛИ.
Ивыполняется раньшеИЛИ. ЗаписьА ИЛИ Б И ВозначаетА ИЛИ (Б И В). Если имели в виду иное — поставьте скобки явно. - 📌 Всегда заканчивайте ВЫБОР веткой ИНАЧЕ с понятным значением вроде
"Не определено". Строка с таким текстом в отчёте сразу покажет, какие данные не попали ни под одно условие. - 📌 Один тип результата во всех ветках
ВЫБОР. Если одна ветка возвращает число, а другая строку, поле получит составной тип. Сортировать и суммировать его неудобно. - 📌 Пороги в параметры. Число
100000, зашитое в три места запроса, однажды поменяют только в двух. Передайте его параметром&Порог.