При переносе внешних обработок, документов или модулей из одной типовой конфигурации 1С в другую (например, из «1С:Управление торговлей» в «1С:Комплексная автоматизация» или «1С:ERP») разработчики часто сталкиваются с неожиданными сбоями в стандартных механизмах. Одним из наиболее коварных является сбой с текстом «Преобразование значения к типу Булево не может быть выполнено», возникающий в модуле менеджера справочника Номенклатура.
В этой статье мы подробно разберем причины возникновения этой ошибки, проанализируем поведение стандартных функций Библиотеки Стандартных Подсистем (БСП) и рассмотрим несколько надежных способов устранения проблемы как на уровне программного кода, так и на уровне настройки данных.
Давайте проанализируем фрагмент кода, на котором происходит аварийное завершение работы системы:
Если ЗначениеЗаполнено(Номенклатура.ВидНоменклатуры)
И Не ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Номенклатура.ВидНоменклатуры, "СодержитДрагоценныеМатериалы") Тогда
Номенклатура.ДрагоценныеМатериалы.Очистить();
КонецЕсли;
Платформа 1С:Предприятие выбрасывает исключение в момент вычисления логического условия. Оператор Не (логическое отрицание NOT) ожидает, что выражение, стоящее после него, вернет строго логический тип Булево (то есть значение Истина или Ложь).
Однако функция БСП ОбщегоНазначения.ЗначениеРеквизитаОбъекта спроектирована таким образом, что в случае возникновения непредвиденных ситуаций она возвращает значение Неопределено. Попытка выполнить операцию Не Неопределено приводит к фатальной ошибке, так как платформа не может автоматически привести неопределенный тип к логическому.
Выделим три основные причины, почему функция БСП возвращает Неопределено вместо ожидаемого Булево:
ВидыНоменклатуры может отсутствовать реквизит СодержитДрагоценныеМатериалы. Это происходит из-за различий в релизах или отключенных функциональных опций.ВидыНоменклатуры, а не конкретный элемент. У групп справочника этот реквизит отсутствует или не заполнен, что возвращает NULL или Неопределено.ВидНоменклатуры содержит пустую ссылку или ссылку на несуществующий элемент (битую ссылку), чтение физически не может быть выполнено.Для того чтобы обезопасить программный код от подобных падений, мы должны применить принцип оборонительного программирования. Нам нужно переписать логическое условие так, чтобы результат сравнения гарантированно приводился к типу Булево при любом возвращаемом значении.
Давайте посмотрим на пример правильного написания условия:
Если ЗначениеЗаполнено(Номенклатура.ВидНоменклатуры)
И Не (ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Номенклатура.ВидНоменклатуры, "СодержитДрагоценныеМатериалы") = Истина) Тогда
Номенклатура.ДрагоценныеМатериалы.Очистить();
КонецЕсли;
Разберем детально, как работает эта конструкция:
Истина, то выражение в скобках возвращает Истина. Оператор Не превращает его в Ложь, и условие не выполняется.Ложь, то выражение Ложь = Истина возвращает Ложь. Оператор Не превращает его в Истина, и очистка табличной части выполняется.Неопределено (например, реквизита нет в базе), то выражение Неопределено = Истина вернет корректное булево значение Ложь. Оператор Не Ложь превратит его в Истина. Программа продолжит работу без аварийного завершения!Если вы хотите, чтобы логика конфигурации работала именно так, как задумано разработчиками «1С:Управление торговлей», проверьте структуру метаданных в вашей системе «1С:Комплексная автоматизация».
Выполним следующие шаги для проверки:
ВидыНоменклатуры и развернем список его реквизитов.СодержитДрагоценныеМатериалы. Если его нет, это означает, что в вашем релизе конфигурации данный функционал может быть реализован через дополнительные реквизиты и сведения, либо вырезан.Очень часто ошибка возникает из-за того, что внешняя обработка некорректно заполняет реквизит ВидНоменклатуры у создаваемых позиций номенклатуры. Проанализируем алгоритм поиска вида номенклатуры в коде вашей обработки.
Избегайте простого поиска по наименованию без проверки на группу. Рассмотрим пример того, как правильно реализовать поиск элемента во внешней обработке:
НайденныйВид = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Товары");
Если ЗначениеЗаполнено(НайденныйВид) Тогда
Если НайденныйВид.ЭтоГруппа Тогда
ВызватьИсключение "Ошибка: найденная ссылка является группой справочника, выберите элемент!";
Иначе
НовыйОбъект.ВидНоменклатуры = НайденныйВид;
КонецЕсли;
КонецЕсли;
Использование свойства ЭтоГруппа у найденного элемента защитит вашу систему от записи некорректных данных, которые впоследствии ломают стандартные модули менеджеров и объектов конфигурации.