Как скопировать элемент одного справочника в другой справочник в 1С?

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

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

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

Вариант 1. Явный перенос реквизитов и табличных частей

Рассмотрим стандартный подходят с применением функции ЗаполнитьЗначенияСвойств для реквизитов и выгрузкой/загрузкой табличных частей через промежуточные таблицы значений.

Функция ЗаполнитьЗначенияСвойств переносит только обычные реквизиты объекта, исключая служебные поля, такие как Ссылка или Родитель, однако она не копирует табличные части. Чтобы перенести табличные части, необходимо выгрузить каждую из них в таблицу значений и загрузить в новый объект.

Посмотрим на пример реализации данного подхода на сервере:


// Создаем новый элемент в справочнике-приемнике
КопияСпецификации = Справочники.Спецификации.СоздатьЭлемент();

// Заполняем реквизиты объекта, исключая служебные
ЗаполнитьЗначенияСвойств(КопияСпецификации, ОбъектИсточника, , "Ссылка, Родитель");

// Переносим табличную часть "Состав"
ТЗ = ОбъектИсточника.Состав.Выгрузить();
КопияСпецификации.Состав.Загрузить(ТЗ);

// Переносим табличную часть "Операции"
ТЗ = ОбъектИсточника.Операции.Выгрузить();
КопияСпецификации.Операции.Загрузить(ТЗ);

// Записываем созданный элемент
КопияСпецификации.Записать();

Этот способ отлично подходит, если количество табличных частей небольшое и их состав заранее известен.

Вариант 2. Универсальное копирование табличных частей через метаданные

Если справочник содержит много табличных частей или его структура может меняться в процессе развития конфигурации, логичнее использовать универсальный обход коллекции ТабличныеЧасти объекта метаданных. В этом случае нам не придется прописывать название каждой табличной части вручную.

Проанализируем алгоритм универсального копирования:


// Создаем новый элемент справочника-приемника
КопияСпецификации = Справочники.Спецификации.СоздатьЭлемент();

// Копируем шапочные реквизиты
ЗаполнитьЗначенияСвойств(КопияСпецификации, ОбъектИсточника, , "Ссылка, Родитель");

// Универсально обходим все табличные части
Для Каждого ТабличнаяЧасть Из ОбъектИсточника.Метаданные().ТабличныеЧасти Цикл
    ИмяТЧ = ТабличнаяЧасть.Имя;
    КопияСпецификации[ИмяТЧ].Загрузить(ОбъектИсточника[ИмяТЧ].Выгрузить());
КонецЦикла;

// Записываем объект
КопияСпецификации.Записать();

Такой подход экономит время при написании кода и гарантирует, что ни одна табличная часть не будет пропущена.

Вариант 3. Использование процедуры ОбработкаЗаполнения в модуле объекта

Еще один архитектурно правильный вариант — вынести логику копирования в модуль объекта справочника-приемника. В процедуре ОбработкаЗаполнения объекта-приемника переопределяется логика наполнения реквизитов, после чего вызов в коде сводится к одной строке: НовыйОбъект.Заполнить(Источник).

Разберем, как это реализовать:

  1. В модуле объекта справочника Спецификации описываем процедуру:
    
    Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
        Если ТипЗнч(ДанныеЗаполнения) = Тип("СправочникСсылка.Спецификации2") Тогда
            ЗаполнитьЗначенияСвойств(ЭтотОбъект, ДанныеЗаполнения, , "Ссылка, Родитель");
            
            Для Каждого ТабличнаяЧасть Из ДанныеЗаполнения.Метаданные().ТабличныеЧасти Цикл
                ИмяТЧ = ТабличнаяЧасть.Имя;
                ЭтотОбъект[ИмяТЧ].Загрузить(ДанныеЗаполнения[ИмяТЧ].Выгрузить());
            КонецЦикла;
        КонецЕсли;
    КонецПроцедуры
    
  2. В месте вызова (например, в обработчике команды формы) выполняем код:
    
    КопияСпецификации = Справочники.Спецификации.СоздатьЭлемент();
    КопияСпецификации.Заполнить(ОбъектИсточника);
    КопияСпецификации.Записать();
    

Важные нюансы при копировании элементов

При выполнении копирования элементов между разными справочниками следует учитывать несколько ключевых особенностей платформы 1С:

  1. Контекст выполнения: Методы Выгрузить() и Загрузить() для табличных частей работают на сервере. При работе с управляемыми формами вызов кода должен производиться в серверной процедуре (&НаСервере).
  2. Иерархия и подчинение: Если один из справочников является иерархическим или имеет владельца, реквизиты Родитель и Владелец копировать прямо нельзя, так как ссылки на группы одного справочника не могут быть родителем для другого справочника. Их необходимо либо исключать, либо переопределять.
  3. Уникальность кодов: При необходимости сохранения уникальной нумерации после заполнения реквизитов рекомендуется вызывать метод УстановитьНовыйКод() для нового элемента, чтобы избежать конфликтов при записи.
← На главную