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