При настройке обмена данными между конфигурациями 1С с помощью «Конвертации данных 2.1» часто возникает ситуация, когда иерархия справочников в источнике и приемнике не совпадает. Типичная задача: если при переносе объект (например, Номенклатура) уже существует в базе-приемнике, его нужно оставить в той папке, где он находится. Однако, если объект новый и создается в процессе загрузки, его необходимо поместить в заранее определенную группу (например, «Новые из обмена»), чтобы пользователь позже мог разнести его вручную. В этой статье мы подробно разберем, как реализовать такую логику несколькими способами.
Этот метод считается наиболее гибким и надежным. Рассмотрим ситуацию: мы переносим документ, в реквизите которого указана Номенклатура. В правилах конвертации объектов (ПКО) для этого справочника мы можем перехватить момент, когда система уже попыталась найти объект, но еще не записала его в базу данных.
Проанализируем работу обработчика После загрузки. Этот обработчик выполняется после прочтения всех атрибутов объекта из файла, но до вызова метода Записать(). Нам доступны важные параметры: ОбъектНайден (булево) и Объект (ссылка на создаваемый или найденный объект).
Рассмотрим пример кода, который необходимо разместить в ПКО справочника в событии После загрузки:
Если ОбъектНайден Тогда
// Если объект найден, нам важно сохранить его текущую иерархию в приемнике.
// Параметр Ссылка содержит ссылку на существующий объект в базе.
Объект.Родитель = Ссылка.Родитель;
Иначе
// Если объект не найден, значит, создается новый.
// Нам нужно найти целевую папку. Для оптимизации лучше делать это один раз.
ЦелеваяГруппа = Справочники.Номенклатура.НайтиПоНаименованию("Новые поступления (перенос)");
Если Не ЦелеваяГруппа.Пустая() Тогда
Объект.Родитель = ЦелеваяГруппа;
КонецЕсли;
КонецЕсли;
В данном примере мы проверяем статус идентификации. Если объект новый, мы принудительно назначаем ему родителя. Если старый — возвращаем ему того родителя, который уже задан в информационной базе-приемнике, игнорируя данные из файла обмена.
Прежде чем приступать к написанию кода, необходимо проверить настройки самого ПКО на закладке «Настройки поиска». Выясним причину, по которой поиск может работать некорректно. Если у вас установлен флаг «Искать вхождением в родителя», система будет искать Ящик только внутри папки Тара. Если в базе-приемнике Ящик уже лежит в папке Складская оснастка, поиск не сработает, и система создаст дубль.
Рекомендация: Для реализации нашей задачи снимите флаг Искать вхождением в родителя в настройках ПКО. Поиск должен идти только по ключевым полям (например, по наименованию или артикулу) во всем справочнике.
Существует и «бескодовый» способ решения, основанный на настройках правил конвертации свойств (ПКС). Рассмотрим, как это работает через интерфейс настройки правил:
Родитель.Перед выгрузкой можно указать фиксированного родителя.Разберем логику этого механизма. Когда КД 2.1 находит существующий объект в приемнике, она видит, что у него уже заполнен реквизит Родитель. Благодаря флагу «Не замещать», система пропустит это поле и оставит текущее значение. Если же объект создается с нуля, значение Родитель в базе еще не определено (оно пустое), и система запишет туда данные из файла или значение по умолчанию.
Минус этого метода: Он менее гибкий. Если в будущем вам потребуется все-таки перенести изменение родителя для существующих объектов, этот флаг будет мешать.
Посмотрим на ситуацию с точки зрения производительности. Если в файле переноса 10 000 позиций номенклатуры, то вызов НайтиПоНаименованию в каждом объекте 10 000 раз существенно замедлит загрузку. Чтобы избежать этого, применим кэширование через Параметры конвертации.
Шаг 1. В глобальном обработчике Перед загрузкой данных (на уровне всей конвертации) найдем нужную группу один раз:
Параметры.Вставить("ГруппаДляНовыхОбъектов", Справочники.Номенклатура.НайтиПоНаименованию("ТехническаяПапка"));
Шаг 2. В ПКО справочника в событии После загрузки используем готовую ссылку:
Если Не ОбъектНайден Тогда
Объект.Родитель = Параметры.ГруппаДляНовыхОбъектов;
КонецЕсли;
Такой подход позволяет не только ускорить работу, но и легко изменять целевую папку, вынеся её поиск в одно место или даже сделав её настраиваемой через диалог перед началом загрузки.
Проанализируем возможные ошибки при назначении родителя программно. При работе с иерархическими справочниками важно учитывать тип иерархии. Если справочник имеет тип «Иерархия групп и элементов», мы должны быть уверены, что назначаемый родитель сам является группой.
Рассмотрим дополненный код с проверкой на тип объекта:
Если Не ОбъектНайден Тогда
НовыйРодитель = Параметры.ГруппаДляНовыхОбъектов;
Если ЗначениеЗаполнено(НовыйРодитель) И НовыйРодитель.ЭтоГруппа Тогда
Объект.Родитель = НовыйРодитель;
Иначе
ЗаписьЖурналаРегистрации("Конвертация", УровеньЖурналаРегистрации.Предупреждение, , , "Не удалось определить группу для нового объекта!");
КонецЕсли;
КонецЕсли;
Также стоит помнить о флаге ОбъектМодифицирован. В некоторых версиях платформы 8.3 при изменении реквизитов объекта в обработчике После загрузки система может не увидеть изменений, если остальные поля совпали. Хотя КД 2.1 обычно обрабатывает это корректно, в сложных случаях можно явно вызвать Объект.Записать(), однако делать это нужно осторожно, чтобы не нарушить транзакцию загрузки основного документа.
Для решения задачи «Родитель по условию» наиболее рекомендуемым является Метод 1 в сочетании с Методом 3. Это дает полный контроль над логикой идентификации объектов и обеспечивает высокую скорость обработки данных. Главное — не забывать отключать поиск «вхождением в родителя», если вы планируете перемещать объекты между папками в базе-приемнике независимо от источника.