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