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