Как исправить ошибку «Преобразование значения к типу Булево не может быть выполнено» в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Рано или поздно каждый разработчик в среде «1С:Предприятие» сталкивается с ошибкой «Преобразование значения к типу Булево не может быть выполнено». Эта проблема является одной из самых частых во встроенном языке. Она мгновенно останавливает работу сеанса пользователя и вызывает аварийное завершение процедуры.

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

Выясняем причину: почему платформа 1С выдает ошибку?

Для начала давайте разберемся с технической логикой работы платформы 1С. В отличие от таких гибких веб-языков, как JavaScript или PHP, во встроенном языке 1С нет концепции так называемых «правдоподобных» (truthy) и «ложных» (falsy) значений для большинства типов данных.

Что это значит на практике? Если в JavaScript мы можем написать конструкцию if (myVariable), и она успешно выполнится, даже если в переменной находится объект, строка или пустое значение, то в 1С этот фокус не пройдет. Платформа 1С требует, чтобы в логическом условии (будь то оператор Если ... Тогда или тернарный оператор ?()) строго находилось значение логического типа — либо Истина, либо Ложь.

Платформа не умеет автоматически (неявно) приводить к типу Булево следующие типы данных:

  1. Неопределено — значение по умолчанию для неинициализированных переменных или незаполненных реквизитов.
  2. NULL — значение, приходящее из баз данных (например, при левом соединении в запросах).
  3. Пустые ссылки (например, Справочники.Номенклатура.ПустаяСсылка()).
  4. Строковые значения (за исключением текстовых литералов "True"/"False" или "Истина"/"Ложь" при явном преобразовании).

Единственное исключение разработчики платформы сделали для типа Число: число 0 неявно приводится к значению Ложь, а любое другое число — к Истина. Однако писать код с расчетом на эту особенность крайне не рекомендуется, так как это снижает его читаемость и усложняет аудит.

Если в логический оператор передается любое из перечисленных выше некорректных значений, выполнение программы прерывается с ошибкой преобразования.

Анализируем ситуацию из практики

Рассмотрим реальный пример, с которым столкнулся автор темы на форуме. В модуле формы обработки «Печать этикеток» на строке 112 возникает сбой:


ЭтикеткаОбласть.Параметры.Артикул = СтрокаИзСписка.Номенклатура.Артикул + ?(Демо, "-DEMO", "");

На первый взгляд, код выглядит вполне логично. Переменная Демо должна содержать булевский флаг (да или нет), который определяет, нужно ли добавлять суффикс "-DEMO" к артикулу. Однако в процессе работы в какой-то момент времени в переменную Демо попадает значение другого типа — чаще всего Неопределено.

Это может произойти по нескольким причинам:

  1. Реквизит на форме не был инициализирован при открытии.
  2. Значение было затерто в коде из-за конфликта имен (например, когда локальная переменная внутри процедуры перекрыла реквизит формы с тем же именем Демо).
  3. Значение передавалось из структуры параметров, где этот ключ отсутствовал, из-за чего метод чтения вернул Неопределено.

Когда управление доходит до тернарного оператора ?(), платформа пытается вычислить первый параметр. Видя там Неопределено вместо ожидавшегося Истина или Ложь, 1С аварийно завершает работу.

Варианты исправления ошибки: от простых к профессиональным

Рассмотрим подробнее по шагам, как мы можем обезопасить наш код и обойти эту ошибку.

Способ 1. Использование безопасного сравнения с «Истина» (Самый элегантный паттерн)

Это наиболее лаконичный и профессиональный вариант решения проблемы. Мы модифицируем условие внутри тернарного оператора следующим образом:


ЭтикеткаОбласть.Параметры.Артикул = СтрокаИзСписка.Номенклатура.Артикул + ?(Демо = Истина, "-DEMO", "");

Давайте проанализируем, почему этот простой прием гарантирует стабильность работы программы:

Таким образом, результатом выражения Демо = Истина всегда гарантированно будет чистое булево значение. Тернарный оператор ?() выполнится корректно при любых обстоятельствах.

Способ 2. Предварительная инициализация переменной

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


Если Демо = Неопределено Тогда
    Демо = Ложь;
КонецЕсли;

ЭтикеткаОбласть.Параметры.Артикул = СтрокаИзСписка.Номенклатура.Артикул + ?(Демо, "-DEMO", "");

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

Способ 3. Максимально жесткая и безопасная проверка типов

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

Проанализируем этот подход на примере следующего алгоритма:


ПрефиксАртикула = "";
Если ЗначениеЗаполнено(СтрокаИзСписка.Номенклатура.Артикул) Тогда
    ПрефиксАртикула = Строка(СтрокаИзСписка.Номенклатура.Артикул);
КонецЕсли;

СуффиксАртикула = "";
Если ТипЗнч(Демо) = Тип("Булево") Тогда
    Если Демо Тогда
        СуффиксАртикула = "-DEMO";
    КонецЕсли;
КонецЕсли;

ЭтикеткаОбласть.Параметры.Артикул = ПрефиксАртикула + СуффиксАртикула;

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

  1. Сначала мы принудительно приводим артикул номенклатуры к строке через функцию Строка(), защищаясь от возможных пустых ссылок или неопределенных значений в базе данных.
  2. Затем мы выполняем явную проверку типа переменной Демо с помощью функции ТипЗнч(). Только если тип строго совпадает с системным типом Булево, мы позволяем программе проанализировать логическое условие внутри переменной.

Важно: Подводные камни стандартных функций 1С

Пытаясь исправить эту ошибку самостоятельно, начинающие разработчики часто совершают две типичные ошибки, используя стандартные функции платформы:

1. Ловушка функции ЗначениеЗаполнено()

Иногда в коде можно встретить следующую попытку проверки флага: Если ЗначениеЗаполнено(Демо) Тогда.... Будьте осторожны! Во встроенном языке 1С вызов ЗначениеЗаполнено(Ложь) возвращает Истина. Платформа считает системное значение Ложь полностью определенным и заполненным логическим значением (в отличие от пустой строки или Неопределено). Использование этой функции для проверки булевых переменных приведет к логическим ошибкам в работе программы.

2. Ограниченность функции приведения типов Булево()

В 1С существует функция явного преобразования типов Булево(). Но она не спасет вас, если вы передадите в нее пустое значение. При попытке выполнить Булево(Неопределено) или Булево(NULL) платформа выбросит точно такую же ошибку времени выполнения. Эта функция предназначена в основном для преобразования чисел (например, Булево(1) вернет Истина) или строковых значений "Истина"/"Ложь".

Резюме

Для предотвращения ошибок приведения типов придерживайтесь простых правил совместной работы с логическими выражениями в 1С:

← На главную