Почему очищаются параметры обмена при программном запуске выгрузки XML в 1С?

Программист IT и автоматизация бизнеса
← На главную

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

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

Симптомы проблемы и код вызова

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


ИмяФайла = Параметры.ИмяФайлаРегистрацииИзменений;
Дописывать = Истина;
ТекстСтроки = "Выгрузка объектов завершена";
Выполнить(Алгоритмы.ЗаписьТекста);

В алгоритме ЗаписьТекста выполняется создание объекта файловой системы:


Текст = Новый ЗаписьТекста;
Текст.Открыть(ИмяФайла, КодировкаТекста.ANSI, , Дописывать);
Текст.ЗаписатьСтроку(ТекстСтроки);
Текст.Закрыть();

При программном вызове выгрузки код инициализации выглядит следующим образом:


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

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

Во время исполнения кода платформа выдает исключение:

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

Если проанализировать значение переменной Параметры.ИмяФайлаРегистрацииИзменений непосредственно перед вызовом алгоритма, выясняется, что значение параметра оказывается пустым или равным значению по умолчанию, хотя при инициализации обработки оно заполнялось.

Выясняем причину: механизм сброса параметров обработкой

Чтобы понять, куда исчезает значение, проанализируем внутреннее устройство типовой обработки УниверсальныйОбменДаннымиXML:

  1. Перезапись значений при загрузке правил. Метод ЗагрузитьПравилаОбмена() считывает правила и выполняет встроенный обработчик событий «После загрузки правил обмена». Однако сразу после выполнения этого события процедура обработки вызывает внутреннюю инициализацию параметров по умолчанию — ИнициализироватьПервоначальныеЗначенияПараметров(). Вся структура Параметры перечитывается заново, а любые значения, заданные вручную в событии «После загрузки правил обмена» или до него, затираются.
  2. Двойная модель хранения параметров. В обработке параметры присутствуют в двух видах: в реквизите ТаблицаНастройкиПараметров (используется для отображения параметров в диалоге формы) и в контекстной структуре Параметры (передается внутрь алгоритмов). Если заполнить только коллекцию ОбменXML.Параметры без синхронизации с таблицей настроек, при старте метода ВыполнитьВыгрузку() обработка может заново инициализировать структуру из пустых строк таблицы.

Способ 1. Перенос инициализации в событие «Перед выгрузкой данных» (Рекомендуемый)

Самое простое и надежное решение внутри правил обмена — перенести расчет и заполнение глобальных переменных из обработчика «После загрузки правил обмена» в обработчик «Перед выгрузкой данных».

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

Посмотрим на пример кода в обработчике правил «Перед выгрузкой данных»:


ТекущаяДатаСтрокой = Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss");
Параметры.ИмяФайлаРегистрацииИзменений = "D:\Exchange_1C\Logs\Uploads_" + ТекущаяДатаСтрокой + ".txt";

После такого переноса параметр гарантированно сохранит свое значение на протяжении всей выгрузки во всех ПВД и пользовательских алгоритмах.

Способ 2. Корректное заполнение параметров из внешнего кода

Если значение параметра вычисляется не внутри правил, а передается из внешнего модуля перед запуском обработки, необходимо соблюдать строгую последовательность работы с коллекциями обработки:

  1. Вызываем метод ЗагрузитьПравилаОбмена(), чтобы в обработке заполнилась коллекция ТаблицаНастройкиПараметров.
  2. Находим нужную строку в ТаблицаНастройкиПараметров и устанавливаем значение.
  3. Вызываем штатный метод УстановитьПараметрыИзДиалога() для переноса значений в контекстную структуру.
  4. Устанавливаем признак инициализации и выполняем выгрузку.

Разберем программный код для правильной передачи параметров снаружи:


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

// Находим параметр в табличной части обработки
СтрокаПараметра = ОбменXML.ТаблицаНастройкиПараметров.Найти("ИмяФайлаРегистрацииИзменений", "Имя");
Если СтрокаПараметра <> Неопределено Тогда
    СтрокаПараметра.Значение = "D:\Exchange_1C\Logs\Upload.txt";
КонецЕсли;

// Синхронизируем таблицу параметров со структурой контекста правил
ОбменXML.УстановитьПараметрыИзДиалога();
ОбменXML.ПараметрыИнициализированы = Истина;

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

Особенности клиент-серверного контекста и прав доступа

Если имя файла передается корректно, но метод Текст.Открыть(...) по-прежнему падает с ошибкой недопустимого значения параметра, необходимо проверить контекст исполнения кода:

  1. Серверная файловая система. При выполнении выгрузки на стороне сервера (или в регламентном задании) путь к файлу ищется на том сервере, где запущен рабочий процесс службы 1С (например, rphost), а не на клиентской машине или рабочем месте администратора.
  2. Права учетной записи службы. Пользователь операционной системы, от имени которого работает сервер 1С (например, USR1CV8), должен иметь полные права NTFS на чтение и запись в указанную директорию. Если прав нет или каталог не существует, метод Открыть() вернет системную ошибку доступа.

Штатные альтернативы прямому выводу в файл

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

  1. Запись в журнал регистрации. Вызов процедуры ЗаписьЖурналаРегистрации() работает независимо от файловых путей и блокировок диска:
    
    ЗаписьЖурналаРегистрации("Обмен данными.Выгрузка", УровеньЖурналаРегистрации.Информация, , , ТекстСтроки);
    
  2. Штатный протокол сообщений обработки. Обработка умеет самостоятельно протоколировать весь ход работы. Достаточно включить соответствующие свойства перед стартом:
    
    ОбменXML.ЗаписыватьВПротоколСообщений = Истина;
    ОбменXML.ИмяФайлаПротоколаОбмена = "D:\Exchange_1C\Logs\Protocol.txt";
    
← На главную