Логический тип Булево во встроенном языке 1С

· 9 мин

Содержание

Булево значение в 1С задаётся всего двумя литералами — Истина и Ложь. Отдельной функции-конвертера вроде Число() или Строка() для него нет, и «создавать» переменную заранее не обязательно: тип определяется в момент присваивания. Частая путаница у тех, кто пришёл из других языков, — попытка написать == для сравнения или true/false латиницей. Во встроенном языке 1С это не сработает: сравнение и присваивание — один знак =, а значения пишутся по-русски.

Булев тип — самый простой из базовых: у него всего два значения. Но именно на нём чаще всего спотыкаются из-за NULL в запросах, бесполезной проверки ЗначениеЗаполнено и путаницы Неопределено с Ложь. Разберём работу с ним в коде, в запросах и на форме — с рабочими примерами.

Истина и Ложь: как задать логическую переменную

Переменные во встроенном языке не типизированы. Можно объявить через Перем в начале модуля, а можно сразу присвоить значение — тип подтянется автоматически:

Перем ДокументПроведён;
ДокументПроведён = Истина;

// или без объявления
ФлагОбмена = Ложь;

Чаще булево значение не пишут руками, а получают из выражения. Любое сравнение (=, <>, >, <, >=, <=) возвращает Истина или Ложь:

ЕстьОстаток = (Количество > 0);
СуммыРавны   = (СуммаДокумента = СуммаОплаты);

Скобки здесь для читаемости — приоритет сравнения и так выше присваивания. Результат — обычное булево, которым дальше можно пользоваться как переменной.

Переключить флаг на противоположное значение можно одной строкой через НЕ — пригодится в обработчиках «вкл/выкл»:

РежимРедактирования = НЕ РежимРедактирования;

Где булев тип встречается в метаданных:

  • 📄 реквизиты справочников, документов, регистров (флаг «Проведён», «Услуга», «Не действует»);
  • 📊 ресурсы и измерения регистров сведений, когда нужно хранить признак;
  • ⚙️ параметры и возвращаемые значения процедур и функций в модулях.

У реквизита объекта или справочника типа «Булево» всегда есть значение: по умолчанию оно равно Ложь. «Пустого» или неинициализированного булева у реквизита не бывает — это важно отличать от NULL, который приходит только из запросов (об этом ниже).

Логические операторы и проверка условий

Для составных условий есть три оператора: И, ИЛИ, НЕ. Приоритет такой же, как в математике: сначала НЕ, затем И, затем ИЛИ. Когда сомневаетесь — ставьте скобки, они читаются однозначно.

Если Склад = Склады.Основной И Количество > 0 Тогда
    Сообщить("Товар есть на основном складе");
КонецЕсли;

Проверять булево через = Истина не нужно — переменная и так подставляется в условие:

// избыточно
Если ДокументПроведён = Истина Тогда

// правильно и короче
Если ДокументПроведён Тогда

// отрицание — через НЕ
Если НЕ ДокументПроведён Тогда

Операторы И и ИЛИ вычисляются «лениво»: если левая часть уже определяет результат, правая не считается. Это даёт безопасную проверку ссылки перед обращением к её полям:

Если Ссылка <> Неопределено И НЕ Ссылка.ПометкаУдаления Тогда
    // сюда не зайдём, если Ссылка = Неопределено,
    // и обращения к .ПометкаУдаления не будет — ошибки нет
КонецЕсли;

Если нужно выбрать одно из двух значений по условию, пригодится тернарный оператор ?(). Его первый аргумент — булево выражение:

ТекстСтатуса = ?(Активен, "Включён", "Отключён");

Сложную проверку удобно вынести в функцию-предикат — она возвращает Истина или Ложь и читается как обычное условие. Такой код проще сопровождать, чем длинное выражение прямо в Если:

Функция ДоступенКОтгрузке(Товар)
    Возврат НЕ Товар.Услуга
        И НЕ Товар.ПометкаУдаления
        И Товар.ВНаличии;
КонецФункции

// применение
Если ДоступенКОтгрузке(ТекущийТовар) Тогда
    ДобавитьВОтгрузку(ТекущийТовар);
КонецЕсли;

Имя функции-предиката стоит формулировать утвердительно (ДоступенКОтгрузке, ЕстьПрава), чтобы отрицание в вызове читалось естественно: Если НЕ ДоступенКОтгрузке(...).

Булево значение в циклах

Цикл Пока работает ровно до тех пор, пока его условие остаётся Истина. Классический пример — обход выборки из запроса, где метод Следующий() сам возвращает булево:

Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.Наименование);
КонецЦикла;

Как только строки закончатся, Следующий() вернёт Ложь, и цикл остановится.

Часто логическую переменную заводят как «флаг» — чтобы запомнить факт события внутри цикла и использовать его после. Флаг инициализируют Ложь, а при совпадении переключают на Истина:

