Почему не срабатывает ОбменДанными.Загрузка при записи документов через COM-соединение в 1С

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

При организации переноса данных между базами 1С (например, из 1С:Бухгалтерия предприятия 3.0 в нетиповую 1С:Управление торговлей 10.3) разработчики часто используют прямое программное подключение через COM-соединение. Для отключения лишних проверок и логики проведения принято устанавливать свойство ОбменДанными.Загрузка = Истина. Однако нередко при записи объекта платформа все равно генерирует критическую ошибку. Разберем подробно, почему это происходит и как решить данную проблему без изменения конфигурации базы-приемника.

Анализ механизма работы ОбменДанными.Загрузка

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

  1. События модулей и подписки на события продолжают выполняться: При установке режима загрузки обработчики ПередЗаписью, ПриЗаписи и зарегистрированные в метаданных подписки на события (Event Subscriptions) не отключаются автоматически платформой.
  2. Зависимость от разработчика: Чтобы код проверки или заполнения был пропущен, внутри обработчика должно быть явное условие вида:
    
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    Если в модуле подписки на событие или общем модуле такой проверки нет, то код продолжает выполняться в штатном режиме.

Причина ошибки: контекст внешнего соединения и директивы препроцессора

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

  1. Код, обрамленный директивами препроцессора #Если Клиент Тогда ... #КонецЕсли, физически не компилируется в режиме внешнего соединения и отсутствует в памяти процесса.
  2. Если в процессе записи документа (например, через подписку на событие проверки прав доступа или валидации периода) вызывается метод из общего модуля, закрытый такой директивой, платформа выбрасывает исключение: Процедура или функция с указанным именем не определена.

Посмотрим на пример проблемного участка в базе-приемнике:


#Если Клиент Тогда
Функция ОбъектИсключенИзПроверкиПравДоступаПоПериоду(Объект) Экспорт
    ИсключенияИзПроверки = Новый Массив;
    ИсключенияИзПроверки.Добавить(Тип("ДокументОбъект.АктСверкиВзаиморасчетов"));
    Если ИсключенияИзПроверки.Найти(ТипЗНЧ(Объект)) = Неопределено Тогда
        Возврат Ложь;
    Иначе
        Возврат Истина;
    КонецЕсли;
КонецФункции
#КонецЕсли

При вызове этой функции из подписки на событие в контексте COMConnector происходит падение, даже если свойство ОбменДанными.Загрузка установлено в Истина.

Варианты решения проблемы без изменения конфигурации

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

Способ 1. Использование Automation-сервера V83.Application вместо COMConnector

Выясним разницу между компонентами подключения. Объект V83.COMConnector инициализирует легковесное внешнее соединение, где недоступен клиентский контекст. В то же время V83.Application запускает полноценный клиентский сеанс, где директивы #Если Клиент Тогда успешно отрабатывают.

Рассмотрим пример кода подключения и записи объекта:


// Инициализируем Automation-сервер вместо COMConnector
СоединениеБД = Новый COMОбъект("V83.Application");
СтрокаПодключения = "Srvr=""Сервер1С"";Ref=""БазаПриемник"";Usr=""Пользователь"";Pwd=""Пароль"";";
СоединениеБД.Connect(СтрокаПодключения);

ПлПрВ = СоединениеБД.Документы.ПлатежноеПоручениеВходящее;

// Создание и запись документа
ППВ = ПлПрВ.СоздатьДокумент();
ППВ.Дата = ТекущаяДата();
ППВ.Номер = "000000001";
ППВ.ОбменДанными.Загрузка = Истина;
ППВ.Записать();

Способ 2. Выполнение логики через внешнюю обработку в базе-приемнике

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

  1. Создаем внешнюю обработку (.epf), в экспортном методе которой реализуем создание документа, ручное управление движениями и заполнение реквизитов.
  2. Через COM-соединение открываем обработку с помощью метода СоединениеБД.ВнешниеОбработки.Создать("ПутьКФайлу.epf").
  3. Передаем структуру или таблицу данных и выполняем запись документа внутри изолированного контекста обработки.

Способ 3. Переход на обмен данными через файлы XML

Рассмотрим вариант с полным отказом от прямой COM-записи в пользу штатных механизмов:

  1. Формируем выгрузку данных из базы-источника в файл XML с использованием правил конвертации («1С:Конвертация данных 2.0/3.0») или универсальной выгрузки.
  2. Выполняем загрузку файла в базе-приемнике регламентным заданием либо обработкой «Универсальный обмен данными в формате XML», запущенной в интерактивном клиентском сеансе. В этом случае все клиентские проверки выполняются корректно, а ОбменДанными.Загрузка = Истина отрабатывает без сбоев препроцессора.
← На главную