Как реализовать поиск и подмену объекта по произвольному правилу в ПКО при обмене данными

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

Работа с механизмом «1С: Конвертация данных 2.1» (КД 2.1) часто ставит перед разработчиком задачи, выходящие за рамки простого сопоставления полей по наименованию или уникальному идентификатору (GUID). Типичная ситуация: в базе-источнике есть объект (например, Склад1), но в базу-приемник должен попасть не он сам, а другой объект (НовыйСклад), ссылка на который хранится в реквизите исходного объекта. Проанализируем, как правильно реализовать такую подмену, чтобы она работала корректно и глобально для всех документов обмена.

Метод 1: Подмена источника в обработчике «Перед выгрузкой» ПКО

Разберем самый элегантный и «ленивый» способ. Если нам нужно, чтобы везде, где встречается определенный справочник, система автоматически подставляла связанный с ним объект, мы можем изменить сам Источник непосредственно в Правиле Конвертации Объекта (ПКО).

Рассмотрим ситуацию подробнее. У нас есть ПКО Склады. В источнике у справочника Склады есть реквизит СоответствиеВНовойУТ. Мы хотим, чтобы при выгрузке любого склада система фактически выгружала тот склад, который указан в этом реквизите.

Для этого в ПКО Склады, в обработчике Перед выгрузкой, необходимо написать следующий код:


Если ЗначениеЗаполнено(Источник.СоответствиеВНовойУТ) Тогда
    Источник = Источник.СоответствиеВНовойУТ;
КонецЕсли;

Почему это работает: Когда движок конвертации заходит в выполнение ПКО, он инициализирует переменную Источник. Если мы переопределим эту переменную в самом начале, все последующие Правила Конвертации Свойств (ПКС) будут работать уже с новым объектом. В приемник улетят данные (наименование, код, GUID) именно НовогоСклада. Это решение является глобальным: какой бы документ ни ссылался на склад, ПКО отработает именно так.

Метод 2: Использование функции ВыгрузитьПоПравилу в ПКС

Иногда глобальная подмена в ПКО не подходит, или логика выбора объекта должна зависеть от контекста конкретного документа. В этом случае мы можем принудительно указать, какой объект выгружать, в Правиле Конвертации Свойства (ПКС) конкретного реквизита документа.

Проанализируем пример: в документе РеализацияТоваровУслуг есть реквизит Склад. В ПКС этого реквизита, в обработчике Перед выгрузкой, мы можем использовать функцию ВыгрузитьПоПравилу:


// В ПКС реквизита Склад документа
Если ЗначениеЗаполнено(Источник.Склад.СоответствиеВНовойУТ) Тогда
    Значение = ВыгрузитьПоПравилу(Источник.Склад.СоответствиеВНовойУТ, , , , "Склады");
Иначе
    Значение = Источник.Склад;
КонецЕсли;

В данном случае мы явно говорим системе: «Возьми объект из реквизита соответствия и выгрузи его по правилу Склады, а результат запиши в текущее свойство». Этот метод дает максимальный контроль, но требует прописывания кода в каждом ПКС, где используется склад.

Метод 3: Использование обработчика «Поля поиска» в приемнике

Рассмотрим ситуацию, когда данные уже переданы в файл обмена, и нам нужно найти объект в базе-приемнике по сложной логике. Обработчик Поля поиска выполняется на стороне базы-приемника. Важно понимать: здесь у нас нет доступа к объекту Источник из старой базы напрямую, только к тем данным, которые мы передали через XML (включая параметры).

Если мы передали в параметре GUID нужного склада, код в обработчике Поля поиска будет выглядеть так:


// Проверяем наличие параметра, переданного из источника
Если ПараметрыОбъекта <> Неопределено И ПараметрыОбъекта.Свойство("СоответствиеВНовойУТ") Тогда
    УИД_Склада = ПараметрыОбъекта["СоответствиеВНовойУТ"];
    
    // Пытаемся найти ссылку по GUID в приемнике
    СсылкаНаОбъект = Справочники.Склады.ПолучитьСсылку(Новый УникальныйИдентификатор(УИД_Склада));
    
    // Проверяем, существует ли такой объект в базе на самом деле
    Если СсылкаНаОбъект.ПолучитьОбъект() = Неопределено Тогда
        // Если объекта нет, можно оставить СсылкаНаОбъект пустой или искать по другим полям
        СсылкаНаОбъект = Справочники.Склады.ПустаяСсылка();
    Иначе
        // Если объект найден, прекращаем стандартный поиск по полям
        ПрекратитьПоиск = Истина;
    КонецЕсли;
КонецЕсли;

Выясним причину, по которой этот метод часто не срабатывает у новичков. Если в ПКО установлена галочка Искать объект по уникальному идентификатору, то при совпадении GUID система найдет объект еще до выполнения обработчика «Поля поиска». Если вы хотите использовать свою логику поиска, эту галку в настройках ПКО следует снять или правильно управлять переменной НомерВариантаПоиска.

Важные нюансы и рекомендации

При реализации произвольного поиска и подмены объектов следует учитывать несколько критически важных моментов:

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

Таким образом, мы проанализировали основные подходы к поиску объектов по произвольным правилам. Выбор конкретного метода зависит от того, насколько глобальной должна быть подмена и имеете ли вы доступ к GUID объектов в обеих базах.

← На главную