Как исправить ошибку «Поле объекта не обнаружено (ВидыНоменклатуры)» при проведении документа в 1С?

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

При разработке и доработке конфигураций 1С разработчики часто сталкиваются с ошибкой времени выполнения вида: «Поле объекта не обнаружено (ИмяОбъекта)». Особенно часто данная ситуация возникает в процедуре ОбработкаПроведения модуля объекта при попытке проверить тип или вид номенклатуры через менеджер перечислений или реквизит справочника.

Разберем типичный пример кода, в котором возникает эта ошибка, выясним первопричины сбоя и рассмотрим правильные варианты исправления.

Анализ исходного кода и сути ошибки

Рассмотрим фрагмент кода из модуля объекта документа, в котором происходит сбой:


Процедура ОбработкаПроведения(Отказ, Режим)
    Движения.ОстаткиМатериалов.Записывать = Истина;
    Движения.СтоимостьМатериалов.Записывать = Истина;
    
    Для Каждого ТекСтрокаПереченьНоменклатуры Из ПереченьНоменклатуры Цикл
        Если ТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Материал Тогда     
            // регистр ОстаткиМатериалов Расход
            Движение = Движения.ОстаткиМатериалов.Добавить();
            Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
            Движение.Период = Дата;
            Движение.Материал = ТекСтрокаПереченьНоменклатуры.Номенклатура;
            Движение.Склад = Склад;
            Движение.Количество = ТекСтрокаПереченьНоменклатуры.Количество;
            
            // регистр СтоимостьМатериалов Расход
            Движение = Движения.СтоимостьМатериалов.Добавить();
            Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
            Движение.Период = Дата;
            Движение.Материал = ТекСтрокаПереченьНоменклатуры.Номенклатура;
            Движение.Стоимость = ТекСтрокаПереченьНоменклатуры.Количество * ТекСтрокаПереченьНоменклатуры.Стоимость;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

При выполнении строки условия платформа выдает исключение: {Документ.ОказаниеУслуг.МодульОбъекта(6)}: Поле объекта не обнаружено (ВидыНоменклатуры). Это свидетельствует о том, что в глобальной коллекции Перечисления отсутствует менеджер с именем ВидыНоменклатуры.

Основные причины возникновения ошибки

  1. Несовпадение имени объекта метаданных: В дереве метаданных перечисление может называться в единственном числе — ВидНоменклатуры, а в коде использовано множественное число — Перечисления.ВидыНоменклатуры. Также возможна обратная ситуация.
  2. Несоответствие типов данных: Реквизит ВидНоменклатуры в справочнике Номенклатура может ссылаться не на перечисление, а на одноименный справочник (Справочники.ВидыНоменклатуры). В этом случае сравнение со значением перечисления некорректно.
  3. Опечатки и латинские символы: При создании объекта в конфигураторе русские буквы (например, «С», «е», «о», «а», «р») могли быть случайно введены в латинской раскладке клавиатуры. Внешне имя выглядит идентично, но для платформы это два разных идентификатора.
  4. Не обновлена конфигурация базы данных: Объект или его значение были добавлены в конфигураторе, но конфигурация базы данных не была обновлена (не была нажата клавиша F7 или кнопка «Обновить конфигурацию базы данных»).
  5. Перекрытие системного контекста: Если ранее в коде была объявлена локальная переменная с именем Перечисления, она перекрывает системный менеджер.

Пошаговый алгоритм диагностики и решения

Разберем по шагам, как выявить точную причину ошибки:

  1. Проверяем дерево метаданных в конфигураторе: Откроем ветку Перечисления и проверим точное имя объекта. Если перечисление называется ВидНоменклатуры, исправляем код программы на Перечисления.ВидНоменклатуры.Материал.
  2. Проверяем значения перечисления: Развернем список значений перечисления и убедимся, что значение Материал существует и написано без опечаток (например, не Материалы).
  3. Используем отладчик: Установим точку останова на строке с условием Если, запустим режим «1С:Предприятие» и вызовем окно «Вычислить выражение» (Shift + F9). Проверим по отдельности выражения:
    • Перечисления
    • Перечисления.ВидыНоменклатуры
    • ТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатуры
    Отладчик наглядно покажет тип реквизита и доступность полей.

Важные нюансы контекста выполнения и директив

Обратим внимание: модуль объекта документа компилируется и исполняется исключительно на стороне сервера. Директивы компиляции (такие как &НаКлиенте, &НаСервере) используются только в модулях управляемых форм и команд. Попытка прописать директивы компиляции в модуле объекта является синтаксической ошибкой.

Оптимальные и рекомендуемые способы написания кода

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

Вариант 1. Использование функции ПредопределенноеЗначение

Для получения значения перечисления платформой предусмотрена функция ПредопределенноеЗначение, которая проверяется на этапе компиляции:


Если ТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатуры = ПредопределенноеЗначение("Перечисление.ВидыНоменклатуры.Материал") Тогда
    // Формирование движений
КонецЕсли;

Вариант 2. Формирование движений с помощью запроса (Рекомендуемый подход)

Обращение через точку в цикле ТекСтрока.Номенклатура.ВидНоменклатуры генерирует отдельный SQL-запрос к базе данных для каждой строки документа. Чтобы избежать падения производительности, проведение документа следует выполнять через запрос к табличной части с фильтрацией по значению перечисления через литерал ЗНАЧЕНИЕ:


Процедура ОбработкаПроведения(Отказ, Режим)
    
    Движения.ОстаткиМатериалов.Записывать = Истина;
    Движения.СтоимостьМатериалов.Записывать = Истина;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Док.Номенклатура КАК Материал,
        |	&Склад КАК Склад,
        |	Док.Количество КАК Количество,
        |	Док.Количество * Док.Стоимость КАК Стоимость
        |ИЗ
        |	Документ.ОказаниеУслуг.ПереченьНоменклатуры КАК Док
        |ГДЕ
        |	Док.Ссылка = &Ссылка
        |	И Док.Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Материал)";
    
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    Запрос.УстановитьПараметр("Склад", Склад);
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Движение по регистру ОстаткиМатериалов
        Движение = Движения.ОстаткиМатериалов.Добавить();
        Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
        Движение.Период = Дата;
        Движение.Материал = Выборка.Материал;
        Движение.Склад = Выборка.Склад;
        Движение.Количество = Выборка.Количество;
        
        // Движение по регистру СтоимостьМатериалов
        Движение = Движения.СтоимостьМатериалов.Добавить();
        Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
        Движение.Период = Дата;
        Движение.Материал = Выборка.Материал;
        Движение.Стоимость = Выборка.Стоимость;
    КонецЦикла;
    
КонецПроцедуры

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

← На главную