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