НайденоСовпадение = Ложь;
Для Каждого Строка Из ТаблицаТоваров Цикл
    Если Строка.Код = ИскомыйКод Тогда
        НайденоСовпадение = Истина;
        Прервать;
    КонецЦикла;
КонецЦикла;

Опечатка в примере выше намеренно наглядна: закрывать Для Каждого нужно КонецЦикла, а Если — КонецЕсли. Путаница закрывающих ключевых слов — одна из частых причин, почему модуль не компилируется. Внутренний Если закрывается КонецЕсли, затем идёт КонецЦикла.

Правильный вариант завершения:

    Если Строка.Код = ИскомыйКод Тогда
        НайденоСовпадение = Истина;
        Прервать;
    КонецЕсли;
КонецЦикла;

Оператор Прервать выходит из цикла сразу, как только флаг установлен, — не нужно гонять коллекцию до конца.

Логический тип в запросах к базе данных

В языке запросов булевы литералы пишутся так же: ИСТИНА и ЛОЖЬ (регистр не важен). Логическое поле можно поставить прямо в условие ГДЕ без сравнения:

ВЫБРАТЬ
    Номенклатура.Ссылка,
    Номенклатура.Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Услуга

Запись ГДЕ Номенклатура.Услуга эквивалентна ГДЕ Номенклатура.Услуга = ИСТИНА. Отобрать товары, а не услуги, можно через НЕ Номенклатура.Услуга или = ЛОЖЬ.

Вычислить булево прямо в выборке помогает конструкция ВЫБОР … КОГДА:

ВЫБОР
    КОГДА Номенклатура.Услуга
        ТОГДА "Услуга"
    ИНАЧЕ "Товар"
КОНЕЦ КАК ВидНоменклатуры

Логическое выражение можно собрать и из сравнений — например, пометить позиции с нулевым остатком:

ВЫБОР
    КОГДА ОстаткиТоваров.КоличествоОстаток > 0
        ТОГДА ЛОЖЬ
    ИНАЧЕ ИСТИНА
КОНЕЦ КАК НетВНаличии

Булево значение удобно передавать в запрос параметром — тогда одна и та же выборка обслуживает оба случая. В тексте запроса пишем параметр, а в коде устанавливаем его значение:

// в тексте запроса
// ГДЕ Номенклатура.Услуга = &ТолькоУслуги

Запрос.УстановитьПараметр("ТолькоУслуги", Истина);

Тот же приём работает в параметрах системы компоновки данных и в отборах динамических списков: признак задаётся как булево значение, и список фильтруется без правки текста запроса.

Таблица ниже показывает, как одно и то же логическое условие выглядит в коде и в запросе.

ЗадачаВстроенный языкЯзык запросов
Истина / ЛожьИстина / ЛожьИСТИНА / ЛОЖЬ
Проверка флагаЕсли Услуга ТогдаГДЕ Услуга
ОтрицаниеНЕ УслугаНЕ Услуга
И / ИЛИИ / ИЛИИ / ИЛИ
Пустое значениеНеопределеноNULL

Флажок на форме: реквизит булевого типа

Реквизит с типом «Булево» на управляемой форме по умолчанию выводится как флажок (галочка). Чтобы добавить его:

  1. Откройте форму в конфигураторе.
  2. На вкладке реквизитов добавьте реквизит и задайте тип Булево.
  3. Перетащите его на форму — элемент примет вид флажка автоматически.

В палитре свойств элемента есть свойство вида флажка — его можно переключить с обычной галочки на тумблер. Если нужного значения в списке не видно, ориентируйтесь по названию свойства, отвечающего за внешний вид флажка.

Булево удобно связывать с поведением формы. Два типовых приёма:

  • 🔒 Доступность и видимость. Свойства «Доступность» и «Видимость» других элементов можно переключать из обработчика в зависимости от значения флажка — показывать блок полей, только когда галочка стоит.
  • 🎨 Условное оформление. В настройках условного оформления списка булево поле задаёт условие — например, подсветить строки, где флаг «Проведён» снят.
  • ✅ Значение по умолчанию. Чтобы новый объект создавался с уже проставленной галочкой, задайте начальное значение реквизита в обработчике заполнения — например, в ОбработкаЗаполнения или при создании формы, присвоив реквизиту Истина.

Для флажка, который управляет видимостью соседних полей, пропишите реакцию в обработчике события «ПриИзменении» этого элемента, иначе форма перерисуется только после записи объекта.

У поля флажка есть свойство «ТриСостояния». Если его включить, галочка умеет показывать не только Истина и Ложь, но и третье, «серое» состояние — Неопределено. Это удобно для фильтров и отборов, где нужен вариант «не важно»: флаг в среднем положении означает «условие не применяем». Но помните — такой элемент возвращает уже не чистое булево, а значение, которое может быть Неопределено, и обрабатывать его надо явно.

