Логические значения в 1С 8.3: почему условие падает и как это исправить

· 10 мин

Содержание

Тип Булево в 1С хранит ровно два значения: Истина и Ложь. Почти все ошибки с ним сводятся к одному: туда, где платформа ждёт логическое значение, приходит что-то другое — Неопределено, NULL, строка "Да" или число.

Типичный симптом — модуль падает на строке Если ... Тогда с текстом Преобразование значения к типу Булево не может быть выполнено. Ниже — откуда берётся такое значение, как найти источник за пару минут и как написать код, который не ломается.

Что такое Булево в 1С и чем он отличается от других типов

Булево — примитивный тип платформы, как Число, Строка и Дата. У него нет реквизитов и методов, только два литерала.

  • ✅ Истина — условие выполнено, флажок установлен.
  • ❌ Ложь — условие не выполнено, флажок снят. Это же пустое значение типа.
  • 🔤 В английском синтаксисе встроенного языка — True и False.
  • 📝 Строковое представление в русском интерфейсе — "Да" и "Нет", а не "Истина" и "Ложь".

Последний пункт — частый источник путаницы. Строка(Истина) вернёт "Да". Значит, если вы выгрузили флажок в текст, а потом сравниваете его с "Истина", сравнение всегда даст Ложь.

Три свойства, которые надо держать в голове:

СвойствоКак ведёт себя Булево
Значение по умолчанию у реквизитаЛожь
Значение новой переменной без присваиванияНеопределено, а не Ложь
ЗначениеЗаполнено(Ложь)Ложь — для платформы это пустое значение

Логические операции — НЕ, И, ИЛИ. Приоритет именно в таком порядке: сначала НЕ, потом И, потом ИЛИ. Выражение А ИЛИ Б И В читается как А ИЛИ (Б И В). Если сомневаетесь — ставьте скобки, это бесплатно.

Платформа вычисляет логические выражения сокращённо. В А И Б при А = Ложь часть Б не вычисляется вовсе. На этом построена защитная проверка типа, о ней ниже.

Где встречается булев тип: реквизиты, флажки, настройки

Логическое значение в 1С окружает вас постоянно, даже если вы не программист.

Стандартные реквизиты объектов:

  • 🗑 ПометкаУдаления — у справочников и документов;
  • 📄 Проведен — у проводимых документов;
  • 📁 ЭтоГруппа — у иерархических справочников с группами;
  • 🔒 Предопределенный — признак предопределённого элемента.

Реквизиты, которые добавил разработчик. Флажки «Не использовать», «Услуга», «Включать в декларацию» в карточках — почти всегда реквизиты типа Булево.

Константы и функциональные опции. Настройки в разделе Администрирование вида «использовать склады», «вести учёт по сериям» хранятся в константах типа Булево. К ним привязаны функциональные опции: от значения константы зависит, видит ли пользователь поля и команды.

Формы. На форме реквизит Булево выводится полем флажка. Внешний вид задаётся свойством поля: обычный флажок или, в актуальных версиях 8.3, выключатель. Ещё вариант — поле переключателя с двумя подписями «Да» и «Нет».

Запросы и отчёты. В языке запросов есть литералы ИСТИНА и ЛОЖЬ, а в схеме компоновки данных булево поле можно класть в отбор, группировку и условное оформление.

Обмены и интеграции. JSON отдаёт true/false, XML — строки "true"/"false", Excel и CSV — что угодно: "Да", "1", "+", пустая ячейка. Именно на границе с внешними данными тип чаще всего и ломается.

Ошибки с типом Булево: тексты и причины

Вот что видит разработчик или пользователь, и что за этим стоит.

Преобразование значения к типу Булево не может быть выполнено

Платформа получила не-булево значение там, где нужно логическое. Чаще всего:

  • 🕳 переменная не инициализирована и равна Неопределено;
  • 🔗 поле из левого соединения в запросе вернуло NULL;
  • 🔤 в реквизит составного типа или в структуру положили строку;
  • 🔢 в условие передали число из внешнего файла.

Условие молча выполняется не так, как ожидали. Ошибки нет, но ветка Если не срабатывает. Причина — сравнение значений разных типов. Истина = "Истина" и Истина = 1 дают Ложь без всякого сообщения.

