В процессе эксплуатации системы 1С часто возникает потребность в реорганизации справочника Номенклатура. Особенно трудоемкой кажется задача, когда нужно перенести тысячи позиций (например, 6500 наименований) из разных мест в одну общую новую папку, сохранив при этом исходную структуру подпапок. Рассмотрим детально, как решить эту задачу различными способами: от встроенных инструментов до написания собственного программного кода.
Прежде чем мы перейдем к практике, разберем теорию. В платформе 1С иерархия справочников (в частности, номенклатуры) строится на использовании реквизита Родитель. Каждый элемент или группа «знает», в какой папке они находятся, благодаря ссылке на вышестоящую группу в этом поле. Если у объекта Родитель пустой — значит, он находится в корне справочника.
Следовательно, задача «перенести в другую группу» технически сводится к изменению значения реквизита Родитель. Однако сложность заключается в том, что при простом перемещении элементов в одну общую папку иерархия «рассыплется». Чтобы ее сохранить, нам нужно либо перемещать саму «головную» группу, либо воссоздавать структуру папок в целевом месте.
Проанализируем самый простой вариант, доступный пользователю. Если вам нужно переместить целые группы вместе со всем содержимым, платформа позволяет сделать это без программирования.
Важный нюанс: при таком действии все подчиненные элементы и вложенные папки переместятся автоматически, сохранив свою внутреннюю структуру. Это происходит потому, что мы меняем Родитель только у самой верхней папки, а ссылки вложенных элементов на эту папку остаются неизменными.
Если задача сложнее (например, нужно перенести не всю папку, а только определенные товары, но раскидать их по таким же папкам в новом месте), рассмотрим использование мощного инструмента с диска ИТС — обработки Универсальный подбор и обработка объектов.
Разберем по шагам, как работать с этим инструментом:
Номенклатура.Родитель и укажем новую группу.Однако помните: этот метод переместит все выбранные товары «скопом» в одну папку. Если вам нужно, чтобы внутри новой папки создались точно такие же подпапки, как были раньше, этот метод потребует предварительного ручного создания структуры групп.
Когда мы имеем дело с 6500 позициями и сложной вложенностью, лучше всего написать небольшую процедуру. Рассмотрим программный подход, который анализирует текущую структуру и воссоздает ее в новом месте.
Проанализируем пример кода, который копирует структуру папок. Это полезно, если вы хотите сначала создать «скелет» в новом месте, а затем перенести туда товары.
Процедура КопироватьИерархиюГрупп(ИсходнаяГруппа, НоваяГруппаРодитель)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Родитель КАК Родитель
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В ИЕРАРХИИ(&Ссылка)
| И Номенклатура.ЭтоГруппа = ИСТИНА";
Запрос.УстановитьПараметр("Ссылка", ИсходнаяГруппа);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
// Сначала создаем копии групп
Для Каждого Строка Из РезультатЗапроса Цикл
НоваяПапка = Справочники.Номенклатура.СоздатьГруппу();
НоваяПапка.Наименование = Строка.Наименование;
// Здесь логика определения родителя для новой папки
// ...
НоваяПапка.Записать();
КонецЦикла;
КонецПроцедуры
Рассмотрим более продвинутый алгоритм, предложенный в обсуждении, который позволяет корректно перепривязать родителей. Основная идея заключается в том, чтобы сначала создать таблицу соответствия «Старая группа — Новая группа».
// Пример переноса элементов с сохранением иерархии
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Ссылка КАК СтараяСсылка,
| Номенклатура.Родитель КАК СтарыйРодитель,
| Номенклатура.ЭтоГруппа КАК ЭтоГруппа
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В ИЕРАРХИИ(&ВыбРодитель)";
Запрос.УстановитьПараметр("ВыбРодитель", Объект.СтараяГруппа);
ТЗ = Запрос.Выполнить().Выгрузить();
ТЗ.Колонки.Добавить("НоваяСсылка");
// 1 этап: Создаем структуру папок
Для Каждого Стр Из ТЗ Цикл
Если Стр.ЭтоГруппа Тогда
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
НоваяГруппа.Наименование = Стр.СтараяСсылка.Наименование;
// Логика установки родителя...
НоваяГруппа.Записать();
Стр.НоваяСсылка = НоваяГруппа.Ссылка;
КонецЕсли;
КонецЦикла;
В конфигурациях на управляемых формах (УТ 11, БП 3.0, ERP) встроен мощный механизм Групповое изменение реквизитов. Выясним, как им воспользоваться для нашей задачи:
Номенклатура.Родитель и в колонке «Новое значение» выберем целевую папку.Важно: этот метод идеален, если вы переносите товары из разных папок в ОДНУ общую. Но если нужно сохранить вложенность, этот инструмент придется запускать итерационно для каждой подпапки, что может быть неудобно для 6500 позиций.
Разберем основные риски, которые возникают при работе с таким объемом данных (6500 позиций):
1. Счета учета номенклатуры. В программах типа «1С:Бухгалтерия» счета учета (41.01, 10.01 и др.) часто привязаны не к конкретным товарам, а к папкам (группам). Если вы переносите товары из папки «Материалы» в папку «Товары», их бухгалтерское поведение в новых документах может измениться. Проанализируйте регистр сведений Счета учета номенклатуры перед переносом.
2. Транзакции и производительность. При программной записи 6500 объектов база может «зависнуть». Рекомендуется использовать механизм транзакций для ускорения процесса, но делать записи порциями. Рассмотрим пример обертки кода:
НачатьТранзакцию();
Попытка
Для Каждого Элемент Из СписокПереноса Цикл
ОбъектНом = Элемент.ПолучитьОбъект();
ОбъектНом.Родитель = НоваяГруппа;
ОбъектНом.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Ошибка при переносе: " + ОписаниеОшибки());
КонецПопытки;
3. Обмены данными. Если ваша база синхронизируется с сайтом или другой программой, массовое изменение родителя у 6500 товаров пометит их все как «измененные». Это вызовет огромную очередь выгрузки. Чтобы этого избежать, используйте свойство ОбменДанными.Загрузка = Истина при записи объекта в коде.
Для решения задачи автора темы наиболее эффективным будет сочетание методов. Если новые папки еще не созданы, используйте программный скрипт для копирования иерархии (аналогичный коду из Сообщения 13). Если же задача разово переместить отобранные товары в существующую структуру, воспользуйтесь стандартной обработкой Универсальный подбор и обработка объектов. Всегда выполняйте такие операции сначала на копии базы, чтобы убедиться в сохранении ссылочной целостности и корректности отчетов после перемещения.