При настройке правил обмена в конфигурации "Конвертация данных 2.1" (КД 2) разработчики часто сталкиваются с необходимостью кастомной выгрузки данных. Использование стандартных механизмов выборки не всегда позволяет реализовать сложную бизнес-логику. В таких случаях на помощь приходит способ выборки "Произвольный алгоритм" в Правилах выгрузки данных (ПВД). Однако при программном вызове выгрузки через функцию ВыгрузитьПоПравилу нередко возникает проблема: передаваемые параметры (входящие или исходящие данные) бесследно исчезают и не доходят до Правила конвертации объектов (ПКО).
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем внутренние механизмы работы обработчиков КД 2, научимся правильно использовать сигнатуру функции ВыгрузитьПоПравилу, а также рассмотрим процесс настройки надежной отладки обработчиков выгрузки.
Рассмотрим типичную ситуацию. Разработчик создает ПВД со способом выборки "Произвольный алгоритм" и пытается в цикле по результату запроса выгрузить данные, формируя структуру параметров и передавая ее в ПКО. На стороне ПКО в обработчике ПередВыгрузкой или в Правилах конвертации свойств (ПКС) эти данные оказываются пустыми.
Выясним основные причины такого поведения:
ВыгрузитьПоПравилу. Это самая распространенная ошибка. Платформа 1С критична к позициям аргументов при вызове функций. Пропуск запятых или передача структуры не в тот параметр приводит к тому, что КД пытается интерпретировать переданную структуру как XML-узел или объект-источник.ПередВыгрузкой ПВД вместо ПередОбработкой при произвольном алгоритме. При произвольном алгоритме без инициализации выборки стандартный цикл выгрузки ПВД просто не запускается, следовательно, событие ПередВыгрузкой ПВД вообще не вызывается.Разберем каждый из этих нюансов по шагам, чтобы выстроить правильную и отказоустойчивую схему обмена.
Глобальная функция ВыгрузитьПоПравилу — это основной инструмент разработчика для программного запуска конвертации. Проанализируем ее сигнатуру:
ВыгрузитьПоПравилу(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ИмяПКО, УзелСсылка, ТолькоПолучитьСсылка, Проводки, ИмяПКОВидСубконто)
Для правильной передачи параметров нам принципиально важны первые пять аргументов. Посмотрим на их назначение подробнее:
Источник (1-й параметр): Ссылка на объект-источник (например, документ, справочник) или структура/строка таблицы значений, если мы выгружаем данные не из объектной сущности. Если физического источника нет, и мы генерируем данные полностью "из головы", этот параметр обязательно оставляют пустым (передают Неопределено).Приемник (2-й параметр): Узел XML-документа приемника. Обычно при ручном вызове передается как Неопределено или просто пропускается через запятую.ВходящиеДанные (3-й параметр): Произвольная структура вспомогательных данных. Именно этот параметр будет доступен внутри ПКО (и его ПКС) под именем ВходящиеДанные. Сюда мы помещаем те значения, которых нет в объекте-источнике, но которые необходимы для заполнения реквизитов приемника.ИсходящиеДанные (4-й параметр): Структура вспомогательных данных для ПКС текущего правила. Используется реже, в основном для передачи контекста на уровень ниже.ИмяПКО (5-й параметр): Строковое имя правила конвертации объектов, по которому должна выполниться выгрузка.Проанализируем типичные ошибки позиционирования параметров, которые совершают разработчики:
// Ошибка 1: Передача структуры вторым параметром вместо третьего
ВыгрузитьПоПравилу(, ИсходящиеДанные);
// Ошибка 2: Структура передана третьим параметром, но не указано имя ПКО
ВыгрузитьПоПравилу(, , ВходящиеДанные);
В первом случае система попытается обработать структуру параметров как XML-приемник, что приведет к ошибке выполнения или игнорированию данных. Во втором случае, поскольку имя ПКО не указано, а источник пуст (первый параметр не задан), система не сможет определить, по какому именно правилу нужно конвертировать данные, и выгрузка не произойдет вовсе.
Рассмотрим правильный шаблон вызова функции ВыгрузитьПоПравилу:
// Шаблон 1: Выгружаем существующий объект (ссылку) с передачей параметров
ВыгрузитьПоПравилу(СсылкаНаОбъект, , МояСтруктураПараметров, , "ИмяНужногоПКО");
// Шаблон 2: Выгружаем "виртуальный" объект без источника (на основе структуры)
ВыгрузитьПоПравилу(, , МояСтруктураПараметров, , "ИмяНужногоПКО");
При использовании способа выборки "Произвольный алгоритм" критически важно понимать жизненный цикл выполнения обработчиков ПВД.
Рассмотрим два основных сценария работы с произвольным алгоритмом:
В этом сценарии мы пишем весь код (запрос, обход выборки, заполнение структур и вызов выгрузки) непосредственно в обработчике ПВД ПередОбработкой. Это наиболее гибкий и контролируемый способ. Посмотрим на пример реализации такого алгоритма:
// Обработчик ПВД "ПередОбработкой"
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеестрПлатежей.Ссылка КАК Ссылка,
| РеестрПлатежей.Организация КАК Организация,
| РеестрПлатежей.СуммаДокумента КАК Сумма
|ИЗ
| Документ.РеестрПлатежей КАК РеестрПлатежей
|ГДЕ
| РеестрПлатежей.Проведен";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Инициализируем структуру входящих данных на каждой итерации цикла
ПараметрыПередачи = Новый Структура;
ПараметрыПередачи.Вставить("ОрганизацияПриемник", Выборка.Организация);
ПараметрыПередачи.Вставить("СуммаДокумента", Выборка.Сумма);
// Выгружаем одну ссылку в ПКО с передачей параметров
ВыгрузитьПоПравилу(Выборка.Ссылка, , ПараметрыПередачи, , "бит_РеестрПлатежейСтруктура");
КонецЦикла;
// Обязательно устанавливаем Отказ в Истина!
// Это указывает платформе, что стандартную выгрузку для этого ПВД производить не нужно.
Отказ = Истина;
Обратите внимание на важный момент: в конце обработчика ПередОбработкой мы устанавливаем Отказ = Истина;. Если этого не сделать, платформа после выполнения нашего ручного алгоритма попытается запустить стандартный механизм выгрузки для этого ПВД, что приведет к дублированию выгрузки или к ошибкам, так как стандартные параметры выборки для ПВД не инициализированы.
Если мы не хотим вручную вызывать ВыгрузитьПоПравилу для каждой строки в цикле, мы можем использовать предопределенную переменную ВыборкаДанных. В обработчике ПВД ПередОбработкой мы инициализируем эту переменную (например, присваиваем ей таблицу значений или результат запроса):
// Обработчик ПВД "ПередОбработкой"
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Документ.РеестрПлатежей ГДЕ Проведен";
ВыборкаДанных = Запрос.Выполнить().Выгрузить(); // Передаем таблицу значений
В этом случае платформа сама начнет обходить строки таблицы ВыборкаДанных. Для каждой строки будет вызываться обработчик ПВД ПередВыгрузкой. В этом обработчике нам будет доступна переменная Объект (текущая строка таблицы). Если мы хотим передать параметры в ПКО при таком подходе, нам нужно использовать предопределенную переменную ИсходящиеДанные:
// Обработчик ПВД "ПередВыгрузкой"
ИсходящиеДанные = Новый Структура;
ИсходящиеДанные.Вставить("ОрганизацияПриемник", Объект.Организация);
Платформа автоматически перенесет структуру из переменной ИсходящиеДанные обработчика ПВД ПередВыгрузкой во ВходящиеДанные вызываемого ПКО. Этот способ изящнее, но требует четкого понимания того, как платформа связывает обработчики.
Даже если мы идеально настроили ПВД и передали структуру параметров третьим аргументом в ВыгрузитьПоПравилу, на стороне ПКО эти данные могут быть проигнорированы. Разберем, как правильно принять и обработать эти параметры внутри ПКО.
Когда параметры передаются в ПКО, они становятся доступны в виде структуры ВходящиеДанные во всех обработчиках этого ПКО (например, в ПередВыгрузкой, ПриВыгрузке ПКО, а также в ПКС этого ПКО).
Существует два способа работы с ними на стороне ПКО:
Если нам нужно заполнить реквизиты объекта-приемника переданными параметрами, мы настраиваем Правила конвертации свойств (ПКС) следующим образом:
ВходящиеДанные должно строго (символ в символ) совпадать с именем свойства-приемника (или именем свойства-источника в зависимости от версии КД, но надежнее всего называть ключ структуры точно так же, как свойство-приемник).Если эти условия выполнены, КД 2 при конвертации объекта автоматически возьмет значение из структуры ВходящиеДанные по соответствующему ключу и запишет его в реквизит приемника.
Если имя ключа структуры не совпадает с приемником, или нам требуется дополнительная обработка данных перед заполнением, мы можем написать код в обработчике ПКС ПередВыгрузкой:
// Обработчик ПКС "ПередВыгрузкой"
Если ВходящиеДанные <> Неопределено И ВходящиеДанные.Свойство("ОрганизацияПриемник") Тогда
Значение = ВходящиеДанные.ОрганизацияПриемник;
Иначе
ВыразитьОтказ() // или заполнить дефолтным значением
КонецЕсли;
Часто программисты удивляются: "Почему в ПКО в обработчике ПередВыгрузкой параметр Источник заполнен ссылкой, хотя в ПВД выбран Произвольный алгоритм?"
Давайте проясним этот момент. Способ выборки в ПВД ("Стандартная выборка" или "Произвольный алгоритм") определяет исключительно то, как мы получаем данные из базы данных для последующей отправки. ПКО же определяет то, как конкретный объект конвертируется.
Если мы вызвали ВыгрузитьПоПравилу(СсылкаНаОбъект, , Параметры, , "ИмяПКО"), то первым параметром мы передали ссылку на реальный объект информационной базы. Платформа передает эту ссылку в ПКО, и переменная Источник инициализируется этой ссылкой. Это штатное поведение системы.
Если мы хотим, чтобы ПКО работало исключительно "из головы" (только на основании переданной структуры без привязки к конкретному объекту-источнику), нам необходимо:
Неопределено:
ВыгрузитьПоПравилу(, , ПараметрыПередачи, , "ПКО_Без_Источника");
Поскольку код обработчиков ПВД и ПКО хранится в XML-файле правил и выполняется платформой динамически через функцию Выполнить(), стандартная установка точек останова в Конфигураторе не сработает напрямую. Попытки отладить код "в лоб" часто приводят к тому, что отладчик просто игнорирует строки кода в обработчиках.
Проанализируем по шагам, как настроить полноценную интерактивную отладку в КД 2.1 с помощью выгрузки обработчиков во внешнюю обработку:
D:\Debug\г_ОбработчикиВыгрузки.epf), и нажмем кнопку "Сформировать файл обработчиков".Файл -> Открыть найдем и откроем созданный файл внешней обработки г_ОбработчикиВыгрузки.epf.ПВД_ПередОбработкой_ПравилоВыгрузки_РеестрПлатежей.Платформа при начале выгрузки вместо динамического выполнения кода из XML обратится к модулю нашей внешней обработки, благодаря чему управление передастся в Конфигуратор, и выполнение кода остановится ровно на нашей точке останова. Теперь мы можем выполнять пошаговую отладку (F10, F11), вычислять выражения на табло и анализировать состояние переменных, включая ВходящиеДанные и ВыборкаДанных.
Мы детально изучили процесс передачи параметров из ПВД в ПКО. Для успешного обмена данными важно помнить три ключевых правила:
ПередОбработкой ПВД и не забывайте устанавливать Отказ = Истина; в конце алгоритма, либо используйте механизм ВыборкаДанных.ВыгрузитьПоПравилу, передавая структуру параметров именно третьим аргументом и обязательно указывая имя ПКО пятым аргументом.Используя эти правила и настроив интерактивную отладку, мы сможем быстро и без ошибок реализовывать обмены любой сложности в Конвертации данных 2.1.