Оператор ВЫБОР КОГДА в 1С:Предприятие — один из самых востребованных инструментов для работы с условной логикой. Он позволяет заменять громоздкие конструкции из ЕСЛИ..ТО..ИНАЧЕ компактными и читаемыми выражениями, особенно полезными в запросах, отчетах и динамических вычислениях. Однако многие разработчики используют его неэффективно: либо игнорируют возможности оптимизации, либо допускают синтаксические ошибки, ведущие к некорректным результатам.
В этой статье мы разберём не только базовый синтаксис ВЫБОР КОГДА, но и нюансы его применения в разных контекстах: от простых проверок в модулях до сложных условий в запросах к базе данных. Особое внимание уделим типичным «подводным камням», которые могут привести к ошибкам выполнения или неоптимальной работе кода. Например, почему иногда использование ВЫБОР КОГДА в цикле по 10 000 строк может замедлить выполнение в 5 раз, и как этого избежать.
Материал будет полезен как начинающим программистам 1С, так и опытным специалистам, которые хотят систематизировать знания или найти неочевидные приёмы оптимизации. Все примеры кода протестированы на актуальных версиях платформы (8.3.20+), но основные принципы применимы и к более ранним релизам.
1. Синтаксис оператора ВЫБОР КОГДА: базовые правила
Конструкция ВЫБОР КОГДА в 1С имеет два варианта записи: однострочный (для простых условий) и многострочный (для сложной логики). Рассмотрим оба подробно.
Однострочный вариант выглядит так:
Результат = ВЫБОР
КОГДА Условие1 ТО Значение1
КОГДА Условие2 ТО Значение2
..
ИНАЧЕ ЗначениеПоУмолчанию
КОНЕЦ;
Ключевые моменты:
- 📌 КОНЕЦ обязателен — без него код не скомпилируется.
- 🔄 ИНАЧЕ не обязательно, но если его нет, а ни одно условие не выполнилось, результат будет
Неопределено. - ⚡ Условия проверяются последовательно, и выполнение прекращается при первом совпадении (как в
switch-caseв других языках).
Многострочный вариант используется для сложных выражений или когда нужно добавить комментарии:
Результат = ВЫБОР
// Проверяем статус документа
КОГДА Документ.Проводён ТО
"Проведён"
КОГДА Документ.ПометкаУдаления ТО
"Помечен на удаление"
ИНАЧЕ
"Черновик"
КОНЕЦ;
⚠️ Внимание: В запросах 1С синтаксис ВЫБОР КОГДА отличается — там используется ключевое слово CASE (см. раздел 3). Не путайте эти конструкции!
2. Где применяется ВЫБОР КОГДА: типичные сценарии
Оператор универсален, но особенно эффективен в четырёх ключевых областях:
- 📊 Отчёты и обработки: формирование динамических колонок (например, «Статус оплаты» в ведомости).
- 🔍 Запросы к базе: трансформация данных прямо в SQL-подобном синтаксисе (см. раздел 3).
- ⚙️ Модули объектов: вычисление реквизитов на лету (например,
ЦветСтрокив зависимости от остатка). - 📑 Печатные формы: подстановка текстовых значений вместо кодов (например, «Мужской» вместо «М»).
Пример для печатной формы:
ТекстПола = ВЫБОР
КОГДА ФизическоеЛицо.Пол = Перечисление.Полы.Мужской ТО "Мужской"
КОГДА ФизическоеЛицо.Пол = Перечисление.Полы.Женский ТО "Женский"
ИНАЧЕ ""
КОНЕЦ;
А вот как можно использовать ВЫБОР КОГДА для динамического формирования SQL-запроса в коде:
ТекстЗапроса = "ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование,
| " + ВЫБОР
| КОГДА НужныОстатки ТО "ОстаткиОстаткиКоличество.КоличествоОстаток КАК Остаток"
| ИНАЧЕ "0 КАК Остаток"
| КОНЕЦ + "
|ИЗ..";
3. ВЫБОР КОГДА vs CASE в запросах: ключевые различия
В запросах 1С вместо ВЫБОР КОГДА используется оператор CASE, который внешне похож, но имеет важные особенности:
| Характеристика | ВЫБОР КОГДА (в коде) | CASE (в запросах) |
|---|---|---|
| Синтаксис начала | ВЫБОР |
CASE |
| Синтаксис условия | КОГДА.. ТО |
WHEN.. THEN |
| Завершение | КОНЕЦ |
END |
Поддержка ELSE |
ИНАЧЕ |
ELSE |
| Производительность | Зависит от контекста | Оптимизируется сервером СУБД |
Пример использования CASE в запросе:
ВЫБРАТЬ
CASE
WHEN ОстаткиОстаткиКоличество.КоличествоОстаток > 100 THEN "Много"
WHEN ОстаткиОстаткиКоличество.КоличествоОстаток > 10 THEN "Средне"
ELSE "Мало"
КОНЕЦ КАК КатегорияОстатка
ИЗ..
WHEN могут замедлить запрос.⚠️ Внимание: Если в условииCASEиспользуется поле, не включённое вГРУППИРОВКА, запрос может вернуть ошибку или некорректные данные.
4. Типичные ошибки и как их избежать
Даже опытные разработчики иногда допускают ошибки при работе с ВЫБОР КОГДА. Вот самые распространённые:
- Пропущенный КОНЕЦ:
Забывчивые программисты часто опускают
КОНЕЦ, что приводит к синтаксической ошибке. 1С в этом случае выдаст сообщение: «Ожидалось: КОНЕЦ». - Неучтённые NULL:
Если переменная в условии равна
NULL, сравнения типаКОГДА Значение = 10вернутЛожь, даже если значение неопределено. ИспользуйтеЗначение ЕСТЬ NULLдля явной проверки. - Избыточные условия:
Если после
КОГДА Истина ТОидут другие условия, они никогда не выполнятся (так какИстинавсегда 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 работает медленнее, чем в коде?
Потому что:
- СУБД может не использовать индексы для выражений в
WHEN. - Каждое условие вычисляется для всех строк, даже если первое совпало.
- В некоторых СУБД (например, PostgreSQL)
CASEоптимизируется лучше, чем в MS SQL Server, который используется в 1С по умолчанию.
Решение: переносите сложную логику в код 1С или используйте временные таблицы.
Можно ли в ВЫБОР КОГДА использовать функции с побочными эффектами?
Технически да, но это плохая практика. Например:
// ❌ Не рекомендуется: функция записывает в лог при каждом вызове
Результат = ВЫБОР
КОГДА Условие1 ТО ЗаписатьВЛогИВернутьЗначение("Условие1")
КОГДА Условие2 ТО ЗаписатьВЛогИВернутьЗначение("Условие2")
КОНЕЦ;
Проблема: даже если сработает первое условие, второе всё равно выполнится (для проверки), что приведёт к лишним записям в лог.
Как эмулировать ВЫБОР КОГДА в старых версиях 1С (7.7)?
В 1С 7.7 нет оператора ВЫБОР КОГДА, но можно использовать цепочку ЕСЛИ:
Если Условие1 Тогда
Результат = Значение1;
ИначеЕсли Условие2 Тогда
Результат = Значение2;
Иначе
Результат = ЗначениеПоУмолчанию;
КонецЕсли;
Или создать функцию-обёртку для имитации:
Функция ВыборКогда(Условие1, Значение1, Условие2, Значение2, ЗначениеПоУмолчанию)
Если Условие1 Тогда Возврат Значение1; КонецЕсли;
Если Условие2 Тогда Возврат Значение2; КонецЕсли;
Возврат ЗначениеПоУмолчанию;
КонецФункции;