Как программно настроить отбор в обработке «Универсальный обмен данными XML»?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При организации интеграции между различными базами данных на платформе 1С предприятие часто используется стандартная обработка «Универсальный обмен данными XML» (работающая на технологии «Конвертация данных 2.0»). В интерактивном режиме пользователи могут легко зайти в настройки, выбрать нужное правило выгрузки данных (ПВД), включить его и настроить произвольный отбор (например, указать список конкретных документов или элементов справочника для выгрузки). Для автоматизации этого процесса по расписанию и исключения ручных действий можно использовать программу регулярного автоматического обмена данными между базами 1С.

Однако при автоматизации бизнес-процессов возникает необходимость делать это полностью программно: например, запустить регламентное задание, которое выберет измененные объекты по сложному алгоритму, программно заполнит отборы в обработке обмена и выполнит выгрузку в файл. В этой статье мы подробно разберем, как реализовать этот механизм, разберем частые ошибки при работе с ПостроителемОтчета, а также рассмотрим продвинутые сценарии работы с регистрами и иерархией правил.

Почему возникает ошибка «Недопустимое значение параметра» при добавлении отбора?

Прежде чем перейти к готовому коду, давайте выясним причину популярной ошибки, с которой сталкиваются разработчики при попытке программно настроить отборы. Часто при попытке добавить новое поле в коллекцию отборов построителя система выбрасывает исключение:

Ошибка при вызове метода контекста (Добавить): Недопустимое значение параметра (параметр номер '1')

Давайте проанализируем, почему это происходит. Механизм отборов в обработке обмена построен на использовании стандартного объекта платформы ПостроительОтчета. Этот объект работает по строго определенным правилам:

  1. Построитель отчета анализирует текст запроса, переданный в его свойство Текст.
  2. Для того чтобы мы могли наложить отбор на какое-то поле, это поле должно быть объявлено в тексте запроса внутри специальных фигурных скобок — в секции {ГДЕ ...}.
  3. При добавлении элемента в коллекцию отборов с помощью метода Построитель.Отбор.Добавить("ИмяПоля"), передаваемое имя должно строго совпадать с псевдонимом (алиасом), который указан в секции {ГДЕ} после ключевого слова КАК.

Рассмотрим некорректный пример запроса и настройки отбора:


ПостроительОтчета.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
|  АвансовыйОтчет.Ссылка КАК Ссылка
|ИЗ
|  Документ.АвансовыйОтчет КАК АвансовыйОтчет
|{ГДЕ
|  АвансовыйОтчет.Ссылка.* КАК АвансовыйОтчет_Номер}";

// Попытка добавить отбор по реальному реквизиту:
ПостроительОтчета.Отбор.Добавить("Документ_АвансовыйОтчет.Номер"); // Ошибка!

В данном примере построитель отчета ожидает добавления поля с именем АвансовыйОтчет_Номер, так как именно этот алиас прописан в фигурных скобках в качестве имени доступного поля компоновки. Попытка передать туда строку вида "Документ_АвансовыйОтчет.Номер" или любую другую, не объявленную в секции {ГДЕ}, приведет к аварийному завершению работы программы.

Пошаговое руководство по программной установке отбора

Теперь, когда мы поняли теоретические основы взаимодействия с построителем, давайте разберем рабочий алгоритм настройки отбора для справочников или документов по шагам.

Шаг 1. Инициализация обработки и загрузка правил обмена. Сначала нам необходимо создать объект обработки обмена, указать пути к файлам правил и выгрузки данных, после чего инициализировать структуру правил:


Обработина = Обработки.УниверсальныйОбменДаннымиXML.Создать();
Обработина.РежимОбмена = "Выгрузка";
Обработина.ИмяФайлаПравилОбмена = "C:\Rules\ПравилаОбменаОС.xml";
Обработина.ИмяФайлаОбмена = "C:\Exchange\ВыгрузкаОС.xml";
Обработина.ЗагрузитьПравилаОбмена();

Шаг 2. Подготовка данных для отбора. Сформируем список значений, содержащий ссылки на объекты, которые мы хотим выгрузить. Это могут быть ссылки, полученные из запроса или переданные из внешнего источника:


СписокОС = Новый СписокЗначений;
// Предположим, мы выбираем ОС по определенному условию
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.ОсновныеСредства ГДЕ ПометкаУдаления = ЛОЖЬ";
РезультатТаблица = Запрос.Выполнить().Выгрузить();

Для каждого СтрокаИзТаблицы Из РезультатТаблица Цикл
    СписокОС.Добавить(СтрокаИзТаблицы.Ссылка);
КонецЦикла;

