При настройке обмена данными между конфигурациями 1С с помощью «1С:Конвертация данных» (КД 2.1) разработчики часто сталкиваются с неприятной ситуацией: при первой загрузке данные переносятся корректно, но при повторном запуске обмена те же самые объекты (например, договора, контрагенты или документы) начинают дублироваться. В этой статье мы подробно разберем, почему возникает этот эффект на примере договоров контрагентов, проанализируем поведение платформы и научимся правильно настраивать правила конвертации объектов (ПКО) и свойств (ПКС) для исключения подобных ошибок.
Для начала разберем общую механику сопоставления объектов. При импорте данных из XML-файла конфигурация «Универсальный обмен данными в формате XML» считывает свойства объектов и пытается найти их в базе-приемнике. Поиск происходит по тем полям, у которых в правилах конвертации свойств (ПКС) установлен флаг «Поиск». Это может быть УникальныйИдентификатор (GUID), Код, Наименование, Номер или любая другая комбинация реквизитов.
Задвоение происходит в тот момент, когда поисковый запрос КД в базу-приемник возвращает пустой результат (объект не найден), хотя визуально этот объект в базе уже существует. Выясним, почему стандартный поиск по текстовому полю (такому как Номер или Код) может не находить существующую запись.
Проанализируем конкретный пример. В правиле конвертации свойств для реквизита Номер написан следующий обработчик «Перед выгрузкой»:
Если Не ЗначениеЗаполнено(Источник.Номер) Тогда
Значение = "1";
КонецЕсли;
Рассмотрим по шагам, что происходит во время первой и последующих загрузок:
"1". В базе-приемнике выполняется поисковый запрос. Поскольку база чистая, договор с номером "1" не найден. КД создает новый договор, присваивает ему номер "1" и записывает объект.Записать() в базе-приемнике срабатывают механизмы платформы 1С (автонумерация) или подписки на события. Длина реквизита Номер (или Код) в базе-приемнике жестко ограничена (например, 9 символов). Платформа автоматически дополняет переданный номер лидирующими нулями до стандартного формата. В результате в базе сохраняется договор с фактическим номером "000000001"."1" и ищет в базе-приемнике договор с точным соответствием строки: Номер = "1". Но в базе теперь записана строка "000000001"! С точки зрения СУБД, строки "1" и "000000001" не равны. Поиск завершается неудачей. КД считает, что договора нет, создает новый (второй) договор с номером "1", который при записи снова превращается в "000000001" (или "000000002" в зависимости от работы автонумерации). Происходит задвоение.Аналогичная проблема возникает, если в строковых реквизитах поиска присутствуют невидимые пробелы. Например, в источнике номер был записан как " 1 " (с пробелами по краям), а при записи в приемник или в процессе выгрузки пробелы были обрезаны функцией СокрЛП(). Поиск по строке с пробелом никогда не сопоставится со строкой без пробелов.
Для предотвращения дублирования данных мы можем применить несколько эффективных решений. Выбор зависит от того, насколько критичен поиск именно по этому реквизиту.
В настройках ПКС для реквизита, по которому осуществляется поиск (в нашем случае Номер или Код), предусмотрено специальное свойство. Перейдем в настройки правила конвертации свойств и установим флаг «Дополнять строку до длины приемника» (или выберем соответствующую настройку выравнивания и заполнения символами, например, лидирующими нулями). В этом случае КД сама преобразует значение "1" в "000000001" перед отправкой поискового запроса к базе данных, и сопоставление отработает корректно.
Если мы хотим полностью контролировать процесс формирования номера, мы можем дописать программный код в обработчик «Перед выгрузкой» ПКС Номер. Принудительно приведем значение номера к формату базы-приемника, удалив лишние пробелы и добавив нули:
// Очищаем от случайных пробелов
Значение = СокрЛП(Источник.Номер);
Если Не ЗначениеЗаполнено(Значение) Тогда
Значение = "1";
КонецЕсли;
// Приводим к длине приемника (например, 9 символов)
ДлинаПриемника = 9;
Пока СтрДлина(Значение) < ДлинаПриемника Цикл
Значение = "0" + Значение;
КонецЦикла;
Такой подход гарантирует, что в XML-файл сразу попадет отформатированное значение "000000001", которое гарантированно будет найдено при повторных поисках.
Зачастую поиск по номеру или наименованию является избыточным и ненадежным. Проанализируем, можем ли мы сопоставлять договора по уникальному идентификатору GUID. Если выгрузка идет из одной и той же информационной базы, установите в ПКО договора флаг «Поиск по уникальному идентификатору». В этом случае КД вообще не будет обращать внимания на текстовые номера при поиске, а свяжет объекты по их внутренним системным ключам. Поиск по номеру в ПКС при этом нужно отключить (снять флаг «Поиск»).
Если проблема глубже, и простыми методами ее локализовать не удается, нам потребуется воспользоваться отладчиком 1С. Разберем по шагам, как запустить отладку загрузки данных в контексте «1С:Конвертация данных»:
Теперь выясним, в каких именно местах кода нам нужно установить точки останова, чтобы понять, почему объект не сопоставляется:
Этот обработчик срабатывает непосредственно перед выполнением поиска в приемнике. Обратите внимание, что на этапе загрузки переменная Источник (объект базы-источника) уже недоступна, так как мы работаем исключительно с файлом XML.
Все переданные свойства поиска содержатся в специальной структуре СвойстваПоиска. Установим точку останова в данном обработчике и добавим в табло выражение СвойстваПоиска. Проанализируем значение свойства СвойстваПоиска["Номер"]. Именно здесь мы увидим, в каком виде номер пришел для сравнения (есть ли там пробелы, лидирующие нули или скрытые символы переноса строк).
Найдем эту процедуру в сгенерированном модуле отладки. В ней КД динамически конструирует SQL-запрос к СУБД для поиска элемента по ключевым полям. Установим точку останова в момент формирования текста запроса и передачи параметров.
Мы сможем скопировать полученный запрос и его параметры, открыть консоль запросов 1С и выполнить его вручную непосредственно в базе данных. Это позволит наглядно увидеть, почему база данных не возвращает ссылку на уже существующий договор при передаче текущих параметров поиска.
Используя предложенные методы форматирования строк и механизмы отладки, мы сможем полностью исключить дублирование записей и гарантировать стабильную работу обмена данными при многократном повторении процедур импорта.