Значение не приводится к типу Булево: ищем источник в коде и данных
Содержание
Ошибка с типом Булево означает одно: платформа ждала Истина или Ложь, а получила что-то другое. Чаще всего это пустая ссылка, Неопределено, NULL из запроса или строка вроде "Да", которую никто не преобразовал. Лечится в три хода: найти строку модуля, посмотреть, что пришло в переменную, и привести значение к логическому виду там, где оно рождается.
Ниже разбор для платформы 8.3 с интерфейсом «Такси». Текст ошибки в разных ситуациях звучит по-разному: «Преобразование значения к типу Булево невозможно», «Несоответствие типов», «Значение не является значением типа Булево». Причина у них общая, поэтому и лечение общее.
Что такое Булево и когда платформа его требует
Булево — логический тип. У него ровно два значения: Истина и Ложь. Флажок в форме, условие в Если, условие цикла Пока, поле «Использование» в справочнике — везде там, где нужен ответ «да или нет», платформа работает с этим типом.
Строгость у платформы выборочная. Часть преобразований она делает молча:
- число
0превращается вЛожь, любое другое число — вИстина; - строки
"Да"и"Истина"при явном вызовеБулево("Да")даютИстина, а"Нет"и"Ложь"даютЛожь.
А вот Неопределено, NULL, пустая ссылка и произвольные строки в логическое значение не превращаются. Здесь и возникает исключение.
Правило для себя: платформа прощает числа и «Да/Нет», но не прощает «ничего». Любая пустота — главный подозреваемый.
Где тип Булево прячется неявно
Не каждое обращение к нему видно в коде. Булево требуется:
- в условии
Если,ИначеЕсли,Пока; - в операторах
И,ИЛИ,НЕ; - в тернарном выражении
?(Условие, Да, Нет); - при записи в реквизит с типом Булево;
- в условии
ГДЕзапроса, если выражение возвращает не логическое значение.
Поэтому ошибка бывает в строке, где «вроде нет ни одного логического значения». Достаточно, чтобы вместо него подставилась переменная с неподходящим содержимым.
Откуда берётся неподходящее значение
Разработчики 1С сталкиваются с ограниченным набором сценариев. Знание этого набора сокращает поиск с часа до пяти минут.
Результат обращения к реквизиту через точку
Самый частый случай. Обращение вида Документ.Контрагент.Договор.Действует внутри условия. Если на каком-то звене цепочки ссылка пустая, на выходе будет не Ложь, а значение, которое в условии использовать нельзя. Проверка: подставьте цепочку в отладчике по частям.
NULL из результата запроса
Запрос с левым соединением возвращает NULL там, где парной записи нет. Если такое поле попало в условие, ошибка неизбежна. Типичная картина: отчёт работает на тестовой базе, где все данные заполнены, и падает на рабочей, где у части контрагентов нет договора.
Значение из внешнего источника
Загрузка из Excel
, CSV, обмен через XML или веб-сервис приносят текст. В ячейке написано «Да», «1», «+» или «TRUE», а в реквизит с типом Булево надо положить Истина. Прямое присваивание строки либо падает, либо даёт неверный результат.
Составной тип и забытая проверка
Реквизит может принимать несколько типов: Булево, Число, Строка. До первой записи в нём лежит Неопределено. Код, написанный в расчёте на «там всегда флажок», ломается на первой же новой строке.
Параметры процедур
Процедура объявила параметр как логический, а вызывающий код передал в него результат функции, которая в некоторых ветках возвращает Неопределено — например, потому что в одной из веток забыли Возврат. Ошибка проявится в чужом модуле, далеко от настоящей причины.
Как найти место ошибки: журнал и отладчик
Сначала узнайте, где именно падает. Угадывать по тексту не нужно: платформа показывает стек вызова.
Шаг 1. Прочитайте стек в окне ошибки
В сообщении будет имя модуля, процедуры и номер строки, например {ОбщийМодуль.РаботаСДоговорами.Модуль(124)}. Нажмите «Подробно» и скопируйте весь текст. Номер строки — это точка входа.
Шаг 2. Загляните в журнал регистрации
Если ошибка ушла и пользователь не помнит, что делал, поможет журнал. В режиме 1С:Предприятие он открывается из раздела Администрирование (подраздел обслуживания), в Конфигураторе — через меню Администрирование → Журнал регистрации. Журнал доступен пользователям с правом администрирования.
Отберите события так:
- Задайте период — час-два вокруг времени жалобы.
- В отборе по уровню оставьте
Ошибка. - Добавьте отбор по пользователю, если жалоба от одного человека.
- Откройте событие «Ошибка выполнения…» и прочитайте комментарий — там будет тот же стек, что и в окне.
Журнал полезен ещё и тем, что показывает серию ошибок. Если одна и та же строка падает у десяти пользователей, значит причина в данных, а не в действиях одного оператора.
Шаг 3. Остановитесь на ошибке в отладчике
Откройте базу в Конфигураторе и запустите отладку (F5). В меню Отладка включите остановку по ошибке — платформа прервёт выполнение на строке, которая падает, и покажет локальные переменные. Дальше два действия:
- наведите курсор на переменную из условия — увидите её значение и тип;
- нажмите
Shift+F9и вычислите выражение целиком, по частям.
Если в окне «Вычислить» видно Неопределено или NULL, источник найден. Остаётся выяснить, почему туда не попало логическое значение.
Отладка на рабочей базе тормозит сеанс и блокирует пользователей, которые ждут ответа от сервера. Для расследования берите копию базы.
ЕСТЬNULL(Поле, Ложь) в самом запросе.Булево() или собственной функцией разбора перед присвоением.Число().Проверка условий в коде и запросах
Когда место найдено, переходим к исправлению. Принцип один: превращайте «что-то» в Истина или Ложь как можно раньше, там, где значение появилось, а не в конечном условии.
Условия в модуле
Проверяйте заполненность перед использованием:
Если ЗначениеЗаполнено(Договор) Тогда
Действует = Договор.Действует;
Иначе
Действует = Ложь;
КонецЕсли;
Если Действует Тогда
// дальнейшая обработка
КонецЕсли;
Если значение приходит снаружи как строка, используйте явное преобразование:
Функция ТекстВБулево(Текст)
Нормализованный = НРег(СокрЛП(Текст));
Возврат Нормализованный = "да"
Или Нормализованный = "истина"
Или Нормализованный = "1"
Или Нормализованный = "+";
КонецФункции
Функция возвращает Ложь на любой «непонятный» вход, и это сознательный выбор: обработка не падает, а неверные строки легко найти по отчёту после загрузки. Если для вас пустой текст должен быть ошибкой, а не Ложью, добавьте отдельную проверку и выдайте сообщение пользователю.
Условия в запросе
NULL в запросе обрабатывается на стороне запроса. Два рабочих приёма.
Первый — подстановка значения по умолчанию:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
ЕСТЬNULL(Договоры.Действует, ЛОЖЬ) КАК Действует
ИЗ
Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК Договоры
ПО Договоры.Владелец = Контрагенты.Ссылка
Второй — явное выражение выбора, когда нужна своя логика:
ВЫБОР
КОГДА Договоры.Ссылка ЕСТЬ NULL ТОГДА ЛОЖЬ
ИНАЧЕ Договоры.Действует
КОНЕЦ
Оба варианта делают то же самое: к моменту, когда результат попадёт в код, поле всегда содержит логическое значение.
Если запрос используется в схеме компоновки данных, поле с ЕСТЬNULL удобно сразу задать в наборе данных. Тогда условия отбора в отчёте не будут падать на пустых строках.
Три приёма, которые не стоит забывать
Опытный разработчик держит в голове три вещи, без которых разбор неполон:
- Явно сравнивать с
Истинане нужно —Если Флаг = Истина Тогдаизбыточно. Но проверить тип стоит:ТипЗнч(Флаг) = Тип("Булево"). - Не смешивать
НеопределеноиЛожь. Это разные состояния: «не знаем» и «нет». Если логике нужны три состояния, заводите перечисление, а не флажок. - Не писать функцию, у которой есть ветка без
Возврат. Вызывающий код получитНеопределенои упадёт в чужом месте.
Исправление уже испорченных данных
Иногда причина не в коде, а в записях, которые давно лежат в базе. Реквизит принимает составной тип, в нём лежат строки или числа, и каждый отчёт, который эти данные читает, падает.
Как найти плохие записи
Для начала посмотрите, что лежит в реквизите. Запрос по справочнику с условием на тип поможет отделить записи с нормальным значением от остальных. Практичнее выгрузить список в табличный документ и отсортировать: аномалии видны сразу.
Если реквизит одного типа — Булево, — испорченных записей быть не может: платформа не даст положить в него другой тип. Тогда проблема в расчёте, который строится поверх этого реквизита.
Как исправить
Исправляйте обработкой, а не вручную в форме, если записей больше десятка:
- Сделайте копию базы
или выгрузку
.dt. - Отберите записи с неверным значением.
- Для каждой запишите правильное логическое значение, определив его по содержимому: «Да» →
Истина, пусто →Ложь. - Запись выполняйте с отключёнными проверками и обработчиками только если вы точно знаете, что они не нужны; иначе изменения запустят пересчёты и обмены.
Перед массовой правкой данных сделайте резервную копию. Обработка, которая меняет тысячу записей, откатывается только из копии.
После правки прогоните тот сценарий, на котором падало. Если ошибка осталась, значит, источник не в данных — вернитесь к коду.
Как не получить ошибку снова
Профилактика сводится к привычкам при написании кода и настройке данных.
Привычки разработчика
- Задавайте начальное значение логической переменной:
Результат = Ложь;. Тогда у функции всегда есть что вернуть. - Все ветки функции заканчивайте
Возврат. Включите в отладчике просмотр результата перед выходом. - Не используйте реквизиты составного типа там, где достаточно флажка. Чем уже тип, тем меньше сюрпризов.
- Поля запроса, которые уйдут в условия, оборачивайте в
ЕСТЬNULL. - Внешние данные приводите к типу на границе: сразу после чтения файла или ответа сервиса.
Привычки пользователя и администратора
- Не загружайте данные из Excel в реквизиты, не проверив, что в колонке нет текста вместо «Да/Нет».
- После обновления конфигурации проверяйте типовые отчёты и документы на тестовой копии.
- Смотрите журнал регистрации раз в неделю: серия одинаковых ошибок видна сразу, пока ей не пользуются все сотрудники.
Когда не надо лезть в код
Если ошибка появилась после обновления типовой конфигурации и код модуля вы не писали, не правьте типовой модуль «на месте». Такая правка слетит при следующем обновлении, а конфигурация перейдёт на поддержку с изменениями. Безопаснее оформить расширение или обратиться к тому, кто сопровождает базу. Если правка не ваша, а источник в данных — исправляйте данные.
Сводная таблица
| Источник значения | Что приходит | Что делать |
|---|---|---|
| Пустая ссылка в цепочке | Неопределено | Проверить ЗначениеЗаполнено до обращения |
| Запрос, левое соединение | NULL | ЕСТЬNULL(Поле, ЛОЖЬ) в запросе |
| Файл, обмен | Строка «Да/Нет», «1» | Своя функция разбора |
| Составной реквизит | Неопределено до записи | Ограничить тип или проверять тип |
Функция без Возврат | Неопределено | Задать значение по умолчанию |
Частые вопросы
Чем Булево отличается от флажка в форме?
Истина как поставленную галочку.Можно ли хранить в реквизите три состояния: да, нет, не знаю?
Почему ошибка есть у одного пользователя, а у других нет?
Что делать, если ошибка в типовом отчёте?
Как быстро проверить значение в отладчике?
Shift+F9. Там видно и значение, и его тип.