При разработке правил конвертации данных (КД 2.x) нередко требуется вести собственный протокол выгрузки данных в текстовый файл. Для этого в правила добавляют глобальные параметры и обращаются к ним из правил выгрузки данных (ПВД) или алгоритмов. Однако разработчики часто сталкиваются с ситуацией: при интерактивном запуске через обработку Универсальный обмен данными в формате XML выгрузка и запись лога отрабатывают корректно, а при программном запуске той же самой обработки возникает ошибка.
Разберем типичное проявление этой ошибки, проанализируем внутренние механизмы обработки обмена и рассмотрим правильные варианты передачи параметров.
Рассмотрим типовую схему: в правилах конвертации определен глобальный параметр ИмяФайлаРегистрацииИзменений, куда помещается путь к файлу лога. В обработчике ПВД подготавливаются данные и вызывается алгоритм:
ИмяФайла = Параметры.ИмяФайлаРегистрацииИзменений;
Дописывать = Истина;
ТекстСтроки = "Выгрузка объектов завершена";
Выполнить(Алгоритмы.ЗаписьТекста);
В алгоритме ЗаписьТекста выполняется создание объекта файловой системы:
Текст = Новый ЗаписьТекста;
Текст.Открыть(ИмяФайла, КодировкаТекста.ANSI, , Дописывать);
Текст.ЗаписатьСтроку(ТекстСтроки);
Текст.Закрыть();
При программном вызове выгрузки код инициализации выглядит следующим образом:
ОбменXML = Обработки.УниверсальныйОбменДаннымиXML.Создать();
ОбменXML.ИмяФайлаПравилОбмена = ИмяФайлаПравил;
ОбменXML.ИмяФайлаОбмена = ИмяФайлаОбмена;
ОбменXML.ЗагрузитьПравилаОбмена(ОбменXML.ИмяФайлаПравилОбмена);
ОбменXML.РежимОбмена = "Выгрузка";
ОбменXML.ПараметрыИнициализированы = Истина;
ОбменXML.ВыполнитьВыгрузку();
Во время исполнения кода платформа выдает исключение:
Ошибка при вызове метода контекста (Открыть): Недопустимое значение параметра (параметр номер '1')
Если проанализировать значение переменной Параметры.ИмяФайлаРегистрацииИзменений непосредственно перед вызовом алгоритма, выясняется, что значение параметра оказывается пустым или равным значению по умолчанию, хотя при инициализации обработки оно заполнялось.
Чтобы понять, куда исчезает значение, проанализируем внутреннее устройство типовой обработки УниверсальныйОбменДаннымиXML:
ЗагрузитьПравилаОбмена() считывает правила и выполняет встроенный обработчик событий «После загрузки правил обмена». Однако сразу после выполнения этого события процедура обработки вызывает внутреннюю инициализацию параметров по умолчанию — ИнициализироватьПервоначальныеЗначенияПараметров(). Вся структура Параметры перечитывается заново, а любые значения, заданные вручную в событии «После загрузки правил обмена» или до него, затираются.ТаблицаНастройкиПараметров (используется для отображения параметров в диалоге формы) и в контекстной структуре Параметры (передается внутрь алгоритмов). Если заполнить только коллекцию ОбменXML.Параметры без синхронизации с таблицей настроек, при старте метода ВыполнитьВыгрузку() обработка может заново инициализировать структуру из пустых строк таблицы.Самое простое и надежное решение внутри правил обмена — перенести расчет и заполнение глобальных переменных из обработчика «После загрузки правил обмена» в обработчик «Перед выгрузкой данных».
Событие «Перед выгрузкой данных» вызывается внутри метода ВыполнитьВыгрузку() непосредственно перед стартом обработки первого ПВД. В этот момент все структуры параметров уже окончательно сформированы обработкой, и повторной инициализации по умолчанию не происходит.
Посмотрим на пример кода в обработчике правил «Перед выгрузкой данных»:
ТекущаяДатаСтрокой = Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss");
Параметры.ИмяФайлаРегистрацииИзменений = "D:\Exchange_1C\Logs\Uploads_" + ТекущаяДатаСтрокой + ".txt";
После такого переноса параметр гарантированно сохранит свое значение на протяжении всей выгрузки во всех ПВД и пользовательских алгоритмах.
Если значение параметра вычисляется не внутри правил, а передается из внешнего модуля перед запуском обработки, необходимо соблюдать строгую последовательность работы с коллекциями обработки:
ЗагрузитьПравилаОбмена(), чтобы в обработке заполнилась коллекция ТаблицаНастройкиПараметров.ТаблицаНастройкиПараметров и устанавливаем значение.УстановитьПараметрыИзДиалога() для переноса значений в контекстную структуру.Разберем программный код для правильной передачи параметров снаружи:
ОбменXML = Обработки.УниверсальныйОбменДаннымиXML.Создать();
ОбменXML.ИмяФайлаПравилОбмена = ИмяФайлаПравил;
ОбменXML.ИмяФайлаОбмена = ИмяФайлаОбмена;
ОбменXML.ЗагрузитьПравилаОбмена();
// Находим параметр в табличной части обработки
СтрокаПараметра = ОбменXML.ТаблицаНастройкиПараметров.Найти("ИмяФайлаРегистрацииИзменений", "Имя");
Если СтрокаПараметра <> Неопределено Тогда
СтрокаПараметра.Значение = "D:\Exchange_1C\Logs\Upload.txt";
КонецЕсли;
// Синхронизируем таблицу параметров со структурой контекста правил
ОбменXML.УстановитьПараметрыИзДиалога();
ОбменXML.ПараметрыИнициализированы = Истина;
ОбменXML.ВыполнитьВыгрузку();
Если имя файла передается корректно, но метод Текст.Открыть(...) по-прежнему падает с ошибкой недопустимого значения параметра, необходимо проверить контекст исполнения кода:
rphost), а не на клиентской машине или рабочем месте администратора.USR1CV8), должен иметь полные права NTFS на чтение и запись в указанную директорию. Если прав нет или каталог не существует, метод Открыть() вернет системную ошибку доступа.Для логирования процесса обмена не обязательно открывать и закрывать текстовый файл вручную в каждом ПВД. В платформе и типовой обработке есть более стабильные механизмы:
ЗаписьЖурналаРегистрации() работает независимо от файловых путей и блокировок диска:
ЗаписьЖурналаРегистрации("Обмен данными.Выгрузка", УровеньЖурналаРегистрации.Информация, , , ТекстСтроки);
ОбменXML.ЗаписыватьВПротоколСообщений = Истина;
ОбменXML.ИмяФайлаПротоколаОбмена = "D:\Exchange_1C\Logs\Protocol.txt";