Как переносить номенклатуру в определенную группу приемника с помощью реквизитов плана обмена в 1С:Конвертация данных 2.1

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

При настройке обмена данными между конфигурациями 1С (например, при переходе с устаревшей версии 1С:Предприятие 7.7 на современную платформу 1С 8) часто возникает задача распределения загружаемых данных по определенным папкам. Распространенный сценарий: всю входящую номенклатуру из источника необходимо автоматически помещать в специальную группу (папку) в базе-приемнике. При этом сама целевая группа создается непосредственно в приемнике, а информация о ней хранится в реквизитах узла плана обмена.

В этой статье мы подробно разберем, как правильно реализовать данный механизм в конфигурации «Конвертация данных 2.1» (КД 2.1), избежав типичных ошибок производительности и обеспечив безопасность кода при ручной загрузке данных.

Анализ исходной проблемы и критическая оценка подходов

В процессе обсуждения на форуме автор предложил передавать код группы из базы-приемника через параметры, а затем искать эту группу в приемнике с помощью функции НайтиПоКоду. Давайте проанализируем, почему этот подход не является оптимальным:

  1. Лишняя нагрузка на базу данных. Вызов метода НайтиПоКоду для каждого загружаемого элемента номенклатуры порождает сотни или тысячи избыточных запросов к СУБД. При объеме справочника в десятки тысяч позиций это может критически замедлить процесс импорта.
  2. Риск дублирования или неверного поиска. Кодировка в справочнике может быть неуникальной или зависеть от уровня иерархии (в пределах подчинения). Поиск по коду в таких условиях может вернуть ссылку на совершенно другую группу.
  3. Избыточность действий. Поскольку узел обмена и целевая папка находятся в одной и той же информационной базе (в приемнике), у нас уже есть прямой доступ к самой ссылке на эту группу. Передавать ее код, чтобы потом снова искать ссылку, не имеет практического смысла.

Наиболее правильным и производительным решением является прямая передача ссылки на элемент справочника Номенклатура через глобальную структуру параметров конвертации.

Шаг 1. Передача ссылки на группу через обработчик узла обмена

Для начала нам необходимо перехватить узел обмена в момент начала загрузки данных в приемнике и извлечь из его реквизита ссылку на целевую папку. Для этого мы воспользуемся глобальным обработчиком конвертации «После получения информации об узлах обмена».

Этот обработчик выполняется на стороне приемника сразу после того, как из файла обмена прочитаны данные о текущем узле. В контексте этого обработчика нам доступна переменная УзелОбменаЗагрузкаДанных.

Важно предусмотреть защиту от ошибок. Если загрузка будет выполняться интерактивно через обработку УниверсальныйОбменДаннымиXML (например, во время отладки правил), переменная УзелОбменаЗагрузкаДанных может иметь значение Неопределено или содержать пустую ссылку. Прямое обращение к реквизиту в таком случае вызовет аварийное завершение работы системы.

Запишем безопасный и отказоустойчивый код для обработчика «После получения информации об узлах обмена»:


// Проверяем, что загрузка идет в контексте реального плана обмена
Если УзелОбменаЗагрузкаДанных <> Неопределено 
   И Не УзелОбменаЗагрузкаДанных.Пустая() Тогда
    
    // Используем Попытка-Исключение на случай, если правила запущены 
    // в базе, где у плана обмена временно отсутствует данный реквизит
    Попытка
        Параметры.Вставить("ГруппаНоменклатуры", УзелОбменаЗагрузкаДанных.КЭ_ГруппаНоменклатуры);
    Исключение
        Параметры.Вставить("ГруппаНоменклатуры", Справочники.Номенклатура.ПустаяСсылка());
    КонецПопытки;
Иначе
    // Если обмен запущен вручную без указания узла, инициализируем параметр пустой ссылкой
    Параметры.Вставить("ГруппаНоменклатуры", Справочники.Номенклатура.ПустаяСсылка());
КонецЕсли;

Шаг 2. Настройка ПКО для автоматической смены родителя

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

Откроем обработчик события «После загрузки». Данный обработчик выполняется непосредственно перед тем, как объект запишется в базу данных приемника. Здесь мы можем переопределить родителя для загружаемого элемента.

Проанализируем код, который необходимо написать в этом обработчике:


// Проверяем, задана ли целевая папка в параметрах обмена
Если ЗначениеЗаполнено(Параметры.ГруппаНоменклатуры) Тогда
    
    // Переносим только элементы (не трогаем иерархию групп из источника, если это необходимо)
    // Также проверяем, чтобы у объекта еще не был заполнен родитель (или перезаписываем принудительно)
    Если Не Объект.ЭтоГруппа И Не ЗначениеЗаполнено(Объект.Родитель) Тогда
        
        // Назначаем родителем группу, указанную в плане обмена
        Объект.Родитель = Параметры.ГруппаНоменклатуры;
        
    КонецЕсли;
КонецЕсли;

Важное примечание: Если вам требуется принудительно перемещать абсолютно всю номенклатуру (включая группы и подгруппы из источника) внутрь этой папки, условие проверки можно упростить:


Если ЗначениеЗаполнено(Параметры.ГруппаНоменклатуры) Тогда
    // Исключаем зацикливание: группа не должна стать родителем самой себе
    Если Объект.Ссылка <> Параметры.ГруппаНоменклатуры Тогда
        Объект.Родитель = Параметры.ГруппаНоменклатуры;
    КонецЕсли;
КонецЕсли;

Шаг 3. Декларирование параметров в Конвертации данных (рекомендация)

Несмотря на то, что метод Параметры.Вставить() динамически создает ключ в структуре прямо во время выполнения кода, хорошим тоном разработки в КД 2.1 является явное декларирование параметров.

Для этого выполните следующие действия в интерфейсе конфигурации «Конвертация данных»:

  1. Перейдите на вкладку «Параметры» в настройках правил обмена.
  2. Добавьте новую строку с именем ГруппаНоменклатуры.
  3. Укажите тип данных — СправочникСсылка.Номенклатура.
  4. Снимите флаг «Передавать при выгрузке», так как этот параметр используется исключительно на стороне приемника.

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

Особенности контроля уникальности и иерархии

При массовом переносе элементов в единую папку на стороне приемника могут возникнуть коллизии. Проанализируем возможные проблемы и способы их решения:

  1. Уникальность кодов в пределах подчинения. Если в свойствах справочника Номенклатура в конфигурации-приемнике стоит контроль уникальности кодов «В пределах подчинения», то при переносе множества элементов в одну папку система может выдать ошибку уникальности. В таком случае в обработчике «После загрузки» может потребоваться перегенерация кодов с помощью метода Объект.УстановитьНовыйКод().
  2. Транзакционность записи. Обработчик «После загрузки» выполняется до вызова метода Записать(). Это означает, что переопределение родителя не потребует повторного обращения к базе данных для перезаписи — объект сохранится в СУБД за один шаг, что гарантирует максимальное быстродействие решения.
← На главную