Неопределено проходит проверку <> Ложь. Код Если Флаг <> Ложь Тогда выполнит ветку, когда флажок вообще не заполнен. Значения разных типов не равны, поэтому Неопределено <> Ложь — это Истина.

Флажок на форме не сохраняется. Пользователь ставит галочку, записывает — после открытия её нет. Обычно поле связано с реквизитом формы, а не с реквизитом объекта: у поля пустой или не тот путь к данным.

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

Диагностика: выберите симптом

Как найти, откуда пришло неправильное значение

Текст ошибки говорит только «что», но не «откуда». Порядок поиска такой.

  1. Включите отладку и повторите действие. Конфигуратор: точка останова на строке из ошибки или режим остановки по ошибке в меню Отладка.
  2. Посмотрите тип значения. В остановке откройте окно вычисления выражения (Shift+F9) и вычислите ТипЗнч(ИмяПеременной). Увидите Неопределено, NULL, Строка — значит, причина найдена наполовину.
  3. Пройдите назад по присваиваниям. Найдите, где переменная получила значение: параметр процедуры, поле выборки, элемент структуры, ячейка табличного документа.
  4. Если значение из запроса — проверьте соединения. Поле из правой таблицы ЛЕВОГО СОЕДИНЕНИЯ при отсутствии строки вернёт NULL.
  5. Если значение из реквизита составного типа — откройте его свойства в конфигураторе. Составной тип «Булево, Строка» позволяет пользователю или обработке записать туда текст.

Когда отладчик недоступен — например, ошибка возникает только у одного пользователя в рабочей базе, — временно выведите тип в сообщение:

Сообщить("Тип значения: " + Строка(ТипЗнч(Флаг)) + ", значение: " + Строка(Флаг));

Для фоновых заданий и регламентных процедур вместо Сообщить пишите в журнал регистрации через ЗаписьЖурналаРегистрации.

Ошибку, которая возникает только у части пользователей, полезно сопоставить с журналом регистрации: часто она проявляется на конкретных элементах справочника, где реквизит так и не заполнили после доработки.

Исправляем ошибки: приведение типов и защитные проверки

Способов несколько, выбирайте по источнику проблемы.

СпособКогда подходитНа что смотреть
Явная инициализация переменнойПеременная объявлена, но не во всех ветках получает значениеПрисвойте Ложь сразу после Перем или в начале процедуры
ЕСТЬNULL в запросеПоле приходит из левого соединенияВторой параметр — ЛОЖЬ
Проверка ТипЗнчЗначение может быть любого типа: параметры, структуры, составные реквизитыСтавьте проверку типа первой в И
Функция Булево()Пришло число или строка «Истина»/«Ложь»На строке «Да» или «1» упадёт той же ошибкой
Своя функция разбораДанные из Excel, CSV, сторонних системРешите заранее, что делать с непонятным значением
Замена составного типаВ реквизите давно лежат строки вперемешку с флажкамиЭто изменение структуры, нужна обработка перезаполнения

Инициализация

Самое простое и самое забытое:

Перем ЕстьОшибки;
ЕстьОшибки = Ложь;

Если значение задаётся внутри нескольких Если ... ИначеЕсли, без начального Ложь одна из веток обязательно оставит Неопределено.

Защитная проверка типа

Благодаря сокращённому вычислению такое условие безопасно для любого значения:

Если ТипЗнч(Флаг) = Тип("Булево") И Флаг Тогда
    // флажок точно установлен
КонецЕсли;

Если Флаг равен Неопределено, вторая часть не вычисляется, ошибки нет.

Приведение функцией Булево()

Булево(1) вернёт Истина, Булево(0) — Ложь. Любое ненулевое число превращается в Истина. Строки функция понимает только в виде логических литералов, поэтому для данных из файлов лучше своя функция.

Перезаполнение реквизита

Если в рабочей базе в реквизите составного типа скопился мусор, исправлять нужно данные, а не только код. Напишите обработку, которая пройдёт по элементам, приведёт значения к Булево и запишет их.

Перед массовой записью элементов сделайте резервную копию базы. Запись запускает обработчики ПередЗаписью и подписки на события: могут измениться и другие реквизиты, а у документов — движения.

Примеры кода с булевыми значениями

Разбор строки из внешнего файла

