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