При программном создании, заполнении и проведении документов в типовых конфигурациях платформы «1С:Предприятие 7.7» (таких как «Комплексная конфигурация 4.5» или «Торговля и склад 9.2») разработчики часто сталкиваются с ошибкой времени выполнения:
{Глобальный модуль(8846)}: Значение не представляет агрегатный объект (Идентификатор)
Разберем причины возникновения этой ситуации, проанализируем поведение платформы 7.7 и рассмотрим по шагам правильный способ программного заполнения строк табличной части документов.
Проанализируем контекст ошибки. В глобальном модуле при проведении документа вызывается функция определения статуса партии:
Функция глПолучитьСтатусПартииПрихода(ВидТМЦ, Номенклатура, КодОперации, Склад = 0) Экспорт
// ...
Иначе // продукция или полуфабрикаты
Статус = глСП.ЗначениеПоИдентификатору(ВидТМЦ.Идентификатор());
КонецЕсли;
Возврат Статус;
КонецФункции
Ошибка возникает из-за того, что переменная ВидТМЦ оказывается пустой или содержит не агрегатный объект (не значение перечисления), в результате чего вызов метода Идентификатор() приводит к аварийному завершению транзакции.
Выясним причину, почему реквизит оказывается незаполненным, даже если разработчик пытается передать туда значение:
ПриВводеСтроки, ПриВыбореНоменклатуры). В них для реквизита строки задается тип данных и присваивается значение по умолчанию. При создании объекта через СоздатьОбъект("Документ.ВозвратОтПокупателя") программный модуль формы не задействуется, и автозаполнение не срабатывает.ВидСтатус имеет тип «Неопределенный», так как в зависимости от контекста он может принимать значения различных перечислений (например, ВидыТМЦ или СтатусыПартии). В физической структуре базы 1С 7.7 реквизит с неопределенным типом требует обязательной явной типизации перед присвоением значения. Если тип не назначен, прямое присвоение не сохраняет ссылку на перечисление.Док.Номенклатура.ВидСтатус ошибочно, так как ВидСтатус является реквизитом табличной части самого документа, а не справочника Номенклатура. Запись через точку в реквизиты найденного элемента справочника недопустима.Для корректного заполнения табличной части документа необходимо выполнить два обязательных действия:
НазначитьТип().ВидСтатус нужное значение из метаданных перечисления ВидыТМЦ.Посмотрим на пример правильной структуры кода в функции заполнения документа:
Функция ЗаполнитьВозвратОтПокупателя(Док, ОснДок)
Док.ДатаДок = ОснДок.ДатаДок;
Док.ЮрЛицо = Док.Фирма.ЮрЛицо;
Док.Проект = ОснДок.Проект;
Док.Автор = ОснДок.Автор;
Док.Комментарий = "Возврат товара с филиала (торговой точки)";
Док.ДокОснование = ОснДок.ТекущийДокумент();
Док.Валюта = глРубли;
Док.Курс = 1;
Док.Кратность = 1;
Спр = СоздатьОбъект("Справочник.Номенклатура");
Если Спр.НайтиПоНаименованию("Товары в ассортименте", 0, 1) = 0 Тогда
Сообщить("Не найдена номенклатура ""Товары в ассортименте""!");
Возврат 0;
КонецЕсли;
ТовВАсрт = Спр.ТекущийЭлемент();
ВрТЗ = СоздатьОбъект("ТаблицаЗначений");
ОснДок.ВыгрузитьТабличнуюЧасть(ВрТЗ);
ВрТЗ.ВыбратьСтроки();
Пока ВрТЗ.ПолучитьСтроку() = 1 Цикл
ВрТЗ.РозничнаяЦена = ВрТЗ.РозничнаяЦена * ВрТЗ.Количество;
КонецЦикла;
ВрТЗ.Свернуть("СтавкаНДС,СтавкаНП", "Сумма,СуммаНДС,СуммаНП,РозничнаяЦена");
Док.УдалитьСтроки();
// Обязательно назначаем тип реквизиту табличной части перед записью
Док.НазначитьТип("ВидСтатус", "Перечисление.ВидыТМЦ");
ВрТЗ.ВыбратьСтроки();
Пока ВрТЗ.ПолучитьСтроку() = 1 Цикл
Док.НоваяСтрока();
Док.Номенклатура = ТовВАсрт;
// Заполняем реквизит текущей строки документа
Док.ВидСтатус = Перечисление.ВидыТМЦ.Товар;
Док.Количество = 1;
Док.Единица = Док.Номенклатура.БазоваяЕдиница;
Док.Коэффициент = 1;
Док.Сумма = ВрТЗ.РозничнаяЦена;
Док.Цена = ?(Док.Количество = 0, 0, Док.Сумма / Док.Количество);
// Вызываем типовой пересчет реквизитов строки
глПересчетТаблЧасти(Док, "РозничнаяЦена");
КонецЦикла;
Возврат 1;
КонецФункции
Рассмотрим подробнее правила работы с типизацией реквизитов платформы 1С 7.7:
НазначитьТип(<ИмяРеквизита>, <ИмяТипа>) применяется исключительно к тем полям шапки или табличной части, у которых в конфигураторе установлен базовый тип «Неопределенный». Если тип реквизита в метаданных жестко задан (например, «Справочник.Номенклатура»), вызов данного метода вызовет ошибку.НазначитьТип с методом НазначитьВид(<Реквизит>, <ИмяВида>). Метод НазначитьВид применяется тогда, когда базовый тип уже известен (например, «Справочник» или «Документ»), но не определен его конкретный вид. Для реквизитов с типом «Неопределенный» необходимо использовать строго НазначитьТип.НазначитьТип("Реквизит", "Строка", 50). В противном случае платформа ограничит длину строки 23 символами.Соблюдение правил явной типизации колонок табличной части позволяет корректно формировать движения регистров и избегать ошибок при программном проведении документов в любых конфигурациях 1С 7.7.