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