Как реализовать копирование группы контрагентов с иерархией вложенных элементов в 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе работы с базами данных 1С часто возникает задача дублирования структуры справочников. Особенно это актуально для справочника Контрагенты, где структура может включать сотни папок и тысячи элементов. Стандартная кнопка «Копировать» в интерфейсе 1С копирует только текущий объект (либо только саму папку, либо только один элемент), не затрагивая вложенную иерархию. Разберем подробно, как решить эту задачу программно и с помощью стандартных инструментов.

Анализ проблемы и выбор стратегии

При копировании ветки справочника с вложенными элементами мы сталкиваемся с несколькими техническими сложностями:

  1. Сохранение подчиненности: Новые элементы должны ссылаться на новые родительские группы, а не на старые.
  2. Объем данных: Если в группе более 5000 элементов, обычный перебор может привести к длительной блокировке базы или нехватке памяти.
  3. Подчиненные справочники: Контрагенты обычно имеют связанные данные: договоры, банковские счета и контактную информацию. Простое копирование ссылки в поле Родитель не перенесет эти данные автоматически.

Рассмотрим два основных пути решения: использование внешней обработки с программным кодом и применение средств конвертации данных.

Решение 1: Программное копирование через рекурсию

Для корректного переноса иерархии лучше всего использовать рекурсивную функцию. Она будет заходить в каждую папку, создавать её копию и вызывать саму себя для всех элементов внутри этой папки. Разберем пример реализации, который можно разместить во внешней обработке.

Сначала рассмотрим основной метод, который инициирует процесс:


Процедура ВыполнитьКопированиеГруппы(ИсходнаяГруппаСсылка, НовыйРодитель)
    
    // 1. Создаем копию текущей группы
    НоваяГруппаОбъект = ИсходнаяГруппаСсылка.Скопировать();
    НоваяГруппаОбъект.Родитель = НовыйРодитель;
    // Можно очистить код, чтобы он сгенерировался автоматически при записи
    НоваяГруппаОбъект.Код = ""; 
    НоваяГруппаОбъект.Записать();
    
    НоваяГруппаСсылка = НоваяГруппаОбъект.Ссылка;
    
    // 2. Выбираем все элементы и группы, входящие в исходную группу
    Выборка = Справочники.Контрагенты.Выбрать(ИсходнаяГруппаСсылка, , , "Наименование Возр");
    
    Пока Выборка.Следующий() Цикл
        Если Выборка.ЭтоГруппа Тогда
            // Если это вложенная папка - вызываем эту же процедуру (рекурсия)
            ВыполнитьКопированиеГруппы(Выборка.Ссылка, НоваяГруппаСсылка);
        Иначе
            // Если это элемент - просто копируем его
            НовыйЭлементОбъект = Выборка.Ссылка.Скопировать();
            НовыйЭлементОбъект.Родитель = НоваяГруппаСсылка;
            НовыйЭлементОбъект.Код = "";
            НовыйЭлементОбъект.Записать();
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Проанализируем этот код. Мы используем метод Скопировать(), который позволяет сохранить все заполненные реквизиты (ИНН, КПП, основной менеджер и т.д.), кроме уникального идентификатора. Важным моментом является передача НоваяГруппаСсылка в качестве родителя для всех вложенных объектов. Это гарантирует, что структура будет в точности дублировать оригинал.

Решение 2: Обработка больших объемов данных (5000+ элементов)

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

  1. Использование транзакций: Оборачивание процесса в транзакцию ускоряет запись на диск, но при очень больших объемах может переполнить лог транзакций. Оптимально фиксировать транзакцию каждые 500-1000 элементов.
  2. Отключение проверок: Использование свойства ОбменДанными.Загрузка = Истина позволяет проигнорировать прикладные проверки в модуле объекта, что значительно ускоряет запись.

Посмотрим на модифицированный фрагмент кода для записи элемента:


НовыйЭлементОбъект = Выборка.Ссылка.Скопировать();
НовыйЭлементОбъект.Родитель = НоваяГруппаСсылка;
// Отключаем проверки для ускорения
НовыйЭлементОбъект.ОбменДанными.Загрузка = Истина;
НовыйЭлементОбъект.Записать();

Решение 3: Копирование связанных данных (Договоры и Счета)

Проблема простого копирования справочника Контрагенты заключается в том, что его договоры и банковские счета хранятся в других справочниках, где поле Владелец ссылается на контрагента. При программном копировании самого контрагента эти записи не дублируются автоматически.

Рассмотрим, как можно доработать код для копирования договоров:


Процедура СкопироватьДоговоры(СтарыйВладелец, НовыйВладелец)
    ВыборкаДоговоров = Справочники.ДоговорыКонтрагентов.Выбрать(, СтарыйВладелец);
    Пока ВыборкаДоговоров.Следующий() Цикл
        НовыйДоговор = ВыборкаДоговоров.Ссылка.Скопировать();
        НовыйДоговор.Владелец = НовыйВладелец;
        НовыйДоговор.Записать();
    КонецЦикла;
КонецПроцедуры

Эту процедуру необходимо вызывать сразу после записи нового элемента контрагента. Аналогичную логику следует реализовать для справочника БанковскиеСчета и контактной информации (если она хранится не в табличной части, а в регистре сведений).

Альтернативный вариант: Универсальный обмен данными XML

Если задача разовая и программирование кажется сложным, можно воспользоваться стандартной обработкой "Универсальный обмен данными в формате XML". Рассмотрим этот сценарий подробнее:

  1. В базе-источнике (которая может совпадать с базой-приемником) настраиваются правила обмена в программе Конвертация данных 2.1.
  2. В правилах указывается выгрузка справочника Контрагенты с фильтром по конкретной группе.
  3. Важный нюанс: Чтобы при загрузке в ту же базу создались копии, а не обновились старые записи, необходимо в правилах обмена (ПКО) отключить поиск по Уникальному Идентификатору (GUID) и настроить поиск, например, по наименованию с условием, что если не найдено — создавать новый.

Однако, как справедливо заметили участники форума, для новичка этот путь может оказаться сложнее, чем написание небольшого скрипта, так как требует понимания логики работы GUID в 1С.

Заключение и рекомендации

Выясним итоговый алгоритм действий для успешного копирования иерархии:

При правильном подходе программное создание дубля ветки справочника занимает не более 30 минут разработки и гарантирует чистоту данных в системе.

← На главную