ИначеЕсли в коде или ВЫБОР КОГДА в запросе: что выбрать в 1С

· 9 мин

Содержание

Во встроенном языке 1С ветвление пишут через Если … Тогда … ИначеЕсли … Иначе … КонецЕсли, а слово КОГДА там не существует. «Когда» есть только в языке запросов и в выражениях СКД: ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ. Поэтому выбор между «Иначе» и «Когда» — это по сути выбор места: условие считается в модуле или прямо в запросе к базе.

Правило простое. Значение нужно для каждой строки выборки — ставьте ВЫБОР в запрос. Нужно решить, что делать программе дальше (вызвать процедуру, показать сообщение, прервать запись) — это Если в коде.

Два языка, две конструкции: базовый синтаксис

Условие во встроенном языке

Полная форма оператора выглядит так:

Если Сумма >= 1000000 Тогда
    Категория = "Крупная";
ИначеЕсли Сумма >= 100000 Тогда
    Категория = "Средняя";
Иначе
    Категория = "Мелкая";
КонецЕсли;

Правила, которые проверяет синтаксический контроль:

  • ✅ ИначеЕсли пишется одним словом и может повторяться сколько угодно раз;
  • ✅ Иначе — не больше одного раза и только последним блоком;
  • ✅ каждое Если закрывается своим КонецЕсли;
  • ✅ ветви проверяются сверху вниз, выполняется первая с истинным условием, остальные пропускаются.

Английские аналоги: If … Then … ElsIf … Else … EndIf. В одном модуле можно смешивать, но читать такой код тяжело — выберите один вариант.

Для коротких случаев есть тернарный оператор ?(Условие, ЗначениеЕслиИстина, ЗначениеЕслиЛожь). Он возвращает значение, а не выполняет действия:

ТекстСальдо = ?(Остаток > 0, "Дебетовое", "Кредитовое");

Условие в языке запросов

В запросе ветвление — это выражение, которое возвращает значение для поля:

ВЫБОР
    КОГДА Реализация.СуммаДокумента >= 1000000 ТОГДА "Крупная"
    КОГДА Реализация.СуммаДокумента >= 100000 ТОГДА "Средняя"
    ИНАЧЕ "Мелкая"
КОНЕЦ КАК Категория

Здесь КОГДА играет роль ИначеЕсли, ИНАЧЕ — роль Иначе, а КОНЕЦ закрывает конструкцию. По-английски: CASE WHEN … THEN … ELSE … END. Порядок тот же: срабатывает первое истинное КОГДА.

Что нужноВстроенный языкЯзык запросов
Первое условиеЕсли … ТогдаВЫБОР КОГДА … ТОГДА
Следующее условиеИначеЕсли … ТогдаКОГДА … ТОГДА
Всё остальноеИначеИНАЧЕ
ЗакрытиеКонецЕсли;КОНЕЦ
Короткая форма?(…, …, …)нет, только ВЫБОР
Без ветки «иначе»ничего не выполняетсярезультат NULL

Когда нужен «КОГДА», а когда «ИначеЕсли»

Решение принимают по трём вопросам.

  1. Где живут данные? Если значения лежат в таблицах базы и вы их всё равно выбираете запросом, классификацию делайте там же. Тянуть 50 000 строк в код, чтобы потом в цикле проставить каждой категорию через Если, — лишняя работа.
  2. Что получается в результате? ВЫБОР даёт только значение поля. Записать документ, вывести сообщение, вызвать функцию модуля из запроса нельзя. Для действий нужен Если.
  3. Нужна ли группировка или отбор по результату? Категорию, посчитанную в запросе, можно сразу сгруппировать и просуммировать. В коде для этого придётся заводить таблицу значений и сворачивать её.

💡 Хорошее разделение: запрос раскладывает строки по категориям через ВЫБОР, код по уже готовой категории решает, что делать, через Если.

Ошибки в условиях с Иначе и Когда и как их избежать

«Иначе Если» в два слова

Конструкция Иначе Если формально допустима, но это уже не продолжение цепочки, а новый вложенный оператор. Ему нужен свой КонецЕсли:

Если А > 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, зашитое в три места запроса, однажды поменяют только в двух. Передайте его параметром &Порог.

Частые вопросы и мифы об условиях

Есть ли в 1С оператор Выбор или Case для встроенного языка?
Нет. В модулях 1С:Предприятия 8.3 множественный выбор пишут цепочкой ИначеЕсли или через Соответствие. ВЫБОР КОГДА работает только в запросах и выражениях СКД.
Быстрее ли ВЫБОР в запросе, чем Если в коде?
Для массовой обработки строк обычно да: данные не нужно выгружать в память и перебирать циклом. Но в условии ГДЕ ВЫБОР может помешать использовать индекс.
Обязательна ли ветка Иначе?
В операторе Если — нет, без неё просто ничего не выполнится. В ВЫБОР формально тоже нет, но тогда несовпавшие строки получат NULL.
Можно ли в одном КОГДА проверить несколько условий?
Да, через И, ИЛИ и скобки: КОГДА Сумма > 0 И НЕ Проведен ТОГДА … Так же можно использовать В (…) для списка значений.
Миф: тернарный оператор ?() работает быстрее, чем Если.
Разница не измерима на практике. Выбирайте по читаемости: ?() для одного короткого условия со значением, Если для всего остального.