При разработке и доработке конфигураций 1С разработчики часто сталкиваются с ошибкой времени выполнения вида: «Поле объекта не обнаружено (ИмяОбъекта)». Особенно часто данная ситуация возникает в процедуре ОбработкаПроведения модуля объекта при попытке проверить тип или вид номенклатуры через менеджер перечислений или реквизит справочника.
Разберем типичный пример кода, в котором возникает эта ошибка, выясним первопричины сбоя и рассмотрим правильные варианты исправления.
Рассмотрим фрагмент кода из модуля объекта документа, в котором происходит сбой:
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиМатериалов.Записывать = Истина;
Движения.СтоимостьМатериалов.Записывать = Истина;
Для Каждого ТекСтрокаПереченьНоменклатуры Из ПереченьНоменклатуры Цикл
Если ТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Материал Тогда
// регистр ОстаткиМатериалов Расход
Движение = Движения.ОстаткиМатериалов.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Материал = ТекСтрокаПереченьНоменклатуры.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ТекСтрокаПереченьНоменклатуры.Количество;
// регистр СтоимостьМатериалов Расход
Движение = Движения.СтоимостьМатериалов.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Материал = ТекСтрокаПереченьНоменклатуры.Номенклатура;
Движение.Стоимость = ТекСтрокаПереченьНоменклатуры.Количество * ТекСтрокаПереченьНоменклатуры.Стоимость;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
При выполнении строки условия платформа выдает исключение: {Документ.ОказаниеУслуг.МодульОбъекта(6)}: Поле объекта не обнаружено (ВидыНоменклатуры). Это свидетельствует о том, что в глобальной коллекции Перечисления отсутствует менеджер с именем ВидыНоменклатуры.
ВидНоменклатуры, а в коде использовано множественное число — Перечисления.ВидыНоменклатуры. Также возможна обратная ситуация.ВидНоменклатуры в справочнике Номенклатура может ссылаться не на перечисление, а на одноименный справочник (Справочники.ВидыНоменклатуры). В этом случае сравнение со значением перечисления некорректно.Перечисления, она перекрывает системный менеджер.Разберем по шагам, как выявить точную причину ошибки:
ВидНоменклатуры, исправляем код программы на Перечисления.ВидНоменклатуры.Материал.Материал существует и написано без опечаток (например, не Материалы).Если, запустим режим «1С:Предприятие» и вызовем окно «Вычислить выражение» (Shift + F9). Проверим по отдельности выражения:
ПеречисленияПеречисления.ВидыНоменклатурыТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатурыОбратим внимание: модуль объекта документа компилируется и исполняется исключительно на стороне сервера. Директивы компиляции (такие как &НаКлиенте, &НаСервере) используются только в модулях управляемых форм и команд. Попытка прописать директивы компиляции в модуле объекта является синтаксической ошибкой.
В стандартах разработки 1С рекомендуется избегать прямого обращения к менеджерам перечислений и разыменования ссылок через точку в циклах.
Вариант 1. Использование функции ПредопределенноеЗначение
Для получения значения перечисления платформой предусмотрена функция ПредопределенноеЗначение, которая проверяется на этапе компиляции:
Если ТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатуры = ПредопределенноеЗначение("Перечисление.ВидыНоменклатуры.Материал") Тогда
// Формирование движений
КонецЕсли;
Вариант 2. Формирование движений с помощью запроса (Рекомендуемый подход)
Обращение через точку в цикле ТекСтрока.Номенклатура.ВидНоменклатуры генерирует отдельный SQL-запрос к базе данных для каждой строки документа. Чтобы избежать падения производительности, проведение документа следует выполнять через запрос к табличной части с фильтрацией по значению перечисления через литерал ЗНАЧЕНИЕ:
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиМатериалов.Записывать = Истина;
Движения.СтоимостьМатериалов.Записывать = Истина;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Номенклатура КАК Материал,
| &Склад КАК Склад,
| Док.Количество КАК Количество,
| Док.Количество * Док.Стоимость КАК Стоимость
|ИЗ
| Документ.ОказаниеУслуг.ПереченьНоменклатуры КАК Док
|ГДЕ
| Док.Ссылка = &Ссылка
| И Док.Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Материал)";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("Склад", Склад);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Движение по регистру ОстаткиМатериалов
Движение = Движения.ОстаткиМатериалов.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Материал = Выборка.Материал;
Движение.Склад = Выборка.Склад;
Движение.Количество = Выборка.Количество;
// Движение по регистру СтоимостьМатериалов
Движение = Движения.СтоимостьМатериалов.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Материал = Выборка.Материал;
Движение.Стоимость = Выборка.Стоимость;
КонецЦикла;
КонецПроцедуры
Такой подход исключает множественные запросы к базе данных, защищает от ошибок при обращении к несуществующим свойствам объектов и гарантирует высокую скорость проведения документа.