NULL, Неопределено и приведение типов

С булевым типом связаны два «пустых» значения, и их нельзя путать.

Неопределено — значение переменной, которой ещё ничего не присвоили, или реквизита, которого нет. Это не Ложь: сравнение Неопределено = Ложь даёт Ложь.

NULL приходит из запросов, когда соединение не нашло данных. Если левым соединением подтянуть регистр остатков, а остатка нет, булево поле вернёт не ЛОЖЬ, а NULL. Строка при этом в условие ГДЕ Поле не попадёт, потому что NULL — не Истина. Лечится функцией ЕСТЬNULL:

ГДЕ ЕСТЬNULL(Остатки.ВНаличии, ЛОЖЬ)

Теперь отсутствующий остаток трактуется как Ложь, и логика становится предсказуемой.

В языке запросов логика трёхзначная: выражение с NULL даёт не Истина и не Ложь, а снова NULL. Поэтому NULL И ИСТИНА — это NULL, а строка с таким результатом в условие ГДЕ не проходит. Если в соединении есть поля, способные быть пустыми, оборачивайте их в ЕСТЬNULL до того, как подставляете в И/ИЛИ, — иначе часть строк молча выпадет из выборки.

Отдельной функции приведения к булеву типу (аналога Число(), Строка(), Дата()) во встроенном языке нет. Приводят через сравнение:

// из числа: любое ненулевое считаем Истина
Флаг = (ЗначениеЧисла <> 0);

// из строки: сверяем с эталоном
Флаг = (ВРег(СокрЛП(ТекстСтроки)) = "ДА");

Для сериализации работают стандартные функции XML: XMLСтрока(Истина) вернёт строку "true", а обратное преобразование делает XMLЗначение(Тип("Булево"), "true"). Это удобно при обмене данными и записи настроек в строку.

Функция ЗначениеЗаполнено() для булева бесполезна: ЗначениеЗаполнено(Ложь) возвращает Ложь, потому что Ложь для платформы — «пустое» значение типа. Проверять, что пользователь осознанно поставил галочку, через ЗначениеЗаполнено нельзя — у реквизита всегда есть значение по умолчанию.

Проверьте себя
Чему равно `ЗначениеЗаполнено(Ложь)`?
Какой знак используется для сравнения во встроенном языке 1С?
Что вернёт булево поле из левого соединения, если данных нет?

Частые ошибки при работе с булевым типом

Короткий разбор граблей, на которые наступают регулярно:

  • ❌ == вместо =. Во встроенном языке и в запросах сравнение — одиночный =. Двойного знака нет, он даёт синтаксическую ошибку.
  • ❌ true / false латиницей. Литералы только русские: Истина, Ложь (в запросе ИСТИНА, ЛОЖЬ). Строка "Истина" — это текст, а не логическое значение.
  • ❌ Если Флаг = Истина. Не ошибка, но лишнее. Пишите Если Флаг и Если НЕ Флаг.
  • ❌ Проверка булева через ЗначениеЗаполнено. Для Ложь она вернёт Ложь — условие сработает не так, как ожидалось.
  • ❌ NULL из запроса приняли за Ложь. После левого соединения оборачивайте логическое поле в ЕСТЬNULL(Поле, ЛОЖЬ).
  • ❌ Путаница Неопределено и Ложь. Неинициализированная переменная равна Неопределено, а не Ложь; сравнивать их напрямую нельзя.

Частые вопросы

Можно ли сравнить булево значение с числом или строкой?
Напрямую — нет, такое сравнение всегда даст Ложь, потому что это разные типы. Сначала приведите число или строку к логическому выражению через сравнение (Число <> 0), а потом сопоставляйте булево с булевым.
Почему условие `ГДЕ Поле` в запросе пропускает часть строк?
Если поле пришло из левого соединения и оказалось NULL, оно не равно ИСТИНА, и строка в выборку не попадает. Оберните поле в ЕСТЬNULL(Поле, ЛОЖЬ), чтобы задать поведение для пустого значения.
Какое значение у булева реквизита по умолчанию?
Ложь. У реквизита объекта всегда есть конкретное значение — «пустого» булева, как NULL в запросе, у него не бывает.
Как в коде получить флажок с формы?
Обращайтесь к реквизиту формы по имени — он хранит Истина или Ложь. Чтобы реагировать на переключение сразу, обработайте событие «ПриИзменении» элемента, а не ждите записи объекта.
Есть ли функция `Булево()` для приведения типа?
Нет. В отличие от Число(), Строка() и Дата(), конвертера к булеву типу не предусмотрено. Используйте сравнение (Значение <> 0) или функции XML для сериализации.