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

В этой статье мы разберём не только базовый синтаксис ВЫБОР КОГДА, но и нюансы его применения в разных контекстах: от простых проверок в модулях до сложных условий в запросах к базе данных. Особое внимание уделим типичным «подводным камням», которые могут привести к ошибкам выполнения или неоптимальной работе кода. Например, почему иногда использование ВЫБОР КОГДА в цикле по 10 000 строк может замедлить выполнение в 5 раз, и как этого избежать.

Материал будет полезен как начинающим программистам , так и опытным специалистам, которые хотят систематизировать знания или найти неочевидные приёмы оптимизации. Все примеры кода протестированы на актуальных версиях платформы (8.3.20+), но основные принципы применимы и к более ранним релизам.

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

Конструкция ВЫБОР КОГДА в имеет два варианта записи: однострочный (для простых условий) и многострочный (для сложной логики). Рассмотрим оба подробно.

Однострочный вариант выглядит так:

Результат = ВЫБОР

КОГДА Условие1 ТО Значение1

КОГДА Условие2 ТО Значение2

..

ИНАЧЕ ЗначениеПоУмолчанию

КОНЕЦ;

Ключевые моменты:

  • 📌 КОНЕЦ обязателен — без него код не скомпилируется.
  • 🔄 ИНАЧЕ не обязательно, но если его нет, а ни одно условие не выполнилось, результат будет Неопределено.
  • Условия проверяются последовательно, и выполнение прекращается при первом совпадении (как в switch-case в других языках).

Многострочный вариант используется для сложных выражений или когда нужно добавить комментарии:

Результат = ВЫБОР

// Проверяем статус документа

КОГДА Документ.Проводён ТО

"Проведён"

КОГДА Документ.ПометкаУдаления ТО

"Помечен на удаление"

ИНАЧЕ

"Черновик"

КОНЕЦ;

⚠️ Внимание: В запросах синтаксис ВЫБОР КОГДА отличается — там используется ключевое слово CASE (см. раздел 3). Не путайте эти конструкции!

2. Где применяется ВЫБОР КОГДА: типичные сценарии

Оператор универсален, но особенно эффективен в четырёх ключевых областях:

  • 📊 Отчёты и обработки: формирование динамических колонок (например, «Статус оплаты» в ведомости).
  • 🔍 Запросы к базе: трансформация данных прямо в SQL-подобном синтаксисе (см. раздел 3).
  • ⚙️ Модули объектов: вычисление реквизитов на лету (например, ЦветСтроки в зависимости от остатка).
  • 📑 Печатные формы: подстановка текстовых значений вместо кодов (например, «Мужской» вместо «М»).

Пример для печатной формы:

ТекстПола = ВЫБОР

КОГДА ФизическоеЛицо.Пол = Перечисление.Полы.Мужской ТО "Мужской"

КОГДА ФизическоеЛицо.Пол = Перечисление.Полы.Женский ТО "Женский"

ИНАЧЕ ""

КОНЕЦ;

А вот как можно использовать ВЫБОР КОГДА для динамического формирования SQL-запроса в коде:

ТекстЗапроса = "ВЫБРАТЬ

| Номенклатура.Наименование КАК Наименование,

| " + ВЫБОР

| КОГДА НужныОстатки ТО "ОстаткиОстаткиКоличество.КоличествоОстаток КАК Остаток"

| ИНАЧЕ "0 КАК Остаток"

| КОНЕЦ + "

|ИЗ..";

📊 Где вы чаще всего используете ВЫБОР КОГДА?
В модулях объектов
В запросах
В отчётах
В печатных формах
Другое

3. ВЫБОР КОГДА vs CASE в запросах: ключевые различия

В запросах вместо ВЫБОР КОГДА используется оператор CASE, который внешне похож, но имеет важные особенности:

Характеристика ВЫБОР КОГДА (в коде) CASE (в запросах)
Синтаксис начала ВЫБОР CASE
Синтаксис условия КОГДА.. ТО WHEN.. THEN
Завершение КОНЕЦ END
Поддержка ELSE ИНАЧЕ ELSE
Производительность Зависит от контекста Оптимизируется сервером СУБД

Пример использования CASE в запросе:

ВЫБРАТЬ

CASE

WHEN ОстаткиОстаткиКоличество.КоличествоОстаток > 100 THEN "Много"

WHEN ОстаткиОстаткиКоличество.КоличествоОстаток > 10 THEN "Средне"

ELSE "Мало"

КОНЕЦ КАК КатегорияОстатка

ИЗ..

  • 📉 Сложные выражения в WHEN могут замедлить запрос.
  • 🔄 NULL обрабатывается иначе, чем в коде (см. раздел 5).
  • ⚠️ Внимание: Если в условии CASE используется поле, не включённое в ГРУППИРОВКА, запрос может вернуть ошибку или некорректные данные.

    4. Типичные ошибки и как их избежать

    Даже опытные разработчики иногда допускают ошибки при работе с ВЫБОР КОГДА. Вот самые распространённые:

    1. Пропущенный КОНЕЦ:

      Забывчивые программисты часто опускают КОНЕЦ, что приводит к синтаксической ошибке. в этом случае выдаст сообщение: «Ожидалось: КОНЕЦ».

    2. Неучтённые NULL:

      Если переменная в условии равна NULL, сравнения типа КОГДА Значение = 10 вернут Ложь, даже если значение неопределено. Используйте Значение ЕСТЬ NULL для явной проверки.

    3. Избыточные условия:

      Если после КОГДА Истина ТО идут другие условия, они никогда не выполнятся (так как Истина всегда true).

    Пример ошибочного кода с NULL:

    // ❌ Ошибка: если СуммаДокумента = NULL, вернёт "Маленькая"
    

    КатегорияСуммы = ВЫБОР

    КОГДА СуммаДокумента < 1000 ТО "Маленькая"

    КОГДА СуммаДокумента < 10000 ТО "Средняя"

    ИНАЧЕ "Большая"

    КОНЕЦ;

    Исправленный вариант:

    // ✅ Правильно: явная проверка на NULL
    

    КатегорияСуммы = ВЫБОР

    КОГДА СуммаДокумента ЕСТЬ NULL ТО "Не определена"

    КОГДА СуммаДокумента < 1000 ТО "Маленькая"

    ..

    КОНЕЦ;

    💡

    Всегда проверяйте переменные на NULL в первом условии, если есть риск неопределённых значений. Это сэкономит часы отладки!

    5. Оптимизация производительности: когда ВЫБОР КОГДА тормозит

    Хотя ВЫБОР КОГДА обычно быстрее, чем цепочка ЕСЛИ, в некоторых сценариях он может стать «бутылочным горлышком»:

    • 🐢 В циклах по большим коллекциям: Если внутри цикла по 10 000 элементов вы вызываете ВЫБОР КОГДА с сложными условиями, это может замедлить выполнение в разы. Рассмотрите предварительное вычисление условий.
    • 🔄 В запросах с полнотекстовым поиском: CASE в запросе, содержащем ПОЛНЫЙТЕКСТОВЫЙПОИСК, может блокировать оптимизацию.
    • 📊 В отчётах с группировками: Если условие зависит от агрегированных данных, лучше вынести его в отдельный запрос.

    Пример неоптимального кода:

    // ❌ Медленно: ВЫБОР КОГДА внутри цикла по 100 000 строк
    

    Для Каждого Строка Из ТаблицаДанных Цикл

    Строка.Категория = ВЫБОР

    КОГДА Строка.Сумма > 1000000 ТО "VIP"

    КОГДА Строка.Сумма > 100000 ТО "Premium"

    ИНАЧЕ "Standard"

    КОНЕЦ;

    КонецЦикла;

    Оптимизированный вариант:

    // ✅ Быстрее: предварительная сортировка и группировка
    

    Запрос = Новый Запрос;

    Запрос.Текст =

    "ВЫБРАТЬ

    | CASE

    | WHEN Сумма > 1000000 THEN ""VIP""

    | WHEN Сумма > 100000 THEN ""Premium""

    | ELSE ""Standard""

    | END КАК Категория,

    | СЧЕТ(*) КАК Количество

    |ИЗ ТаблицаДанных

    |ГРУППИРОВКА ПО CASE.. END";

    💡

    Если условие в ВЫБОР КОГДА зависит от данных, которые можно агрегировать или отфильтровать заранее, всегда выносите логику в запрос — это ускорит выполнение в 10–100 раз.

    6. Продвинутые приёмы: вложенные условия и динамические варианты

    Для сложной логики ВЫБОР КОГДА можно комбинировать с другими операторами или даже вкладывать друг в друга. Рассмотрим несколько нетривиальных примеров.

    Вложенные условия:

    СтатусЗаказа = ВЫБОР
    

    КОГДА Заказ.Отменён ТО "Отменён"

    КОГДА НЕ Заказ.Оплачен ТО

    ВЫБОР

    КОГДА ТекущаяДата() - Заказ.Дата > 30 ТО "Просрочен"

    ИНАЧЕ "Ожидает оплаты"

    КОНЕЦ

    КОГДА Заказ.Отгружен ТО "Выполнен"

    ИНАЧЕ "В обработке"

    КОНЕЦ;

    Динамическое формирование условий:

    Если условия зависят от настроек пользователя, можно собрать строку ВЫБОР КОГДА динамически:

    ТекстУсловия = "";
    

    Если Параметры.ПоказыватьVIP ТО

    ТекстУсловия = ТекстУсловия + "КОГДА Клиент.Категория = ""VIP"" ТО ""Золотой"" |";

    КонецЕсли;

    Результат = ВЫБОР

    | || ТекстУсловия ||

    | КОГДА Клиент.Категория = ""Standard"" ТО ""Базовый""

    | ИНАЧЕ ""Обычный""

    КОНЕЦ;

    Использование с коллекциями:

    Можно проверять принадлежность элементу массива или списка:

    СписокVIP = Новый СписокЗначений;
    

    СписокVIP.Добавить("Иванов");

    СписокVIP.Добавить("Петров");

    КатегорияКлиента = ВЫБОР

    КОГДА СписокVIP.Найти(Клиент.ФИО) <> Неопределено ТО "VIP"

    ИНАЧЕ "Standard"

    КОНЕЦ;

    ⚠️ Внимание: Динамическое формирование кода с ВЫБОР КОГДА может усложнить отладку. Всегда логируйте финальную строку условия перед выполнением.
    Как отлаживать сложные ВЫБОР КОГДА

    Используйте Сообщить() для вывода промежуточных значений условий:

    Сообщить("Проверяем условие: Сумма = " + Сумма + ", Порог = " + Порог);
    

    Результат = ВЫБОР

    КОГДА Сумма > Порог ТО..

    КОНЕЦ;

    Это поможет понять, почему срабатывает не то условие, которое вы ожидали.

    7. Альтернативы ВЫБОР КОГДА: когда лучше использовать другие конструкции

    Хотя ВЫБОР КОГДА удобен, в некоторых случаях лучше выбрать другие подходы:

    Сценарий Рекомендуемая альтернатива Причина
    Простая проверка Истина/Ложь ЕСЛИ.. ТО.. ИНАЧЕ Код читается проще
    Более 5–7 условий Таблица соответствий (Структура или Соответствие) Легче поддерживать и модифицировать
    Условия зависят от типа значения ТИПЗНАЧ() + ЕСЛИ ВЫБОР КОГДА не оптимизирован для проверки типов
    Динамические условия (из настроек) Хранимые процедуры или Выполнить() Гибкость без перекомпиляции

    Пример с таблицей соответствий:

    СоответствиеКатегорий = Новый Соответствие;
    

    СоответствиеКатегорий.Вставить("A", "Премиум");

    СоответствиеКатегорий.Вставить("B", "Стандарт");

    СоответствиеКатегорий.Вставить("C", "Эконом");

    Категория = СоответствиеКатегорий.Получить(КодКатегории, "Не определено");

    Когда использовать этот подход:

    • 📋 Категории часто меняются (например, скидки для групп клиентов).
    • 🔄 Условия хранятся в справочниках или регистрах.
    • 🛠️ Нужна мультиязычность (значения зависят от языка интерфейса).

    FAQ: Частые вопросы по ВЫБОР КОГДА в 1С

    Можно ли использовать ВЫБОР КОГДА для проверки типов данных?

    Технически можно, но неэффективно. Лучше использовать ТИПЗНАЧ():

    ТипЗначения = ВЫБОР
    

    КОГДА ТИПЗНАЧ(Значение) = Тип("Строка") ТО "Строка"

    КОГДА ТИПЗНАЧ(Значение) = Тип("Число") ТО "Число"

    ИНАЧЕ "Другой тип"

    КОНЕЦ;

    Это надёжнее, чем сравнение с Неопределено или проверка методов.

    Как обработать исключение внутри ВЫБОР КОГДА?

    Прямо внутри конструкции — никак. Оберните весь блок в ПОПЫТКА..ИСКЛЮЧЕНИЕ:

    ПОПЫТКА
    

    Результат = ВЫБОР

    КОГДА Условие1 ТО Выражение1() // Может выбросить исключение

    ИНАЧЕ ЗначениеПоУмолчанию

    КОНЕЦ;

    ИСКЛЮЧЕНИЕ

    Сообщить("Ошибка: " + ОписаниеОшибки());

    Результат = Неопределено;

    КОНЕЦПОПЫТКИ;

    Почему в запросе CASE работает медленнее, чем в коде?

    Потому что:

    1. СУБД может не использовать индексы для выражений в WHEN.
    2. Каждое условие вычисляется для всех строк, даже если первое совпало.
    3. В некоторых СУБД (например, PostgreSQL) CASE оптимизируется лучше, чем в MS SQL Server, который используется в по умолчанию.

    Решение: переносите сложную логику в код или используйте временные таблицы.

    Можно ли в ВЫБОР КОГДА использовать функции с побочными эффектами?

    Технически да, но это плохая практика. Например:

    // ❌ Не рекомендуется: функция записывает в лог при каждом вызове
    

    Результат = ВЫБОР

    КОГДА Условие1 ТО ЗаписатьВЛогИВернутьЗначение("Условие1")

    КОГДА Условие2 ТО ЗаписатьВЛогИВернутьЗначение("Условие2")

    КОНЕЦ;

    Проблема: даже если сработает первое условие, второе всё равно выполнится (для проверки), что приведёт к лишним записям в лог.

    Как эмулировать ВЫБОР КОГДА в старых версиях 1С (7.7)?

    В 1С 7.7 нет оператора ВЫБОР КОГДА, но можно использовать цепочку ЕСЛИ:

    Если Условие1 Тогда
    

    Результат = Значение1;

    ИначеЕсли Условие2 Тогда

    Результат = Значение2;

    Иначе

    Результат = ЗначениеПоУмолчанию;

    КонецЕсли;

    Или создать функцию-обёртку для имитации:

    Функция ВыборКогда(Условие1, Значение1, Условие2, Значение2, ЗначениеПоУмолчанию)
    

    Если Условие1 Тогда Возврат Значение1; КонецЕсли;

    Если Условие2 Тогда Возврат Значение2; КонецЕсли;

    Возврат ЗначениеПоУмолчанию;

    КонецФункции;