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