Рассмотрим достаточно распространенную задачу при переносе данных между базами 1С: необходимо сконвертировать элементы справочника из базы-источника в базу-приемник. Проблема возникает тогда, когда в источнике элементов существенно больше, и часть из них является предопределенными, а в базе-приемнике таких предопределенных элементов нет (отсутствуют соответствующие имена метаданных). В результате обычные элементы переносятся корректно, а предопределенные загружаются в приемник как пустые ссылки (битые значения). Проанализируем эту ситуацию и разберем по шагам, как заставить правила обмена относиться к таким элементам как к обычным и создавать их в приемнике.
Для начала разберем техническую сторону работы «1С:Конвертации данных 2.1». Откуда система вообще знает, что элемент особенный?
Когда КД 2.1 выгружает объект, она сверяется со структурой метаданных базы-источника, которая была предварительно загружена в конфигурацию КД (в справочники Конфигурации, Объекты, Свойства и Значения). Если элемент числится в справочнике Значения как предопределенный, в формируемый файл обмена (XML) принудительно записывается специальный системный тег ИмяПредопределенногоДанных.
Что происходит при загрузке в базу-приемник? Универсальная обработка обмена (V8Exchan82.epf) видит этот тег в XML-файле и пытается найти элемент строго по этому имени в конфигураторе. Если такого предопределенного имени в конфигурации приемника нет, обработка даже не пытается искать элемент по стандартным полям поиска (Коду или Наименованию). Поскольку создать новый предопределенный элемент в режиме 1С:Предприятие невозможно (это делается исключительно в Конфигураторе), обработка просто возвращает пустую ссылку.
Посмотрим на самое простое концептуальное решение. Если в базе-приемнике нет соответствия предопределенным элементам, то нам просто не нужно, чтобы база-источник (и сами правила КД) определяла их как предопределенные. Пусть работают обычные правила создания объектов.
Для реализации этого метода выполним следующие шаги:
Значения).Значения или снимем у них признак предопределенности.Теперь при выгрузке обработка не будет писать тег ИмяПредопределенногоДанных в XML, и элементы приедут как обычные данные.
Важный подводный камень: Как только вы решите обновить структуру метаданных источника (например, загрузите свежий файл описания структуры конфигурации), КД заново обновит эти элементы и вернет им флаг предопределенности. Вам придется помнить об этом нюансе и каждый раз после обновления структуры вручную снимать этот признак, иначе обмен снова сломается.
Если мы заставляем систему относиться к предопределенным элементам как к обычным (через ручную правку в КД), нам необходимо убедиться, что система сможет их правильно идентифицировать в приемнике.
У предопределенных элементов синхронизация по умолчанию идет жестко по имени метаданных. Когда мы превращаем их в «обычные», системе требуются новые критерии поиска. Обязательно проверьте Правило Конвертации Объекта (ПКО) этого справочника:
Код или Наименование (в зависимости от вашей логики синхронизации).Если этого не сделать, при загрузке обработка попытается найти элементы по Уникальному Идентификатору (УИД) и, не найдя совпадений, может наплодить дублей или снова выдать ошибку.
Если вы не хотите каждый раз вручную править метаданные в КД после обновления структуры конфигурации, разберем более надежный, программный способ. Решить проблему можно в обработчике ПКО «Поля поиска». Этот код будет выполняться на стороне базы-приемника в момент загрузки элемента.
В этом обработчике мы напишем алгоритм, который будет перехватывать ситуацию: если элемент пришел с заполненным именем предопределенного, но стандартный поиск выдает ошибку (так как элемента нет в метаданных приемника), мы программно очистим переменную имени и направим поиск по строке свойств.
Посмотрим на примерный каркас кода, который можно адаптировать под вашу задачу в обработчике «Поля поиска»:
Если ЗначениеЗаполнено(ИмяПредопределенногоДанных) Тогда
// Пытаемся проверить, есть ли такое предопределенное имя в конфигурации приемника
ИмяСправочника = "НашСправочник";
Попытка
СсылкаНаОбъект = Справочники[ИмяСправочника][ИмяПредопределенногоДанных];
Исключение
// Элемента в конфигураторе нет!
// Очищаем системную переменную, чтобы отключить поиск по имени метаданных
ИмяПредопределенногоДанных = "";
// Теперь обработка перейдет к стандартному поиску по свойствам,
// указанным в ПКС (например, по Коду или Наименованию).
// Дополнительно можно программно сформировать строку поиска:
// СтрокаИменСвойствПоиска = "Код, Наименование";
КонецПопытки;
КонецЕсли;
Проанализируем этот код. Блок Попытка ... Исключение защищает нас от ошибки при обращении к несуществующему имени метаданных. В блоке исключения мы принудительно обнуляем ИмяПредопределенногоДанных. Дальше стандартный механизм загрузки КД увидит, что имя пустое, и пойдет искать объект по значениям реквизитов (из переменной СвойстваПоиска). Если по коду или наименованию объект в базе не найдется, универсальная обработка корректно создаст новый, уже совершенно обычный (не предопределенный) элемент справочника.
Подведем итог: оба метода рабочие. Если структура базы меняется редко — можно просто убрать признак в самой КД. Если вы предпочитаете "настроил и забыл" — смело используйте программный перехват в обработчике «Поля поиска». Не забывайте про обязательную настройку ПКС для поиска по коду или наименованию.