Порой при переводе систем с одной конфигурации на другую нужно часто переносить справочники из одних в другие.
При этом сложно завязываться на код или наименование.
Но! Можно завязаться на GUID элемента. 1С позволяет использовать один и тот же GUID в разных справочниках.
Причем в составных полях хранится не только GUID, но и тип, поэтому использование в одной базе ссылок с одинаковым GUID но разным типом безопасно!
Для примера рассмотрим алгоритм, который переносит один справочник в другой, используя синхронизацию по GUID.
Понятно, что его можно использовать многократно.
Алгоритм имеет следующие параметры:
Наименование |
Направление передачи |
ТипУчастникаКА |
Внутренний |
зпЗапрос |
Вход |
ИдентификаторРезСправочника |
Вход |
ПапкаНовых |
Вход |
ТолькоНовые |
Вход |
ГрузитьИерархию |
Вход |
ГрузитьПодчиненность |
Вход |
ВладелецНовых |
Вход |
ЧислоОбрабатываемых |
Вход |
ИерархияЭлементовВИерархиюГрупп |
Вход |
ПроставлятьСсылкуНаРезультатВРеквизите |
Вход |
//Запрос, которым получаем исходные элементы
Запрос = ПолучитьЗапрос(зпЗапрос);
ТЗ = Запрос.Выполнить().Выгрузить();
ТЗ.Колонки.Добавить("Уровень");
//Сортируем по уровню
//Чтобы группы создавались раньше элементов, в один проход тогда можно
Состояние("Индексация");
Для Каждого СтрокаТЧ ИЗ ТЗ Цикл
Попытка
СтрокаТЧ.Уровень = СтрокаТЧ.Ссылка.Уровень();
Исключение
Прервать; //Не индексируем
КонецПопытки;
ОбработкаПрерыванияПользователя();
КонецЦикла;
ТЗ.Сортировать("Уровень Возр");
//Загрузка
Состояние("Загрузка");
СчетчикСозданных= 0;
//Перебираем объекты
Для Каждого СтрокаТЧ ИЗ ТЗ Цикл
ОбработкаПрерыванияПользователя();
//Получаем GUID исходного элемента
СсылкаИсх = СтрокаТЧ.Ссылка;
МенеджерИсх = Справочники[СсылкаИсх.Метаданные().Имя];
ГуидИсх = СсылкаИсх.УникальныйИдентификатор();
Попытка
ГуидИсхРодитель = СсылкаИсх.Родитель.УникальныйИдентификатор();
Исключение
ГуидИсхВладелец = СсылкаИсх.Родитель.УникальныйИдентификатор();
КонецПопытки;
//Формируем GUID результирующего элемента и родителей, владельцев
СсылкаРез = Справочники[ИдентификаторРезСправочника].ПолучитьСсылку(ГуидИсх);
Попытка
СсылкаРезРодитель = Справочники[ИдентификаторРезСправочника].ПолучитьСсылку(ГуидИсхРодитель);
Исключение
СсылкаРезВладелец = Справочники[ИдентификаторРезСправочника].ПолучитьСсылку(ГуидИсхВладелец);
КонецПопытки;
//Находим элемент по GUID, если его нет, то формируем
ТекОбъект = СсылкаРез.ПолучитьОбъект();
Попытка
ЭтоГруппаИсх = СсылкаИсх.ЭтоГруппа;
Исключение
ЭтоГруппаИсх = ложь;
КонецПопытки;
Если ИерархияЭлементовВИерархиюГрупп Тогда
Выборка = МенеджерИсх.Выбрать(СсылкаИсх);
Если Выборка.Следующий() Тогда
ЭтоГруппаИсх = истина;
КонецЕсли;
КонецЕсли;
//Создаем объект или группу, в зависимости от того, был элемент группой или нет
Если ТекОбъект = Неопределено Тогда
Если ЭтоГруппаИсхТогда
Попытка
ТекОбъект = Справочники[ИдентификаторРезСправочника].СоздатьГруппу();
Исключение
ТекОбъект = Справочники[ИдентификаторРезСправочника].СоздатьЭлемент();
КонецПопытки;
Иначе
ТекОбъект = Справочники[ИдентификаторРезСправочника].СоздатьЭлемент();
КонецЕсли;
ТекОбъект.УстановитьСсылкуНового(СсылкаРез);
Иначе
Если ТолькоНовые Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
//Устанавливаем папку
Попытка
Если ЗначениеЗаполнено(ПапкаНовых) Тогда
ТекОбъект.Папка = ПапкаНовых;
КонецЕсли;
Исключение
КонецПопытки;
//Устанавливаем владельца
Попытка
Если ЗначениеЗаполнено(ВладелецНовых) Тогда
ТекОбъект.Владелец = ВладелецНовых;
КонецЕсли;
Исключение
КонецПопытки;
//Если переносим иерархию
Попытка
Если ГрузитьИерархию=истина Тогда
ТекОбъект.Родитель = СсылкаРезРодитель.ПолучитьОбъект().Ссылка;
КонецЕсли;
Исключение
КонецПопытки;
Попытка
Если ГрузитьПодчиненность=истина Тогда
ТекОбъект.Владелец = СсылкаРезВладелец.ПолучитьОбъект().Ссылка;
КонецЕсли;
Исключение
КонецПопытки;
//Устанавливаем наименование и код
ТекОбъект.Наименование = СсылкаИсх.Наименование;
//ТекОбъект.Код = СсылкаИсх.Код;
//Устанавливаем код синхронизации
Попытка
ТекОбъект.ИдВнешний = СсылкаИсх.Код6;
Исключение
Попытка
ТекОбъект.ИдВнешний = СсылкаИсх.ИдВнешний;
Исключение
КонецПопытки
КонецПопытки;
//Устанавливаем тип участника, если это справочник участников
Попытка
ТекОбъект.ТипУчастника = ТипУчастникаКА;
Исключение
КонецПопытки;
ТекОбъект.ПометкаУдаления = СсылкаИсх.ПометкаУдаления;
СчетчикСозданных= СчетчикСозданных + 1;
Сообщить(""+СчетчикСозданных+": "+ТекОбъект);
ТекОбъект.Записать();
Если СокрЛП(ПроставлятьСсылкуНаРезультатВРеквизите) <> "" Тогда
ОбъектИсх = СсылкаИсх.ПолучитьОбъект();
ОбъектИсх[СокрЛП(ПроставлятьСсылкуНаРезультатВРеквизите)] = ТекОбъект.Ссылка;
ОбъектИсх.Записать();
КонецЕсли;
Если ЧислоОбрабатываемых<>0 И СчетчикСозданных >= ЧислоОбрабатываемых Тогда
Прервать;
КонецЕсли;
//Обновляем элемент
//Ставим родителя
ОбработкаПрерыванияПользователя();
//Прервать;
КонецЦикла;
В коде используется функция ПолучитьЗапрос, которая получает объект запроса по его идентификатору (у нас в конфигурации ведется реестр запросов).
Есть также некоторые заточки по заполнению новых элементов определенного типа.
Но в целом, я использовал этот алгоритм достаточно универсально для переноса и синхронизации по ГУИД около пять-восьми справочников разного типа.
Надеюсь, вам тоже пригодится.