Как избежать дублирования групп справочника при переносе в Конвертации данных

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

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

Выясним причину дублирования групп при обмене

Проанализируем базовый механизм сопоставления объектов платформы 1С при загрузке данных. По умолчанию в правиле конвертации объекта (ПКО) активен флаг Искать объект приемника по внутреннему идентификатору (GUID). Механизм загрузки отрабатывает по следующему алгоритму:

  1. Обработка загрузки считывает уникальный идентификатор объекта из файла выгрузки.
  2. Выполняется попытка найти ссылку в базе-приемнике именно по этому GUID через метод менеджера справочника ПолучитьСсылку.
  3. Если папка «Продукция» создавалась в обеих базах вручную независимыми пользователями, их внутренние идентификаторы гарантированно различаются, даже если код и наименование абсолютно одинаковы.
  4. Если сопоставление по GUID не увенчалось успехом, а флаг Продолжить поиск по полям поиска, если по идентификатору объект не найден выключен, обработка обмена считает, что такого объекта в базе-приемнике нет, и создает новую папку с новым кодом или дублирующимся кодом рядом со старой.

Способ 1. Настройка стандартных параметров поиска в ПКО

Рассмотрим самое простое и быстрое решение, которое применимо в большинстве типовых переносов. Для устранения дублирования папок нам требуется изменить логику поиска на вкладке настроек соответствующего правила конвертации объектов:

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

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

Способ 2. Учет различия длины кода между базами

Часто встречается ситуация, когда в источнике длина кода справочника составляет 10 символов, а в приемнике — 11 символов. Если просто включить типовое приведение длины, строка кода может быть дополнена пробелами справа, тогда как нумератор типовой конфигурации 1С формирует текстовые коды с ведущими нулями слева (например, код 0000000005 в базе с 11 знаками должен стать 00000000005). Если количество ведущих нулей не совпадает, точное строковое равенство не сработает, и группа снова создастся повторно.

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

Значение = Прав("00000000000" + СокрЛП(Источник.Код), 11);

Такое преобразование гарантирует, что поиск по коду в базе-приемнике найдет именно существующую группу без создания дубликата из-за несовпадающего строкового представления.

Способ 3. Разделение правил конвертации для элементов и групп

В сложных обменах наиболее надежным решением является физическое разделение логики переноса элементов и папок на два разных правила конвертации объектов. Рассмотрим, как реализовать такую архитектуру:

  1. Создадим первое правило конвертации: Номенклатура_Элементы. В обработчике Перед выгрузкой этого ПКО установим условие:

Если Источник.ЭтоГруппа Тогда
    Отказ = Истина;
КонецЕсли;
  1. Создадим второе правило конвертации: Номенклатура_Группы. В его обработчике Перед выгрузкой пропишем обратное условие:

Если Не Источник.ЭтоГруппа Тогда
    Отказ = Истина;
КонецЕсли;
  1. Для правила Номенклатура_Группы полностью отключим поиск по внутреннему идентификатору и укажем поля поиска Код или Наименование. Для защиты структуры папок приемника от перезаписи можно также включить флаг Не замещать существующие объекты при загрузке (обновлять только пустые).
  2. В правиле Номенклатура_Элементы для ПКС Родитель явно укажем правило конвертации: Номенклатура_Группы.

Такой подход полностью изолирует настройки поиска папок от настроек конечных номенклатурных позиций.

Способ 4. Алгоритмическое сопоставление через обработчик ПоляПоиска

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

Посмотрим на пример переопределения поиска для папок через коллекцию СвойстваПоиска:


Если СвойстваПоиска["ЭтоГруппа"] = Истина Тогда
    НайденнаяГруппа = Справочники.Номенклатура.НайтиПоКоду(СвойстваПоиска["Код"]);
    Если ЗначениеЗаполнено(НайденнаяГруппа) Тогда
        СсылкаНаОбъект = НайденнаяГруппа;
        ПрекратитьПоиск = Истина;
    КонецЕсли;
КонецЕсли;

Переменная ПрекратитьПоиск = Истина сообщает механизму загрузки, что сопоставление успешно завершено, и стандартные механизмы сравнения по идентификаторам или таблицам полей поиска вызываться больше не будут.

Способ 5. Переопределение родителя при загрузке

Если стоит задача не просто сопоставить папки, а принудительно сложить всю выгружаемую номенклатуру в конкретную заранее созданную папку приемника, удобнее всего сделать это в обработчике Перед загрузкой или При загрузке объекта-приемника.

Рассмотрим пример кода в обработчике ПКО При загрузке:


Если Не Объект.ЭтоГруппа Тогда
    ЦелеваяПапка = Справочники.Номенклатура.НайтиПоКоду("00000000005");
    Если ЗначениеЗаполнено(ЦелеваяПапка) Тогда
        Объект.Родитель = ЦелеваяПапка;
    КонецЕсли;
КонецЕсли;

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

← На главную