Функция СтрокаВБулево(Знач Текст, ЗначениеПоУмолчанию = Ложь) Экспорт

    Текст = НРег(СокрЛП(Текст));

    Если Текст = "истина" Или Текст = "да" Или Текст = "true" Или Текст = "1" Тогда
        Возврат Истина;
    ИначеЕсли Текст = "ложь" Или Текст = "нет" Или Текст = "false" Или Текст = "0" Тогда
        Возврат Ложь;
    КонецЕсли;

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

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

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

Вывод флажка в текст

ТекстФлага = Формат(Флаг, "БЛ=Нет; БИ=Да");

БЛ — представление для Ложь, БИ — для Истина. Так же задаётся формат поля на форме или в макете: например, БЛ=-; БИ=+ для компактной таблицы.

Булево в число и обратно

Количество = ?(Флаг, 1, 0);
Флаг       = (Количество <> 0);

Сравнение в скобках само по себе является логическим выражением, его можно сразу присвоить переменной. Писать Если Количество <> 0 Тогда Флаг = Истина Иначе Флаг = Ложь незачем.

Переключение флажка

Объект.НеИспользовать = НЕ Объект.НеИспользовать;

Запрос с защитой от NULL и необязательным отбором

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|    Номенклатура.Ссылка КАК Ссылка,
|    ВЫБОР
|        КОГДА ЕСТЬNULL(Остатки.КоличествоОстаток, 0) > 0
|            ТОГДА ИСТИНА
|        ИНАЧЕ ЛОЖЬ
|    КОНЕЦ КАК ЕстьОстаток
|ИЗ
|    Справочник.Номенклатура КАК Номенклатура
|        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
|        ПО Остатки.Номенклатура = Номенклатура.Ссылка
|ГДЕ
|    (НЕ &ТолькоНеПомеченные ИЛИ НЕ Номенклатура.ПометкаУдаления)";

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

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

Поле ЕстьОстаток в результате всегда Булево: даже если остатков нет, ЕСТЬNULL подставит ноль, и ВЫБОР вернёт ЛОЖЬ, а не NULL.

Лишние сравнения

// Работает, но избыточно:
Если Объект.Проведен = Истина Тогда

// Достаточно:
Если Объект.Проведен Тогда

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

Логический тип в 1С 7.7, 8.2 и 8.3: что изменилось

1С 7.7. Отдельного типа Булево в языке не было. Условия строились на числах: ноль — ложь, всё остальное — истина. Флажки в формах хранили 0 и 1 в реквизите числового типа. При переносе данных из 7.7 такие реквизиты приходят числами, их нужно приводить через Булево() или сравнение <> 0.

1С 8.0–8.2. Появился полноценный тип Булево с литералами Истина и Ложь. В обычных формах флажок — элемент «Флажок», связанный с реквизитом.

1С 8.3. Сам тип не менялся, изменилось окружение:

  • 🖥 в управляемых формах — поле флажка со свойством вида отображения;
  • 🔄 с релиза 8.3.6 платформа умеет читать и писать JSON, а true/false из JSON сразу становятся Булево;
  • 📦 через XMLСтрока(Истина) получается "true", а XMLЗначение(Тип("Булево"), "true") возвращает обратно Истина — удобно для обменов.

Код, написанный для 8.2, в части логических выражений работает в 8.3 без изменений. Ломается обычно не тип, а данные, которые пришли из старой базы или стороннего файла.

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

Можно ли сделать флажок с тремя состояниями — да, нет, не задано?
Типом Булево — нет, у него только два значения. Используйте составной тип с Неопределено и явно обрабатывайте третье состояние или заведите перечисление из трёх значений.
Почему Строка(Истина) возвращает «Да», а не «Истина»?
Так устроено строковое представление в русской локализации. Для своих подписей используйте Формат с параметрами БЛ и БИ.
Как в отчёте СКД вывести «+» вместо «Да»?
Задайте полю формат БЛ=; БИ=+ в настройках поля набора данных или в условном оформлении.
Когда вместо флажка лучше завести перечисление?
Когда у признака может появиться третье значение или нужны понятные подписи в отчётах. Перечисление легко дополнить, а замена Булево на другой тип потребует переносить данные.
Как быстро найти все элементы с установленным флажком?
В форме списка настройте отбор по реквизиту со значением «Да». В коде — запрос с условием ГДЕ Таблица.Реквизит, без сравнения с ИСТИНА.