Логические значения в 1С 8.3: почему условие падает и как это исправить
Содержание
Тип Булево в 1С хранит ровно два значения: Истина и Ложь. Почти все ошибки с ним сводятся к одному: туда, где платформа ждёт логическое значение, приходит что-то другое — Неопределено, NULL, строка "Да" или число.
Типичный симптом — модуль падает на строке Если ... Тогда с текстом Преобразование значения к типу Булево не может быть выполнено. Ниже — откуда берётся такое значение, как найти источник за пару минут и как написать код, который не ломается.
Что такое Булево в 1С и чем он отличается от других типов
Булево — примитивный тип платформы, как Число, Строка и Дата. У него нет реквизитов и методов, только два литерала.
- ✅
Истина— условие выполнено, флажок установлен. - ❌
Ложь— условие не выполнено, флажок снят. Это же пустое значение типа. - 🔤 В английском синтаксисе встроенного языка —
TrueиFalse. - 📝 Строковое представление в русском интерфейсе —
"Да"и"Нет", а не"Истина"и"Ложь".
Последний пункт — частый источник путаницы. Строка(Истина) вернёт "Да". Значит, если вы выгрузили флажок в текст, а потом сравниваете его с "Истина", сравнение всегда даст Ложь.
Три свойства, которые надо держать в голове:
| Свойство | Как ведёт себя Булево |
|---|---|
| Значение по умолчанию у реквизита | Ложь |
| Значение новой переменной без присваивания | Неопределено, а не Ложь |
ЗначениеЗаполнено(Ложь) | Ложь — для платформы это пустое значение |
Логические операции — НЕ, И, ИЛИ. Приоритет именно в таком порядке: сначала НЕ, потом И, потом ИЛИ. Выражение А ИЛИ Б И В читается как А ИЛИ (Б И В). Если сомневаетесь — ставьте скобки, это бесплатно.
Платформа вычисляет логические выражения сокращённо. В А И Б при А = Ложь часть Б не вычисляется вовсе. На этом построена защитная проверка типа, о ней ниже.
Где встречается булев тип: реквизиты, флажки, настройки
Логическое значение в 1С окружает вас постоянно, даже если вы не программист.
Стандартные реквизиты объектов:
- 🗑
ПометкаУдаления— у справочников и документов; - 📄
Проведен— у проводимых документов; - 📁
ЭтоГруппа— у иерархических справочников с группами; - 🔒
Предопределенный— признак предопределённого элемента.
Реквизиты, которые добавил разработчик. Флажки «Не использовать», «Услуга», «Включать в декларацию» в карточках — почти всегда реквизиты типа Булево.
Константы и функциональные опции. Настройки в разделе Администрирование вида «использовать склады», «вести учёт по сериям» хранятся в константах типа Булево. К ним привязаны функциональные опции: от значения константы зависит, видит ли пользователь поля и команды.
Формы. На форме реквизит Булево выводится полем флажка. Внешний вид задаётся свойством поля: обычный флажок или, в актуальных версиях 8.3, выключатель. Ещё вариант — поле переключателя с двумя подписями «Да» и «Нет».
Запросы и отчёты. В языке запросов есть литералы ИСТИНА и ЛОЖЬ, а в схеме компоновки данных булево поле можно класть в отбор, группировку и условное оформление.
Обмены и интеграции. JSON отдаёт true/false, XML — строки "true"/"false", Excel и CSV — что угодно: "Да", "1", "+", пустая ячейка. Именно на границе с внешними данными тип чаще всего и ломается.
Ошибки с типом Булево: тексты и причины
Вот что видит разработчик или пользователь, и что за этим стоит.
Преобразование значения к типу Булево не может быть выполнено
Платформа получила не-булево значение там, где нужно логическое. Чаще всего:
- 🕳 переменная не инициализирована и равна
Неопределено; - 🔗 поле из левого соединения в запросе вернуло
NULL; - 🔤 в реквизит составного типа или в структуру положили строку;
- 🔢 в условие передали число из внешнего файла.
Условие молча выполняется не так, как ожидали. Ошибки нет, но ветка Если не срабатывает. Причина — сравнение значений разных типов. Истина = "Истина" и Истина = 1 дают Ложь без всякого сообщения.
Неопределено проходит проверку <> Ложь. Код Если Флаг <> Ложь Тогда выполнит ветку, когда флажок вообще не заполнен. Значения разных типов не равны, поэтому Неопределено <> Ложь — это Истина.
Флажок на форме не сохраняется. Пользователь ставит галочку, записывает — после открытия её нет. Обычно поле связано с реквизитом формы, а не с реквизитом объекта: у поля пустой или не тот путь к данным.
Нельзя записать элемент с пустым флажком. Для реквизита Булево включена проверка заполнения. Раз Ложь считается пустым значением, платформа требует поставить галочку. Иногда так сделано намеренно — «согласен с условиями», — но чаще это случайная настройка.
Как найти, откуда пришло неправильное значение
Текст ошибки говорит только «что», но не «откуда». Порядок поиска такой.
- Включите отладку и повторите действие. Конфигуратор: точка останова на строке из ошибки или режим остановки по ошибке в меню
Отладка. - Посмотрите тип значения. В остановке откройте окно вычисления выражения (
Shift+F9) и вычислитеТипЗнч(ИмяПеременной). УвидитеНеопределено,NULL,Строка— значит, причина найдена наполовину. - Пройдите назад по присваиваниям. Найдите, где переменная получила значение: параметр процедуры, поле выборки, элемент структуры, ячейка табличного документа.
- Если значение из запроса — проверьте соединения. Поле из правой таблицы
ЛЕВОГО СОЕДИНЕНИЯпри отсутствии строки вернётNULL. - Если значение из реквизита составного типа — откройте его свойства в конфигураторе. Составной тип «Булево, Строка» позволяет пользователю или обработке записать туда текст.
Когда отладчик недоступен — например, ошибка возникает только у одного пользователя в рабочей базе, — временно выведите тип в сообщение:
Сообщить("Тип значения: " + Строка(ТипЗнч(Флаг)) + ", значение: " + Строка(Флаг));
Для фоновых заданий и регламентных процедур вместо Сообщить пишите в журнал регистрации через ЗаписьЖурналаРегистрации.
Ошибку, которая возникает только у части пользователей, полезно сопоставить с журналом регистрации: часто она проявляется на конкретных элементах справочника, где реквизит так и не заполнили после доработки.
Исправляем ошибки: приведение типов и защитные проверки
Способов несколько, выбирайте по источнику проблемы.
| Способ | Когда подходит | На что смотреть |
|---|---|---|
| Явная инициализация переменной | Переменная объявлена, но не во всех ветках получает значение | Присвойте Ложь сразу после Перем или в начале процедуры |
ЕСТЬ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 без изменений. Ломается обычно не тип, а данные, которые пришли из старой базы или стороннего файла.