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