Как программно переместить товары из одной группы номенклатуры в другую в 1С:УТ 11?

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

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

Разбор типичной ошибки: Ссылка против Объекта

Одной из самых частых ошибок, которую совершают начинающие разработчики, является попытка изменить реквизиты непосредственно у ссылки (Ссылка), полученной из запроса или выборки. Разберем по шагам, почему это не работает. Ссылка в 1С — это лишь указатель на запись в базе данных, она предназначена для чтения и поиска. Для того чтобы изменить какой-либо реквизит (в нашем случае Родитель), необходимо получить объект этого элемента в оперативную память.

Если в коде написать Выборка.Ссылка.Родитель = НоваяГруппа;, система либо выдаст ошибку, либо просто проигнорирует действие, так как у ссылки нельзя менять значения полей. Правильный алгоритм всегда должен включать вызов метода ПолучитьОбъект().

Программный метод перемещения товаров

Рассмотрим пример кода, который позволяет найти товары по списку артикулов и переместить их в целевую папку «Архив». Проанализируем оптимальную структуру запроса и цикла обработки данных.


// 1. Находим целевую папку (группу)
ПапкаАрхива = Справочники.Номенклатура.НайтиПоКоду("00-000001"); // Лучше искать по коду или ссылке

Если ПапкаАрхива.Пустая() Тогда
    Сообщить("Целевая папка не найдена!");
    Возврат;
КонецЕсли;

// 2. Подготавливаем список артикулов
СписокАртикулов = Новый Массив;
СписокАртикулов.Добавить("21");
СписокАртикулов.Добавить("483");
СписокАртикулов.Добавить("187");

// 3. Выбираем товары, которые еще не в архиве
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |   Номенклатура.Артикул В(&СписокАртикулов)
    |   И НЕ Номенклатура.ЭтоГруппа
    |   И Номенклатура.Родитель <> &Архив";

Запрос.УстановитьПараметр("СписокАртикулов", СписокАртикулов);
Запрос.УстановитьПараметр("Архив", ПапкаАрхива);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

// 4. Перемещаем в цикле
Пока Выборка.Следующий() Цикл
    Попытка
        ОбъектТовара = Выборка.Ссылка.ПолучитьОбъект();
        ОбъектТовара.Родитель = ПапкаАрхива;
        
        // Используем ОбменДанными для ускорения и обхода проверок
        ОбъектТовара.ОбменДанными.Загрузка = Истина;
        
        ОбъектТовара.Записать();
    Исключение
        Сообщить("Ошибка при записи товара: " + Выборка.Ссылка + " - " + ОписаниеОшибки());
    КонецПопытки;
КонецЦикла;

В данном примере мы добавили важную строку ОбъектТовара.ОбменДанными.Загрузка = Истина;. Рассмотрим подробнее, зачем это нужно. В конфигурациях на базе ERP и УТ 11 при записи номенклатуры срабатывает огромное количество подписок на события: проверка заполнения штрихкодов, проверка уникальности, контроль обязательных реквизитов. Если вы перемещаете старый товар, в котором не заполнены новые обязательные поля, обычный метод Записать() завершится ошибкой. Режим загрузки позволяет «отключить» лишние проверки и быстро изменить только иерархию.

Оптимизация при работе с большим объемом данных

Если вам необходимо переместить около 4000 или более товаров, последовательная запись каждого объекта может занять значительное время. Выясним причину: каждая команда Записать() инициирует отдельную транзакцию в базе данных SQL.

Для ускорения процесса разберем применение транзакций. Мы можем обернуть цикл в одну общую транзакцию, что ускорит работу в 5–10 раз. Однако помните, что при возникновении ошибки внутри транзакции, изменения не запишутся ни для одного товара из этого блока.


НачатьТранзакцию();
Пока Выборка.Следующий() Цикл
    // ... получение объекта и установка родителя ...
    ОбъектТовара.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();

Также, если список артикулов очень большой, рекомендуется использовать Временные Таблицы в запросе. Вместо передачи массива в параметр В(&СписокАртикулов), мы можем загрузить таблицу артикулов в менеджер временных таблиц и соединить её с таблицей справочника. Это наиболее профессиональный подход с точки зрения производительности SQL-сервера.

Использование стандартной обработки «Групповое изменение реквизитов»

Проанализируем ситуацию, когда писать код вовсе не обязательно. В типовых конфигурациях 1С (УТ, ERP, КА) существует мощный инструмент, который часто недооценивают. Если задача разовая, лучше воспользоваться им.

  1. Перейдите в раздел НСИ и АдминистрированиеОбслуживаниеКорректировка данных.
  2. Выберите пункт Групповое изменение реквизитов.
  3. В поле «Выбирать элементы» укажите Номенклатура.
  4. Нажмите «Добавить условие отбора» и укажите список ваших артикулов (или воспользуйтесь загрузкой из файла, если список велик).
  5. В списке реквизитов найдите Группа (Родитель) и укажите новое значение.
  6. Важный нюанс: Нажмите кнопку «Дополнительные параметры» и установите флаг «Режим разработчика». Это позволит вам увидеть скрытые реквизиты и, при необходимости, отключить стандартные проверки при записи.

Этот способ безопаснее, так как система сама позаботится о корректности ссылок и транзакционности изменений. К тому же, он не требует навыков программирования и внесения изменений в конфигурацию.

Меры предосторожности и проверка результатов

При массовом перемещении товаров следует учитывать настройки Видов номенклатуры. В 1С:УТ 11 иерархия может быть ограничена: например, в настройках вида номенклатуры может быть запрещено создание групп или жестко задана структура. Если целевая папка не соответствует настройкам перемещаемого товара, запись может быть заблокирована системой.

После завершения операции обязательно проверьте результат. Посмотрите на общее количество перемещенных позиций и убедитесь, что полнотекстовый поиск работает корректно. При масштабных изменениях иерархии (тысячи элементов) иногда требуется ручное обновление индекса полнотекстового поиска, чтобы пользователи могли мгновенно находить товары в новых разделах каталога.

Подводя итог, отметим: для разовых задач идеально подходит Групповое изменение реквизитов, а для автоматизации в коде — связка Запрос + ПолучитьОбъект() + ОбменДанными.Загрузка. Правильное использование этих инструментов сэкономит время и предотвратит повреждение данных в базе.

← На главную