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