Почему возникает ошибка «Поле объекта не обнаружено» при формировании движений документа в 1С?

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

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

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

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


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

При попытке проведения этого документа платформа последовательно генерирует исключения:

  1. Поле объекта не обнаружено (ОстаткиТоваров) в строке добавления прихода;
  2. Поле объекта не обнаружено (ОстаткиТовара) в завершающей строке взведения флага записи.

Проанализируем ситуацию детально: здесь допущено сразу три типичные ошибки, которые блокируют корректное формирование записей.

Причина 1. Путаница между коллекцией «Движения» и переменной «Движение»

Посмотрим на строку обращения к регистру накопления:

Движение = Движение.ОстаткиТоваров.ДобавитьПриход();

Выясним причину ошибки: переменная Движение несколькими строками выше была инициализирована как строка регистра сведений через вызов Движения.ЗакупочныеЦены.Добавить(). Соответственно, переменная Движение содержит объект типа РегистрСведенийЗапись.ЗакупочныеЦены. У отдельной записи регистра сведений нет и не может быть свойства с именем другого регистра ОстаткиТоваров.

Доступ ко всем регистрам, по которым документ совершает движения, осуществляется строго через системное свойство документа во множественном числе — Движения (коллекция КоллекцияДвижений). Таким образом, правильное обращение должно выглядеть как Движения.ОстаткиТоваров.

Причина 2. Несоответствие имен метаданных и ошибки в окончаниях

Обратим внимание на окончание процедуры проведения:

Движение.ОстаткиТовара.Записывать = Истина;

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

Чтобы избежать подобных опечаток, всегда используйте стандартную комбинацию контекстной подсказки Ctrl + Пробел. Автодополнение конфигуратора никогда не подставит несуществующее имя регистра и избавит от ручного перебора окончаний.

Причина 3. Настройка регистраторов в свойствах документа

Если синтаксис написан без опечаток, но ошибка Поле объекта не обнаружено (ИмяРегистра) сохраняется, разберем по шагам проверку метаданных:

  1. Откроем в конфигураторе документ (в нашем примере — Приходная).
  2. Перейдем на вкладку «Движения».
  3. Убедимся, что напротив нужных регистров (ЗакупочныеЦены и ОстаткиТоваров) установлены флажки.

Важно: если указать документ в списке регистраторов только внутри самого регистра накопления, но забыть отметить его на вкладке «Движения» самого документа, коллекция Движения не создаст соответствующее свойство набора записей, что приведет к исключению во время выполнения кода.

Дополнительные тонкости: вид регистра и очистка движений

Рассмотрим подробнее работу методов добавления строк в регистры накопления:

  1. Методы ДобавитьПриход() и ДобавитьРасход() поддерживаются только регистрами накопления с видом «Остатки». Если регистр имеет вид «Обороты», вызов этих методов приведет к ошибке — для оборотных регистров используется стандартный метод Добавить() с последующим заполнением реквизитов.
  2. Ручной вызов Движения.ЗакупочныеЦены.Очистить() в подавляющем большинстве случаев избыточен. Если в свойствах документа параметр «Удаление движений» имеет типовое значение «Удалять автоматически при перепроведении», платформа сама удаляет старые записи перед запуском процедуры ОбработкаПроведения.
  3. Для чистоты и читаемости кода не рекомендуется переиспользовать одну переменную для строк разных таблиц. Разделим их на осмысленные идентификаторы: например, ДвижениеЦены и ДвижениеОстатки.

Итоговый корректный вариант кода

Объединим все исправления и оформим процедуру проведения согласно стандартам разработки:


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

Для ускорения разработки и полного исключения ошибок ручного набора начинающим разработчикам также рекомендуется применять «Конструктор движений», доступный на вкладке «Движения» окна редактирования документа в конфигураторе. Он генерирует готовый типовой каркас процедуры проведения автоматически.

← На главную