При написании обработок импорта данных или автоматического создания номенклатуры в платформе 1С 7.7 (например, в типовой конфигурации «Торговля и склад 9.2» или «Комплексная конфигурация») разработчики нередко сталкиваются с ошибками вида «Поле агрегатного объекта не обнаружено (РеквБазоваяЕдиница)» или «Неверное имя атрибута» при попытке использования метода УстановитьАтрибут(). Разберем, почему возникают эти ошибки и как правильно программно инициализировать номенклатуру со всеми связанными единицами измерения.
Проанализируем две ключевые причины, из-за которых программная запись реквизитов завершается аварийно:
РеквБазоваяЕдиница является элементом экранного диалога (переменной формы элемента справочника), а не реквизитом самого объекта Справочник.Номенклатура. При программной работе с объектом через СоздатьОбъект("Справочник.Номенклатура") доступны только метаданные справочника. На уровне базы данных реквизит номенклатуры называется БазоваяЕдиница.БазоваяЕдиница в типовых решениях имеет тип ссылки на подчиненный справочник Справочник.Единицы, а не на общероссийский классификатор Справочник.ОКЕИ. Напрямую присвоить значение из ОКЕИ в реквизит номенклатуры нельзя.Рассмотрим структуру учета единиц измерения в конфигурации «Торговля и склад 9.2»:
ОКЕИ содержит общегосударственные классификаторы единиц (штуки, килограммы, литры и т.д.).Единицы является подчиненным справочнику Номенклатура. Каждый его элемент содержит ссылку на классификатор ОКЕИ, текстовое наименование и коэффициент пересчета относительно базовой единицы (для базовой единицы коэффициент всегда равен 1).Номенклатура содержит реквизиты БазоваяЕдиница и ОсновнаяЕдиница, которые ссылаются на элементы подчиненного справочника Единицы.Поскольку элемент подчиненного справочника невозможно создать без записанного владельца, программное создание номенклатуры выполняется строго в два этапа с промежуточным сохранением.
Разберем по шагам правильный алгоритм создания позиции номенклатуры с автоматическим формированием базовой единицы измерения:
Записать(). Это необходимо для того, чтобы у номенклатуры сформировалась ссылка в базе данных, которая станет владельцем для единицы измерения.Справочник.Единицы, привязываем его к созданной номенклатуре с помощью метода ИспользоватьВладельца(), заполняем реквизит ОКЕИ, коэффициент (равный 1), наименование и вызываем Записать().БазоваяЕдиница и ОсновнаяЕдиница номенклатуры, после чего повторно вызываем Записать() для номенклатуры.Посмотрим на пример законченного кода для корректного создания номенклатуры и подчиненной базовой единицы измерения:
// Создаем объекты для работы со справочниками
спрНоменклатура = СоздатьОбъект("Справочник.Номенклатура");
спрЕдиницы = СоздатьОбъект("Справочник.Единицы");
спрОКЕИ = СоздатьОбъект("Справочник.ОКЕИ");
// Ищем требуемую единицу в классификаторе ОКЕИ (например, по коду 796 - шт)
Если спрОКЕИ.НайтиПоКоду(КодОКЕИ, 0) = 0 Тогда
Сообщить("Единица ОКЕИ не найдена в базе!", "!");
Возврат;
КонецЕсли;
// Открываем транзакцию для обеспечения целостности данных
НачатьТранзакцию();
Попытка
// Шаг 1: Создаем и первично записываем номенклатуру
спрНоменклатура.Новый();
спрНоменклатура.Наименование = "Товар новый";
спрНоменклатура.ПолнНаименование = "Товар новый (полное наименование)";
спрНоменклатура.Записать();
// Шаг 2: Создаем подчиненную единицу измерения
спрЕдиницы.ИспользоватьВладельца(спрНоменклатура.ТекущийЭлемент());
спрЕдиницы.Новый();
спрЕдиницы.ОКЕИ = спрОКЕИ.ТекущийЭлемент();
спрЕдиницы.Коэффициент = 1;
спрЕдиницы.Наименование = спрОКЕИ.Наименование;
// Если требуется штрихкод, в типовых конфигурациях 7.7 он часто хранится в единице
// спрЕдиницы.Штрихкод = ВводШтрихкода;
спрЕдиницы.Записать();
// Шаг 3: Прописываем единицы в номенклатуру и сохраняем
спрНоменклатура.БазоваяЕдиница = спрЕдиницы.ТекущийЭлемент();
спрНоменклатура.ОсновнаяЕдиница = спрЕдиницы.ТекущийЭлемент();
спрНоменклатура.Записать();
ЗафиксироватьТранзакцию();
Сообщить("Элемент успешно создан!");
Исключение
ОтменитьТранзакцию();
Сообщить("Ошибка при создании номенклатуры: " + ОписаниеОшибки(), "!");
КонецПопытки;
Если в процессе разработки возникают сомнения относительно того, где хранятся данные или как заполняются поля экранных форм, обратимся к встроенным модулям конфигурации:
Номенклатура в конфигураторе.ПриОткрытии() и ПриЗаписи() (или ВводНового()). В них явно прописан механизм чтения значений из реквизитов объекта в переменные диалога формы и обратная выгрузка при сохранении.