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