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