Шаг 3. Поиск нужного правила в дереве выгрузки и настройка Построителя. Правила выгрузки данных хранятся в свойстве ТаблицаПравилВыгрузки. Нам нужно найти строку, соответствующую нашему объекту, составить для неё текст запроса, инициализировать отбор и передать настройки обратно в строку дерева правил:


Для каждого СтрокаП Из Обработина.ТаблицаПравилВыгрузки.Строки[0].Строки Цикл
    Если СтрокаП.Имя = "ОсновныеСредства" Тогда
        
        // Включаем данное правило для выгрузки
        СтрокаП.Включить = Истина;
        
        // Инициализируем построитель отчета
        Построитель = Новый ПостроительОтчета;
        
        // Динамически формируем текст запроса. 
        // ИмяОбъектаДляЗапроса содержит системное имя объекта, например, "Справочник.ОсновныеСредства"
        ИмяОбъектаМетаданных = СтрокаП.ИмяОбъектаДляЗапроса;
        ИмяАлиаса = СтрЗаменить(ИмяОбъектаМетаданных, ".", "_");
        
        Построитель.Текст = "ВЫБРАТЬ Разрешенные _.* ИЗ " + ИмяОбъектаМетаданных + " КАК _ 
                            |{ГДЕ _.Ссылка.* КАК " + ИмяАлиаса + "}";
        
        // Добавляем отбор в построитель
        Отбор = Построитель.Отбор;
        Отбор.Добавить(ИмяАлиаса);
        
        // Настраиваем параметры отбора
        Отбор[ИмяАлиаса].Использование = Истина;
        Отбор[ИмяАлиаса].ВидСравнения = ВидСравнения.ВСписке;
        Отбор[ИмяАлиаса].Значение = СписокОС;
        
        // Сохраняем настройки построителя обратно в структуру правила выгрузки
        СтрокаП.ИспользоватьОтбор = Истина;
        СтрокаП.НастройкиПостроителя = Построитель.ПолучитьНастройки();
        
    КонецЕсли;
КонецЦикла;

Шаг 4. Запуск выгрузки. После того как дерево правил настроено и отборы установлены, мы можем либо интерактивно открыть форму обработки, чтобы пользователь увидел предзаполненные отборы, либо сразу программно выполнить выгрузку:


// Вариант 1: Открыть форму для визуального контроля
Обработина.ПолучитьФорму("Форма").Открыть();

// Вариант 2: Выполнить автоматическую выгрузку без показа формы
Обработина.ВыполнитьВыгрузку();

Продвинутые сценарии и решение частых проблем

На практике при написании универсального кода вы можете столкнуться со специфическими ситуациями, которые не учтены в простейших примерах. Рассмотрим, как их правильно обрабатывать.

1. Особенности работы с регистрами

Если ваше правило выгрузки настроено не для справочника или документа, а для регистра (сведений или накопления), стандартное свойство ИмяОбъектаДляЗапроса окажется пустым. Для регистров имя таблицы хранится в колонке ИмяОбъектаДляЗапросаРегистра. Чтобы ваш код был универсальным, используйте следующую конструкцию при определении имени таблицы метаданных:


ИмяОбъектаМетаданных = ?(ЗначениеЗаполнено(СтрокаП.ИмяОбъектаДляЗапроса), 
                       СтрокаП.ИмяОбъектаДляЗапроса, 
                       СтрокаП.ИмяОбъектаДляЗапросаРегистра);

2. Активация родительских групп в дереве правил

В обработке обмена правила выгрузки сгруппированы в дерево (например, ветка «Документы», внутри которой лежат конкретные ПВД). Если вы программно установите флаг СтрокаП.Включить = Истина; для конкретного документа, но его родительский узел (группа «Документы») останется выключенным, то выгрузка этого документа не произойдет.

Чтобы избежать этой проблемы, необходимо рекурсивно обходить дерево правил вверх до самого корня и включать все родительские группы. Рассмотрим готовую процедуру:


Процедура ВключитьРодительскиеУзлы(СтрокаПравила)
    Родитель = СтрокаПравила.Родитель;
    Пока Родитель <> Неопределено Цикл
        Родитель.Включить = Истина;
        Родитель = Родитель.Родитель;
    КонецЦикла;
КонецПроцедуры

Просто вызывайте эту процедуру каждый раз при активации конкретного правила:


СтрокаП.Включить = Истина;
ВключитьРодительскиеУзлы(СтрокаП);

3. Безопасное редактирование таблицы правил выгрузки

При выполнении обмена в фоновых заданиях или высоконагруженных многопоточных процессах прямое изменение структуры Обработка.ТаблицаПравилВыгрузки может вызывать сбои или блокировки. Более надежной практикой считается предварительное копирование таблицы во временную переменную, выполнение всех манипуляций там, и последующий возврат структуры обратно:


