При настройке обмена данными между конфигурациями (например, при перегрузке из Управление торговлей 10.3 в Бухгалтерию предприятия 3.0) разработчики часто сталкиваются с ситуацией, когда типовые или доработанные механизмы выгрузки внезапно прерываются. Ошибка обычно указывает на модуль объекта документа и сообщает о неопределенных переменных, таких как РежимДиалогаВопрос, КодВозвратаДиалога или об отсутствии функции Вопрос.
В этой статье мы разберем, почему код, который отлично работает при ручном вводе документов, «ломается» во время автоматизированного обмена, и как правильно адаптировать модули 1С, чтобы избежать подобных проблем.
Проблема кроется в разграничении контекстов исполнения кода в платформе 1С:Предприятие. Существует контекст Клиента (где отрисовывается интерфейс и доступны окна сообщений) и контекст Сервера (где выполняется работа с базой данных и программный код без интерфейса). Также существует выполнение кода в режиме внешнего соединения или фоновых заданий.
Когда мы работаем с документом РеализацияТоваровУслуг интерактивно, платформа понимает, что открыта форма и пользователь может нажать на кнопку. Но когда работает обработка «Универсальный обмен данными в формате XML» (используемая в Конвертации данных 2.0), она обращается к объекту программно. В процессе выгрузки могут вызываться процедуры модуля объекта, такие как ПередЗаписью или другие экспортные функции, в которых разработчики ранее добавили «вопросы» пользователю.
Выясним причину: так как при выгрузке данных графический интерфейс для этого потока исполнения недоступен (или код выполняется в контексте, не поддерживающем интерактивность), глобальные функции типа Вопрос() и системные перечисления типа РежимДиалогаВопрос просто не существуют для системы. Это приводит к ошибке компиляции модуля.
Самый быстрый и надежный способ устранить ошибку, не переписывая всю логику системы — это использование инструкций препроцессора. Мы должны явно указать платформе, что данный кусок кода следует компилировать и исполнять только в том случае, если приложение запущено в интерактивном режиме (на клиенте).
Проанализируем пример исправления кода в модуле объекта:
// Было (вызывало ошибку при выгрузке)
Ответ = Вопрос("По данной реализации выписан Счет-фактура. Он будет удален, продолжить?", РежимДиалогаВопрос.ДаНет, 0);
Если Ответ = КодВозвратаДиалога.Да Тогда
// Логика удаления
КонецЕсли;
// Стало (безопасно для обмена)
#Если Клиент Тогда
Ответ = Вопрос("По данной реализации выписан Счет-фактура. Он будет удален, продолжить?", РежимДиалогаВопрос.ДаНет, 0);
Если Ответ = КодВозвратаДиалога.Да Тогда
// Логика удаления
КонецЕсли;
#КонецЕсли
Важно понимать, почему обычная конструкция Попытка ... Исключение здесь не поможет. Ошибка «Переменная не определена» является ошибкой компиляции. Платформа пытается подготовить модуль к выполнению и «спотыкается» на неизвестном слове еще до того, как начнет работать блок Попытка. Инструкция #Если Клиент же просто исключает этот текст из кода, если условия не соблюдены, поэтому система даже не пытается искать переменную РежимДиалогаВопрос.
Хотя в теме обсуждалась выгрузка, хорошим тоном при написании кода в модулях объектов является проверка свойства ОбменДанными.Загрузка. Это встроенный механизм 1С, который позволяет понять, что объект сейчас создается или изменяется в рамках автоматизированного процесса обмена.
Рассмотрим, как это применить вместе с проверкой контекста:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Если идет обмен данными, выходим из процедуры или пропускаем проверки
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
#Если Клиент Тогда
// Здесь размещаем интерактивные проверки
Если ЭтоНовый() Тогда
// ... логика с Вопросом
КонецЕсли;
#КонецЕсли
КонецПроцедуры
Размещение функций Вопрос, Предупреждение или ОткрытьФорму непосредственно в модуле объекта (особенно в типовых событиях ПередЗаписью, ПриЗаписи) считается грубой ошибкой проектирования. Модуль объекта должен содержать только логику работы с данными, которая должна выполняться всегда, независимо от того, записывает документ человек или регламентное задание.
Разберем по шагам, как сделать правильно:
ПередЗаписьюНаСервере или в обработчиках команд).Частый вопрос при работе с Конвертацией данных 2.0: нужно ли заново выгружать описание метаданных через обработку MD82exp.epf, если вы изменили код в модуле объекта?
Ответ: Нет, не нужно, если вы не добавляли новые реквизиты, табличные части или новые объекты метаданных. Обмен в КД2 опирается на структуру данных (поля, типы). Изменение внутренней логики существующих процедур (добавление #Если Клиент) подхватится автоматически при выполнении обмена, так как база-источник просто начнет выполнять измененный код модуля.
Мы проанализировали ситуацию и выяснили, что ошибки при выгрузке из 1С:УТ 10.3 часто связаны с «наследием» старого стиля разработки, когда интерактивные функции вставлялись в ядро объекта. Для исправления ситуации достаточно обернуть такие вызовы в директивы препроцессора #Если Клиент Тогда, а в будущем — придерживаться правила разделения интерфейсной логики и логики данных.