При написании обработок, будь то простой шаблон для чтения и загрузки из Excel (удобно через загрузка и массовое создание номенклатуры из Excel и CSV), инструменты для загрузки данных товаров из файлов YML и CSV или импорт XML, в конфигурации "1С:Управление Торговлей 11" (а также КА 2 и ERP) разработчики часто сталкиваются с неочевидным поведением системы. Казалось бы, простой код создания элемента справочника работает, элемент записывается, но при открытии карточки товара выясняется, что ключевые поля не заполнены, а система ведет себя некорректно.
Разберем типичную ситуацию: мы создаем номенклатуру, присваиваем ей ВидНоменклатуры, но настройки этого вида (ставка НДС, единица измерения, тип номенклатуры) не применяются к новому элементу автоматически. Попытаемся разобраться, почему так происходит, и как написать правильный код.
Рассмотрим пример кода, с которого начиналось обсуждение. Задача состоит в том, чтобы найти Вид номенклатуры и присвоить его новому элементу.
Первая ошибка — избыточные действия с базой данных:
// Неоптимальный код
СсылкаН = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Продукция", Истина);
ОбъектН = СсылкаН.ПолучитьОбъект(); // Лишнее действие!
НовыйЭлемент.ВидНоменклатуры = ОбъектН.Ссылка; // Возврат к тому, с чего начали
Здесь мы видим классическую ошибку начинающих разработчиков: получение объекта там, где достаточно ссылки. Метод НайтиПоНаименованию уже возвращает ссылку. Получать объект (который считывает все данные из базы) только для того, чтобы взять его же ссылку — бессмысленная трата ресурсов сервера. Правильный вариант выглядит так:
// Оптимальный код
ВидНоменклатурыСсылка = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Продукция", Истина);
НовыйЭлемент.ВидНоменклатуры = ВидНоменклатурыСсылка;
Однако главная проблема автора заключалась не в производительности, а в логике работы УТ 11. После записи элемента поле "Вид номенклатуры" было заполнено, но зависимые поля (НДС, Тип товара и т.д.) оставались пустыми, пока пользователь вручную не перевыберет вид в форме.
В современных конфигурациях ВидНоменклатуры — это не просто группировка. Это шаблон (template), содержащий значения по умолчанию и настройки учета (серии, характеристики, упаковки). Это особенно важно учитывать, если вы планируете сложную логику, например, когда требуется расчет объема, ширины и высоты в карточке номенклатуры, где корректность базовых единиц измерения критична.
Когда вы создаете номенклатуру интерактивно (руками в форме), срабатывают обработчики событий формы (например, ПриИзменении поля Вид), которые копируют настройки из Вида в реквизиты Номенклатуры. Когда вы создаете элемент программно, эти события формы не срабатывают. Простого присваивания ссылки НовыйЭлемент.ВидНоменклатуры = ... недостаточно. Система "не знает", что вы хотите применить шаблон.
Чтобы программно созданный элемент был полноценным (что особенно актуально, если выполняется комплексная загрузка номенклатуры, штрихкодов, цен (поможет автоматическая загрузка номенклатуры из внешних источников) и документов поступления), необходимо принудительно вызвать логику заполнения. В зависимости от версии конфигурации и контекста задачи, есть несколько способов сделать это.
В конфигурации у объекта справочника Номенклатура часто предусмотрены экспортные методы, дублирующие логику заполнения. Автор темы нашел решение в вызове процедуры:
НовыйЭлемент.ВидНоменклатуры = СсылкаН;
// Принудительно заполняем реквизиты значениями по умолчанию из Вида
НовыйЭлемент.ЗаполнитьРеквизитыПоВидуНоменклатуры();
Примечание: имя метода может отличаться в разных релизах (например, ЗаполнитьЗначенияСвойств или аналогичные). Всегда проверяйте наличие методов в модуле объекта через "Вычислить выражение" или синтакс-помощник.
Платформа 1С предоставляет стандартный метод Заполнить(ДанныеЗаполнения). В типовых конфигурациях в модуле объекта есть обработчик ОбработкаЗаполнения, который содержит всю необходимую логику инициализации нового элемента.
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
// Заполняем на основании Вида (если логика это предусматривает)
НовыйЭлемент.Заполнить(ВидНоменклатурыСсылка);
// Или просто инициализируем дефолтные значения
НовыйЭлемент.Заполнить(Неопределено);
НовыйЭлемент.ВидНоменклатуры = ВидНоменклатурыСсылка;
// ... далее заполнение остальных полей
В исходном коде автора встречалась строка:
НовыйЭлемент.ОбменДанными.Загрузка = Истина;
Крайне не рекомендуется использовать этот флаг при создании справочников в УТ 11, КА 2 или ERP без крайней необходимости. Почему?
ТипНоменклатуры), которые потом невозможно будет использовать в документах.ПриЗаписи) заполняется множество служебных регистров: ключи доступа (RLS), очередь поиска, история изменений. Режим Загрузка = Истина отключает эти подписки. В результате товар может быть создан, но пользователи его "не увидят" в подборе из-за отсутствия записей в регистрах доступа.Соберем воедино корректный код. Этот подход является базой для любых интеграций, будь то простая обработка или полноценная выгрузка / загрузка в формате JSON данных по номенклатурам — для этого подойдёт массовая загрузка номенклатуры из Excel, YML и XML.
// 1. Получаем ссылку на вид номенклатуры (лучше искать по уникальному ID или коду, но для примера - по наименованию)
ВидСсылка = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Продукция");
Если ВидСсылка.Пустая() Тогда
// Обязательно обрабатываем ошибку, чтобы не плодить "битые" элементы
Сообщить("Вид номенклатуры не найден!");
Возврат;
КонецЕсли;
// 2. Создаем элемент
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
// 3. Устанавливаем Вид
НовыйЭлемент.ВидНоменклатуры = ВидСсылка;
// 4. ВАЖНО: Вызываем заполнение значений по умолчанию (НДС, Ед.Изм., ТипНоменклатуры)
// Проверяем наличие метода в вашей версии конфигурации.
// Часто работает стандартный Заполнить() или специфичный метод объекта.
Попытка
НовыйЭлемент.ЗаполнитьРеквизитыПоВидуНоменклатуры();
Исключение
// Если специфичного метода нет, пробуем стандартную обработку заполнения
НовыйЭлемент.Заполнить(ВидСсылка);
КонецПопытки;
// 5. Заполняем уникальные поля
НовыйЭлемент.Наименование = "Апельсиновый сок";
НовыйЭлемент.Артикул = "ART-12345";
// Если ВидНоменклатуры предполагает характеристики, нужно включить флаг и в товаре
НовыйЭлемент.ИспользоватьХарактеристики = ВидСсылка.ИспользоватьХарактеристики;
// 6. Записываем БЕЗ ОбменДанными.Загрузка, чтобы сработали все проверки
Попытка
НовыйЭлемент.Записать();
Исключение
Сообщить("Ошибка при записи номенклатуры: " + ОписаниеОшибки());
КонецПопытки;
При программном создании номенклатуры в сложных конфигурациях 1С:
ПолучитьОбъект(), если нужна только ссылка.ВидНоменклатуры не заполняет автоматически зависимые реквизиты (Ставка НДС, Тип и т.д.).Заполнить() или специализированные методы модуля объекта), чтобы применить шаблон настроек Вида.ОбменДанными.Загрузка = Истина, чтобы не нарушить целостность служебных данных и механизмов RLS.После корректного создания карточки товара можно переходить к наполнению её медиа-контентом, например, используя выгрузку и загрузку картинок номенклатуры на базе БСП.