Синхронизация справочников по GUID

Порой при переводе систем с одной конфигурации на другую нужно часто переносить справочники из одних в другие.

При этом сложно завязываться на код или наименование.

Но! Можно завязаться на GUID элемента. 1С позволяет использовать один и тот же GUID в разных справочниках.

Причем в составных полях хранится не только GUID, но и тип, поэтому использование в одной базе ссылок с одинаковым GUID но разным типом безопасно!

Для примера рассмотрим алгоритм, который переносит один справочник в другой, используя синхронизацию по GUID.

Понятно, что его можно использовать многократно.

Алгоритм имеет следующие параметры:

Наименование

Направление передачи

ТипУчастникаКА

Внутренний

зпЗапрос

Вход

ИдентификаторРезСправочника

Вход

ПапкаНовых

Вход

ТолькоНовые

Вход

ГрузитьИерархию

Вход

ГрузитьПодчиненность

Вход

ВладелецНовых

Вход

ЧислоОбрабатываемых

Вход

ИерархияЭлементовВИерархиюГрупп

Вход

ПроставлятьСсылкуНаРезультатВРеквизите

Вход

 

//Запрос, которым получаем исходные элементы

Запрос = ПолучитьЗапрос(зпЗапрос);

ТЗ = Запрос.Выполнить().Выгрузить();

ТЗ.Колонки.Добавить("Уровень");

//Сортируем по уровню

//Чтобы группы создавались раньше элементов, в один проход тогда можно

Состояние("Индексация");

Для Каждого СтрокаТЧ ИЗ ТЗ Цикл

                Попытка

                               СтрокаТЧ.Уровень = СтрокаТЧ.Ссылка.Уровень();

                Исключение

                               Прервать; //Не индексируем

                КонецПопытки;

                ОбработкаПрерыванияПользователя();

КонецЦикла;

ТЗ.Сортировать("Уровень Возр");

//Загрузка

Состояние("Загрузка");

СчетчикСозданных  = 0;

//Перебираем объекты

Для Каждого СтрокаТЧ ИЗ ТЗ Цикл

                ОбработкаПрерыванияПользователя();

                //Получаем GUID исходного элемента

                СсылкаИсх = СтрокаТЧ.Ссылка;

                МенеджерИсх = Справочники[СсылкаИсх.Метаданные().Имя];

                ГуидИсх = СсылкаИсх.УникальныйИдентификатор();

                Попытка

                               ГуидИсхРодитель = СсылкаИсх.Родитель.УникальныйИдентификатор();

                Исключение

                               ГуидИсхВладелец = СсылкаИсх.Родитель.УникальныйИдентификатор();

                КонецПопытки;

               

                //Формируем GUID результирующего элемента и родителей, владельцев

                СсылкаРез = Справочники[ИдентификаторРезСправочника].ПолучитьСсылку(ГуидИсх);

                Попытка

                               СсылкаРезРодитель = Справочники[ИдентификаторРезСправочника].ПолучитьСсылку(ГуидИсхРодитель);

                Исключение

                               СсылкаРезВладелец = Справочники[ИдентификаторРезСправочника].ПолучитьСсылку(ГуидИсхВладелец);

                КонецПопытки;

                //Находим элемент по GUID, если его нет, то формируем

                ТекОбъект = СсылкаРез.ПолучитьОбъект();

                Попытка

                               ЭтоГруппаИсх = СсылкаИсх.ЭтоГруппа;

                Исключение

                               ЭтоГруппаИсх = ложь;

                КонецПопытки;

                Если ИерархияЭлементовВИерархиюГрупп Тогда

                               Выборка = МенеджерИсх.Выбрать(СсылкаИсх);

                               Если Выборка.Следующий() Тогда

                                               ЭтоГруппаИсх = истина;

                               КонецЕсли;

                КонецЕсли;

                //Создаем объект или группу, в зависимости от того, был элемент группой или нет

                Если ТекОбъект = Неопределено Тогда

                               Если ЭтоГруппаИсх  Тогда

                                               Попытка

                                                               ТекОбъект = Справочники[ИдентификаторРезСправочника].СоздатьГруппу();

                                               Исключение

                                                               ТекОбъект = Справочники[ИдентификаторРезСправочника].СоздатьЭлемент();

                                               КонецПопытки;

                               Иначе

                                               ТекОбъект = Справочники[ИдентификаторРезСправочника].СоздатьЭлемент();

                               КонецЕсли;

                               ТекОбъект.УстановитьСсылкуНового(СсылкаРез);

                Иначе

                               Если ТолькоНовые Тогда

                                               Продолжить;

                               КонецЕсли;

                КонецЕсли;

                //Устанавливаем папку

                Попытка

                               Если ЗначениеЗаполнено(ПапкаНовых) Тогда

                                               ТекОбъект.Папка = ПапкаНовых;

                               КонецЕсли;

                Исключение

                КонецПопытки;

                //Устанавливаем владельца

                Попытка

                               Если ЗначениеЗаполнено(ВладелецНовых) Тогда

                                               ТекОбъект.Владелец = ВладелецНовых;

                               КонецЕсли;

                Исключение

                КонецПопытки;

                //Если переносим иерархию

                Попытка

                               Если ГрузитьИерархию=истина Тогда

                                               ТекОбъект.Родитель = СсылкаРезРодитель.ПолучитьОбъект().Ссылка;

                               КонецЕсли;

                Исключение

                КонецПопытки;

                Попытка

                               Если ГрузитьПодчиненность=истина Тогда

                                               ТекОбъект.Владелец = СсылкаРезВладелец.ПолучитьОбъект().Ссылка;

                               КонецЕсли;

                Исключение

                КонецПопытки;

                //Устанавливаем наименование и код

                ТекОбъект.Наименование = СсылкаИсх.Наименование;

                //ТекОбъект.Код = СсылкаИсх.Код;

                //Устанавливаем код синхронизации

                Попытка

                               ТекОбъект.ИдВнешний = СсылкаИсх.Код6;

                Исключение

                               Попытка

                                               ТекОбъект.ИдВнешний = СсылкаИсх.ИдВнешний;

                               Исключение

                                КонецПопытки

                КонецПопытки;

                //Устанавливаем тип участника, если это справочник участников

                Попытка

                               ТекОбъект.ТипУчастника = ТипУчастникаКА;

                Исключение

                КонецПопытки;

                ТекОбъект.ПометкаУдаления = СсылкаИсх.ПометкаУдаления;

                СчетчикСозданных  = СчетчикСозданных + 1;

                Сообщить(""+СчетчикСозданных+": "+ТекОбъект);

                ТекОбъект.Записать();

                Если СокрЛП(ПроставлятьСсылкуНаРезультатВРеквизите) <> "" Тогда

                               ОбъектИсх = СсылкаИсх.ПолучитьОбъект();

                               ОбъектИсх[СокрЛП(ПроставлятьСсылкуНаРезультатВРеквизите)] = ТекОбъект.Ссылка;

                               ОбъектИсх.Записать();

                КонецЕсли;

                Если ЧислоОбрабатываемых<>0 И СчетчикСозданных >= ЧислоОбрабатываемых Тогда

                               Прервать;

                КонецЕсли;

                //Обновляем элемент

                //Ставим родителя

                ОбработкаПрерыванияПользователя();

                //Прервать;

КонецЦикла;

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

Но в целом, я использовал этот алгоритм достаточно универсально для переноса и синхронизации по ГУИД около пять-восьми справочников разного типа.
Надеюсь, вам тоже пригодится.