При написании кода для работы с дополнительными реквизитами и сведениями в 1С разработчики часто сталкиваются с ошибкой «Значение не является значением объектного типа». Давайте разберем, почему она возникает, как её исправить и как написать код, который будет работать быстро и стабильно.
Ошибка возникает, когда мы пытаемся получить свойство Значение у объекта, который был найден методом Найти(), но фактически не существует. В платформе 1С метод Найти() коллекции дополнительных реквизитов возвращает Неопределено, если указанное свойство у конкретной номенклатуры не заполнено.
Ваш код пытается обратиться к результату функции через точку: Найти(ДопСвойство).Значение. Если метод возвращает Неопределено, платформа закономерно сообщает, что у Неопределено нет свойства Значение. Различие в поведении между версиями платформы может быть обусловлено изменениями в механизмах кэширования и проверки типов данных, но суть остается прежней — отсутствие проверки возвращаемого результата.
Рассмотрим пошагово, как сделать код безопасным. Чтобы избежать вылета программы, нам необходимо сначала получить результат поиска в переменную, а затем проверить его на Неопределено.
Исправленный вариант кода:
// Сначала находим свойство в коллекции
СтрокаРеквизита = ВыборкаСтрок.Номенклатура.ДополнительныеРеквизиты.Найти(ДопСвойство);
// Обязательно проверяем, что объект был найден
Если СтрокаРеквизита <> Неопределено Тогда
ЗначениеМассы = СтрокаРеквизита.Значение;
Иначе
// Указываем значение по умолчанию, если реквизит не заполнен
ЗначениеМассы = 0;
КонецЕсли;
ЗначениеМассыкг = Формат(ЗначениеМассы, "ЧДЦ=3");
Помимо исправления ошибки, важно обратить внимание на производительность. В исходном примере метод НайтиПоНаименованию вызывается на каждой итерации цикла. Это критическая ошибка проектирования. Поиск по строковому наименованию — ресурсоемкая операция, которая заставляет систему обращаться к базе данных многократно.
Разберем, как правильно оптимизировать этот участок кода:
ДопСвойство необходимо инициализировать один раз до начала перебора строк документа.Запрос к базе данных.Пример оптимизированной структуры кода:
// 1. Поиск выполняем один раз до цикла
ДопСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вага");
ИтогоМассаП = 0;
// 2. Выполняем цикл с уже подготовленным свойством
Для Каждого ВыборкаСтрок Из ЗапросТовары Цикл
// ... логика получения реквизита с проверкой ...
Количество = ВыборкаСтрок.Количество;
Коэффициент = ВыборкаСтрок.Коэффициент;
// расчет массы
МассаП = ЗначениеМассы * Коэффициент * Количество;
ИтогоМассаП = ИтогоМассаП + МассаП;
КонецЦикла;
Для сложных отчетов или при большом количестве строк в документе, мы настоятельно рекомендуем использовать Запрос с ЛЕВЫМ СОЕДИНЕНИЕМ таблиц дополнительных реквизитов. Это позволит получить все необходимые данные разом, минуя необходимость использования метода Найти() в цикле. Это не только исключит ошибку обращения к объектному типу, но и значительно увеличит скорость работы всей обработки.
Таким образом, всегда проверяйте возвращаемые значения методов поиска и стремитесь к тому, чтобы все необходимые данные для вычислений были подготовлены до входа в основные циклы обработки.