Каждый начинающий разработчик в среде «1С:Предприятие» рано или поздно сталкивается с системным сообщением: «Преобразование значения к типу Булево не может быть выполнено». Эта ошибка парализует работу алгоритма и часто вызывает недоумение, ведь на первый взгляд код кажется абсолютно логичным. Сегодня мы подробно разберем, почему возникает эта ошибка, проанализируем внутренние механизмы платформы и рассмотрим несколько эффективных способов решения этой задачи — от простых логических исправлений до продвинутых архитектурных подходов.
Для начала выясним причину такого поведения платформы. В отличие от многих веб-языков программирования (таких как JavaScript, PHP или Python), где практически любое заполненное значение (непустая строка, ненулевое число) может неявно приводиться к логической «истине» (так называемые truthy-значения), в 1С реализована строгая типизация для логических операций.
Это означает, что операторы Если, Пока, условный оператор ?(), а также логические связки И, ИЛИ, НЕ ожидают на входе исключительно значения типа Булево (то есть Истина или Ложь). Никакие неявные преобразования строк, чисел или ссылок в логический тип платформой не поддерживаются.
Проанализируем типичную ошибочную конструкцию, которую часто пишут разработчики:
Если Должность = "бугагалтер" или "буггалтер" Тогда
Должность = "Невролог";
КонецЕсли;
Давайте разберем по шагам, как эту строку интерпретирует компилятор 1С:
или: выражение Должность = "бугагалтер". Результатом этого сравнения гарантированно будет тип Булево (либо Истина, либо Ложь).или и ожидает, что справа от него также будет находиться логическое выражение, возвращающее Булево."буггалтер". Платформа честно пытается выполнить преобразование типа Строка в тип Булево, понимает, что это невозможно сделать без потери логики, и выбрасывает ошибку: «Преобразование значения к типу Булево не может быть выполнено».Теперь, когда мы понимаем физику процесса, давайте изучим правильные варианты написания этого кода.
Самый простой и очевидный способ устранить ошибку — явно прописать операцию сравнения для каждого из условий. Каждая часть логической цепочки должна представлять собой законченное выражение сравнения.
Рассмотрим правильный вариант написания кода:
Если (Должность = "бугагалтер") Или (Должность = "буггалтер") Тогда
Должность = "Невролог";
ИначеЕсли Должность = "прогер" Тогда
Должность = "Программист";
КонецЕсли;
В данном случае оба операнда для оператора Или возвращают логический тип данных, благодаря чему код отрабатывает стабильно и без ошибок. Использование скобок необязательно, но крайне рекомендуется для повышения читаемости кода человеком.
Если список возможных вариантов для сравнения начинает расти (например, нужно отловить пять или шесть различных ошибочных вариантов написания должности), классическое условие Или превратится в громоздкую и нечитаемую конструкцию. В таких случаях на помощь приходит оператор В.
Мы можем собрать все проверяемые строки в массив и проверить вхождение нашей переменной в этот массив. В современной платформе 1С 8.3 это можно сделать изящно с помощью функции СтрРазделить, не загромождая код ручным созданием коллекции:
Если Должность В СтрРазделить("бугагалтер,буггалтер", ",") Тогда
Должность = "Невролог";
ИначеЕсли Должность = "прогер" Тогда
Должность = "Программист";
КонецЕсли;
В этом примере функция СтрРазделить преобразует строку с разделителями-запятыми в массив строк. Оператор В проверяет, содержится ли значение переменной Должность внутри этого массива. Такое решение легко масштабируется и выглядит очень аккуратно.
В процессе обсуждения подобных задач разработчики часто предлагают использовать коллекции для замены значений. Однако здесь легко совершить ошибку. Например, попытка использовать объект СписокЗначений следующим образом приведет к краху программы во время выполнения:
// ВНИМАНИЕ: Данный код ошибочен!
СписокЗамен.Добавить("Невролог", "бугагалтер");
Должность = СписокЗамен.Получить("бугагалтер"); // Ошибка! Метод ожидает индекс (число)
Метод Получить() у объекта СписокЗначений принимает в качестве параметра только числовой индекс элемента, а не текстовый ключ. Для реализации полноценного поиска по принципу «ключ — значение» (словарь) в 1С предназначен объект Соответствие.
Давайте посмотрим на правильный пример реализации этой логики:
// 1. Инициализируем карту замен (лучше вынести в начало модуля или кэшировать)
КартаЗамен = Новый Соответствие;
КартаЗамен.Вставить("бугагалтер", "Невролог");
КартаЗамен.Вставить("буггалтер", "Невролог");
КартаЗамен.Вставить("прогер", "Программист");
// 2. Выполняем поиск соответствия для текущей должности
НайденноеЗначение = КартаЗамен.Получить(Должность);
// 3. Если значение найдено (не равно Неопределено), производим замену
Если НайденноеЗначение <> Неопределено Тогда
Должность = НайденноеЗначение;
КонецЕсли;
Этот способ является наиболее профессиональным и быстродействующим при работе с большими объемами заменяемых данных, так как поиск в объекте Соответствие по ключу происходит практически мгновенно.
Если ваши ключевые слова не содержат пробелов и спецсимволов, их можно использовать в качестве имен свойств объекта Структура. Это позволяет написать очень лаконичный и быстродействующий код:
СловарьЗамен = Новый Структура("бугагалтер,буггалтер,прогер", "Невролог", "Невролог", "Программист");
// Метод Свойство() возвращает Истина, если свойство найдено, и сразу записывает значение в переменную
ПравильноеНаименование = "";
Если СловарьЗамен.Свойство(Должность, ПравильноеНаименование) Тогда
Должность = ПравильноеНаименование;
КонецЕсли;
Здесь мы использовали малоизвестную, но очень удобную возможность метода Свойство() — передачу второго необязательного параметра, в который автоматически помещается значение найденного свойства.
Помимо явных синтаксических ошибок в написании условий, разработчики сталкиваются с этой проблемой в ряде других типовых сценариев. Рассмотрим их, чтобы вы могли предостеречь себя от возможных багов.
Если в условии вызывается пользовательская функция, возвращающая признак проверки:
Если МояПроверкаВыполнена(Сотрудник) Тогда
// Код обработки
КонецЕсли;
Но внутри самой функции разработчик забыл написать дефолтный возврат (например, в случае, когда управление обходит все ветки условий ветвления), функция неявно вернет значение Неопределено. Попытка подставить Неопределено в условие Если вызовет ровно ту же самую ошибку преобразования к Булево.
При передаче параметров между клиентом и сервером часто используют структуры. Если в коде написано:
Если ПараметрыПроверки.ТолькоАктивные Тогда
// Действие...
КонецЕсли;
Если на этапе формирования структуры свойство ТолькоАктивные не было инициализировано или туда по ошибке передали Неопределено, алгоритм упадет с ошибкой преобразования к Булево. Безопасный вариант вызова выглядит так:
Если ПараметрыПроверки.Свойство("ТолькоАктивные") И ПараметрыПроверки.ТолькоАктивные Тогда
// Действие...
КонецЕсли;
Если вы получаете данные из базы данных (особенно при использовании левых соединений в запросе) и затем напрямую передаете их в код без предварительной проверки:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЭтоПометкаУдаления Тогда // Здесь может прийти NULL
Продолжить;
КонецЕсли;
КонецЦикла;
Попытка проверить значение NULL в условном операторе гарантированно вызовет ошибку преобразования к Булево. Всегда обрабатывайте такие поля в самом запросе с помощью функции ЕСТЬNULL(Поле, Ложь).
Подводя итог, можно сказать, что ошибка преобразования к типу Булево всегда указывает на невнимательность при работе с типами данных. Будьте бдительны при написании условий, используйте современные конструкции платформы 1С для сопоставления данных и всегда проверяйте типы переменных в отладчике при возникновении спорных ситуаций.