Почему возникает ошибка «Значение не является значением объектного типа» при работе с допреквизитами?

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

При написании кода для работы с дополнительными реквизитами и сведениями в 1С разработчики часто сталкиваются с ошибкой «Значение не является значением объектного типа». Давайте разберем, почему она возникает, как её исправить и как написать код, который будет работать быстро и стабильно.

Суть проблемы

Ошибка возникает, когда мы пытаемся получить свойство Значение у объекта, который был найден методом Найти(), но фактически не существует. В платформе 1С метод Найти() коллекции дополнительных реквизитов возвращает Неопределено, если указанное свойство у конкретной номенклатуры не заполнено.

Ваш код пытается обратиться к результату функции через точку: Найти(ДопСвойство).Значение. Если метод возвращает Неопределено, платформа закономерно сообщает, что у Неопределено нет свойства Значение. Различие в поведении между версиями платформы может быть обусловлено изменениями в механизмах кэширования и проверки типов данных, но суть остается прежней — отсутствие проверки возвращаемого результата.

Как исправить ошибку

Рассмотрим пошагово, как сделать код безопасным. Чтобы избежать вылета программы, нам необходимо сначала получить результат поиска в переменную, а затем проверить его на Неопределено.

Исправленный вариант кода:


// Сначала находим свойство в коллекции
СтрокаРеквизита = ВыборкаСтрок.Номенклатура.ДополнительныеРеквизиты.Найти(ДопСвойство);

// Обязательно проверяем, что объект был найден
Если СтрокаРеквизита <> Неопределено Тогда
    ЗначениеМассы = СтрокаРеквизита.Значение;
Иначе
    // Указываем значение по умолчанию, если реквизит не заполнен
    ЗначениеМассы = 0; 
КонецЕсли;

ЗначениеМассыкг = Формат(ЗначениеМассы, "ЧДЦ=3");

Оптимизация: почему код нельзя оставлять внутри цикла

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

Разберем, как правильно оптимизировать этот участок кода:

  1. Выносим поиск за пределы цикла: Переменную ДопСвойство необходимо инициализировать один раз до начала перебора строк документа.
  2. Минимизируем обращения к БД: Получение дополнительных реквизитов «на лету» внутри цикла — это «медленный» путь. В идеале, подобные данные нужно получать сразу в составе Запрос к базе данных.

Пример оптимизированной структуры кода:


// 1. Поиск выполняем один раз до цикла
ДопСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вага");

ИтогоМассаП = 0;

// 2. Выполняем цикл с уже подготовленным свойством
Для Каждого ВыборкаСтрок Из ЗапросТовары Цикл
    // ... логика получения реквизита с проверкой ...
    Количество = ВыборкаСтрок.Количество;
    Коэффициент = ВыборкаСтрок.Коэффициент;
    
    // расчет массы
    МассаП = ЗначениеМассы * Коэффициент * Количество;
    ИтогоМассаП = ИтогоМассаП + МассаП;
КонецЦикла;

Рекомендация по подходу

Для сложных отчетов или при большом количестве строк в документе, мы настоятельно рекомендуем использовать Запрос с ЛЕВЫМ СОЕДИНЕНИЕМ таблиц дополнительных реквизитов. Это позволит получить все необходимые данные разом, минуя необходимость использования метода Найти() в цикле. Это не только исключит ошибку обращения к объектному типу, но и значительно увеличит скорость работы всей обработки.

Таким образом, всегда проверяйте возвращаемые значения методов поиска и стремитесь к тому, чтобы все необходимые данные для вычислений были подготовлены до входа в основные циклы обработки.

← На главную