ВременнаяТаблицаПравил = Обработина.ТаблицаПравилВыгрузки.Скопировать();

// ... Выполняем поиск нужных строк и установку настроек во ВременнаяТаблицаПравил ...

Обработина.ТаблицаПравилВыгрузки = ВременнаяТаблицаПравил.Скопировать();

4. Наложение сложных отборов по реквизитам

Что делать, если нам нужно наложить отбор не по ссылке на сам объект, а по его реквизитам? Например, выгрузить только документы «Авансовый отчет», принадлежащие определенной Организации. В этом случае мы должны модифицировать текст запроса построителя, указав нужный путь к реквизиту в секции {ГДЕ}:


Построитель = Новый ПостроительОтчета;
Построитель.Текст = "ВЫБРАТЬ Разрешенные _.* ИЗ Документ.АвансовыйОтчет КАК _ 
                    |{ГДЕ _.Организация.* КАК Документ_АвансовыйОтчет_Организация}";

Отбор = Построитель.Отбор;
Отбор.Добавить("Документ_АвансовыйОтчет_Организация");
Отбор["Документ_АвансовыйОтчет_Организация"].Использование = Истина;
Отбор["Документ_АвансовыйОтчет_Организация"].ВидСравнения = ВидСравнения.Равно;
Отбор["Документ_АвансовыйОтчет_Организация"].Значение = ВыбраннаяОрганизация;

СтрокаП.ИспользоватьОтбор = Истина;
СтрокаП.НастройкиПостроителя = Построитель.ПолучитьНастройки();

Альтернативный и элегантный способ: Использование параметров правил выгрузки

Хотя манипуляции с Построителем отчета полностью работоспособны, этот способ является довольно громоздким и сильно зависит от правильности написания строк запросов. Если у вас есть возможность вносить изменения в правила обмена через конфигурацию «Конвертация данных 2.0», задачу фильтрации данных можно решить изящнее и безопаснее с помощью параметров правил выгрузки. Когда требуется выполнить точечную миграцию без изменения правил в Конвертации данных, можно использовать обработку для переноса данных между похожими конфигурациями 1С с возможностью сопоставления объектов по произвольным полям.

Шаг 1. Настройка в Конвертации Данных. Откройте ваши правила обмена в КД 2.0 и создайте новый параметр на вкладке «Параметры» (например, СписокОСДляВыгрузки с типом СписокЗначений).

Шаг 2. Написание обработчика в КД. В правиле выгрузки данных (ПВД) для ваших объектов в обработчике «Перед выгрузкой» напишите следующий лаконичный код:


Если Параметры.Свойство("СписокОСДляВыгрузки") 
   И ЗначениеЗаполнено(Параметры.СписокОСДляВыгрузки) Тогда
    
    // Переопределяем стандартную выборку данных вашим подготовленным списком
    ВыборкаДанных = Параметры.СписокОСДляВыгрузки;
    
КонецЕсли;

Шаг 3. Передача параметров из внешнего кода 1С. Теперь на стороне вашей конфигурации при программном вызове обработки вам вообще не нужно работать с Построителем отчета. Код сокращается до нескольких понятных строк:


Обработина = Обработки.УниверсальныйОбменДаннымиXML.Создать();
Обработина.ИмяФайлаПравилОбмена = "C:\Rules\ПравилаОбменаОС.xml";
Обработина.ИмяФайлаОбмена = "C:\Exchange\ВыгрузкаОС.xml";
Обработина.ЗагрузитьПравилаОбмена();

// Просто передаем подготовленный список объектов напрямую в параметры обработки
Обработина.Параметры.Вставить("СписокОСДляВыгрузки", СписокОС);

// Активируем нужное ПВД
Для каждого СтрокаП Из Обработина.ТаблицаПравилВыгрузки.Строки[0].Строки Цикл
    Если СтрокаП.Имя = "ОсновныеСредства" Тогда
        СтрокаП.Включить = Истина;
        ВключитьРодительскиеУзлы(СтрокаП);
    КонецЕсли;
КонецЦикла;

// Выполняем выгрузку
Обработина.ВыполнитьВыгрузку();

Этот подход архитектурно более правильный, поскольку он полностью разделяет бизнес-логику фильтрации (которая теперь хранится внутри правил обмена) и код вызова обмена в самой информационной базе. Это делает систему более гибкой к изменениям метаданных и исключает ошибки, связанные с синтаксисом Построителя отчета. Чтобы убедиться в корректности переданных сведений после завершения обмена, можно запустить автоматическое сравнение проводок в базах 1С с помощью специализированного инструмента.

← На главную