Разработка и Конфигурация · 12 мин
Как написать условие в 1С: полное руководство с примерами
Разбираем, как написать условие в 1С: оператор Если, условный оператор в запросах, выбор по условию, типичные ошибки сравнения и проверка результата.
Условие — базовая конструкция любого кода на встроенном языке 1С. С его помощью программа принимает решение: выполнить одну ветку алгоритма или другую, отобрать записи в запросе, вывести разный текст в печатной форме. Ошибка в условии приводит не к аварийной остановке, а к тихому неверному поведению: документ проведётся неправильно, скидка не применится, отчёт покажет чужие данные.
В 1С условия встречаются в трёх основных местах: оператор Если…Тогда…КонецЕсли в модуле, конструкция ГДЕ в тексте запроса и тернарный выбор ?(Условие, Значение1, Значение2) в выражениях. Синтаксис у них разный, и типичная ошибка новичка — переносить правила одного контекста в другой.
Ниже разобран синтаксис каждого варианта, операторы сравнения и логические связки, работа с пустыми значениями и датами, типичные ошибки и способы проверить, что условие отрабатывает так, как задумано.
Оператор Если: базовый синтаксис условия в модуле
Основная форма условного оператора во встроенном языке 1С выглядит так:
Если СуммаДокумента > 100000 Тогда
ТребуетсяСогласование = Истина;
ИначеЕсли СуммаДокумента > 0 Тогда
ТребуетсяСогласование = Ложь;
Иначе
Сообщить("Сумма документа не заполнена");
КонецЕсли;
Ключевые правила: после Если идёт выражение, которое должно вычисляться в булево значение (Истина или Ложь), затем обязательное слово Тогда. Веток ИначеЕсли может быть сколько угодно, ветка Иначе — необязательна. Завершает конструкцию КонецЕсли; с точкой с запятой — её отсутствие даёт синтаксическую ошибку при проверке модуля.
Условия проверяются сверху вниз, и выполняется только первая подошедшая ветка. Поэтому порядок веток имеет значение: если поставить проверку СуммаДокумента > 0 раньше, чем СуммаДокумента > 100000, вторая ветка никогда не сработает. Располагайте более строгие условия выше.
- 1Определите, какое выражение должно давать Истина или Ложь
- 2Запишите ветки от самого строгого условия к самому общему
- 3Добавьте ветку Иначе для непредусмотренных ситуаций
- 4Проверьте модуль через конфигуратор: наличие КонецЕсли и точек с запятой
- 5Протестируйте каждую ветку на граничных значениях
Операторы сравнения и логические связки
В условиях используются операторы сравнения =, <> (не равно), >, <, >=, <=. Сравнивать можно числа, строки, даты, ссылки и булевы значения. Строки сравниваются с учётом регистра: "Акт" и "акт" — разные значения.
Сложные условия строятся логическими операторами:
И— истинно, когда истинны обе части;ИЛИ— истинно, когда истинна хотя бы одна часть;НЕ— инвертирует значение.
Если (Статус = "Оплачен" И Сумма > 0)
ИЛИ РежимРучнойКорректировки Тогда
РазрешитьПроведение = Истина;
КонецЕсли;
Приоритет операторов: сначала НЕ, затем И, затем ИЛИ. Смешивая И и ИЛИ без скобок, легко получить не ту логику, которую задумывали. Правило простое: любое сочетание разных логических операторов закрывайте скобками — это убирает двусмысленность и для компилятора, и для читающего код.
Тернарный оператор и Выбор в выражениях
Когда по условию нужно просто выбрать одно из двух значений, громоздкий Если заменяют тернарным оператором:
ТекстСтатуса = ?(ДокументПроведен, "Проведён", "Черновик");
Оператор читается как «если условие истинно — первое значение, иначе второе». Он удобен при формировании строк, установке реквизитов и в выражениях, где полноценный Если не вставить. Не стоит вкладывать тернарные операторы друг в друга: конструкция ?(А, 1, ?(Б, 2, 3)) работает, но читается плохо — при трёх и более ветках возвращайтесь к Если…ИначеЕсли.
В языке запросов аналогичную роль играет конструкция ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ, которая позволяет вычислять значение поля по условию прямо в выборке. Это удобно, когда нужно в одном запросе получить, например, признак «Просрочен» по сравнению даты оплаты с текущей датой.
Сравнение вариантов
Подходит для любой логики и нескольких операторов в ветке; ограничение — многословность для простого выбора значения
Лучший вариант для выбора одного из двух значений в выражении; не подходит для веток с несколькими операторами
Единственный способ условного вычисления поля внутри запроса; не работает в обычном коде модуля
Условия в запросах: ГДЕ, параметры и виртуальные таблицы
В тексте запроса условие отбора записывается в секции ГДЕ:
ВЫБРАТЬ
Номенклатура, Количество
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад)
ГДЕ
Количество > 0
Параметры передаются через &ИмяПараметра и устанавливаются методом УстановитьПараметр до выполнения запроса. Не подставляйте значения конкатенацией строк — это и источник ошибок с типами, и потенциальная уязвимость.
Важная оптимизационная деталь: условия на измерения виртуальной таблицы (остатки, обороты, срезы) указывайте в параметрах самой виртуальной таблицы, как в примере выше, а не в секции ГДЕ. Отбор в параметрах выполняется до расчёта виртуальной таблицы, в ГДЕ — после, что на больших объёмах данных заметно медленнее.
Для отбора по списку значений используйте оператор В (&СписокЗначений), для иерархии — В ИЕРАРХИИ (&Группа), для подстроки — ПОДОБНО "%текст%". Учтите, что ПОДОБНО с шаблоном, начинающимся с %, не использует индекс и на больших таблицах работает медленно.
Проверка пустых значений, Неопределено и NULL
Отдельный класс условий — проверка «заполненности». В 1С есть три разных «пустых» состояния, и путать их нельзя:
- Неопределено — значение не присвоено. Проверка:
Если Значение = Неопределено Тогда. - Пустая ссылка — ссылка заданного типа без объекта. Проверка:
Если Контрагент.Пустая() Тогдаили функцияЗначениеЗаполнено(Контрагент). - NULL — отсутствие значения в результате запроса (например, при левом соединении). Проверка только в запросе:
ЕСТЬ NULLили функцияЕСТЬNULL(Поле, ЗначениеПоУмолчанию).
Универсальный вариант для кода модуля — функция ЗначениеЗаполнено(Значение): она возвращает Ложь для Неопределено, пустых ссылок, пустых строк, нулевых чисел и пустых дат. Но помните: число 0 и пустая дата — иногда вполне осмысленные значения, и отбрасывать их функцией ЗначениеЗаполнено бывает ошибкой бизнес-логики.
В запросе сравнение с NULL через = не работает: результат всегда неопределён, и строка в выборку не попадёт. Только ЕСТЬ NULL / НЕ ЕСТЬ NULL. Это одна из самых частых причин «запрос ничего не вернул, хотя данные есть».
Как проверить, что условие работает правильно
Проверка условия начинается с граничных значений. Для условия Сумма > 100000 тестируют значения 99999, 100000, 100001 и 0: именно на границе чаще всего обнаруживается, что нужно было >=, а не >. Каждая ветка Если и ИначеЕсли должна быть достигнута хотя бы в одном тесте.
Для отладки используйте точку останова в конфигураторе и вычисление выражения (Shift+F9): можно проверить, во что реально вычисляется условие на конкретных данных, не догадываясь. Если условие сложное, временно разбейте его на переменные с говорящими именами — ЭтоОплаченныйЗаказ, ПревышенЛимит — и проверяйте каждую по отдельности.
Для запросов удобен конструктор запроса и консоль запросов в режиме предприятия: выполните запрос с реальными параметрами, затем по одному убирайте условия из ГДЕ, чтобы найти то, которое отсекает нужные строки. Если запрос возвращает меньше записей, чем ожидалось, первым делом проверяйте соединения (левое/внутреннее) и сравнения с NULL.
Как проверить результат
Каждая ветка достигается хотя бы на одном тестовом наборе данных
Ветка Иначе или ИначеЕсли не выполняется никогда — вероятно, условия перекрывают друг друга
На значении ровно на границе срабатывает задуманная ветка
Граница попадает не в ту ветку — перепутаны > и >=
Количество записей соответствует ожиданию на контрольном примере
Записей меньше — проверяйте NULL, типы параметров и вид соединения
Частые ошибки и как их избежать
Самая коварная группа ошибок — сравнение значений разных типов. Сравнение строки с числом или ссылки со строкой не вызывает исключения, а просто даёт Ложь, и условие молча не срабатывает. Перед сравнением убедитесь в типах: используйте ТипЗнч(Значение) или явное приведение.
Вторая группа — условия, зависящие от контекста исполнения. Код, работающий на клиенте, не видит серверные функции и наоборот; директивы &НаСервере и &НаКлиенте определяют, какие данные доступны в условии. Проверка существования объекта по ссылке требует серверного контекста.
Третья группа — избыточная вложенность. Пять вложенных Если подряд читаются хуже, чем плоская цепочка с ранним выходом: Если НЕ Условие Тогда Возврат; КонецЕсли;. Приём «защитного выхода» упрощает и код, и его тестирование.
Если одно и то же условие (например, проверка статуса документа) повторяется в нескольких местах модуля, вынесите его в отдельную функцию с говорящим именем. Когда правило изменится, править придётся одно место, а не искать все копии условия по конфигурации.
FAQ
Чем отличается = от == в 1С?
Во встроенном языке 1С оператора == нет. Одиночный знак равенства используется и для присваивания, и для сравнения — контекст определяется положением: в условии после Если это сравнение, в начале оператора — присваивание.
Как проверить, что строка не пустая?
Используйте НЕ ПустаяСтрока(Строка) — функция считает пустой и строку из одних пробелов. Функция ЗначениеЗаполнено() для строки из пробелов вернёт Истина, что не всегда ожидаемо.
Можно ли в условии сравнивать даты?
Да, даты сравниваются операторами >, <, = напрямую. Помните, что дата содержит время с точностью до секунды: сравнение на равенство двух дат, полученных разными способами, может не сработать из-за разного времени. Для сравнения по дню используйте НачалоДня() или КонецДня().
Почему условие в запросе с параметром-списком не работает?
Для отбора по списку нужен оператор В: ГДЕ Номенклатура В (&СписокНоменклатуры), а параметру должен быть присвоен массив или список значений. Сравнение через = со списком не сработает.
Как написать условие «если поле заполнено, то фильтровать, иначе показать всё» в запросе?
Шаблон: ГДЕ (&Параметр = НЕОПРЕДЕЛЕНО ИЛИ Поле = &Параметр) — при неустановленном параметре отбор отключается. Перед выполнением не забывайте устанавливать параметр в Неопределено, если фильтр не нужен.
Что вернёт сравнение с NULL в запросе через знак равно?
Результат будет неопределённым, и такая строка не попадёт в выборку — условие просто «не сработает» без ошибки. Для проверки на NULL используйте конструкцию Поле ЕСТЬ NULL или функцию ЕСТЬNULL().
Что важно запомнить
В модуле условие пишется через Если…Тогда…КонецЕсли, в запросе — через ГДЕ и ВЫБОР, в выражениях — через тернарный ?(). Следите за типами сравниваемых значений, разделяйте Неопределено, пустую ссылку и NULL, ставьте скобки при смешении И и ИЛИ, а изменения логики проведения проверяйте на копии базы.