Почему возникает ошибка «Тип не определен (ДиалогВыбораФайла)» при проведении документа в регламентном задании?

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

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

Проанализируем типовую ситуацию: в фоновом задании программно создается и проводится документ (например, ПоступлениеТоваровУслуг). В процессе проведения платформа 1С аварийно завершает работу со следующей диагностикой:

Ошибка инициализации модуля: ОбщийМодуль.РаботаСТорговымОборудованием.Модуль по причине: {ОбщийМодуль.РаботаСТорговымОборудованием.Модуль(900,18)}: Тип не определен (ДиалогВыбораФайла)

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

Механизм компиляции общих модулей на сервере

Платформа 1С:Предприятие выполняет компиляцию программного модуля целиком при первом обращении к любому его экспортируемому методу или переменной из текущего контекста. Процесс компиляции переводит исходный текст модуля в промежуточный байт-код.

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

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

Способ 1. Вынос серверной логики в отдельный общий модуль

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

  1. Создадим новый неглобальный общий модуль, например, РаботаСТорговымОборудованиемСервер или ШтрихкодированиеСервер.
  2. В свойствах нового модуля установим флаг Сервер и снимем флаги клиентских контекстов.
  3. Перенесем в него алгоритмы, не требующие экранных форм и оконных вызовов (расчет контрольных символов, генерация штрихкодов, запись в регистры).
  4. В типовом модуле РаботаСТорговымОборудованием снимем ошибочно установленный флаг Сервер, вернув его в исходное клиентское состояние.

Способ 2. Использование инструкций препроцессора

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

Посмотрим на пример оборачивания клиентского кода:


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

Для конфигураций на обычных формах (например, УПП 1.3 или КА 1.1) также используется проверка режима толстого клиента:


#Если ТолстыйКлиентОбычноеПриложение Тогда
    // Код работы с интерактивными диалогами и оборудованием на клиенте
#КонецЕсли

Способ 3. Отключение обработки торгового оборудования при программной записи

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

Разберем по шагам, как передать признак программного проведения:


// В процедуре регламентного задания при формировании документа
ДокументОбъект = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();
// Заполняем реквизиты документа...
ДокументОбъект.ДополнительныеСвойства.Вставить("ОтказОтОбработкиШтрихкодов", Истина);
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);

В модуле объекта проверяем наличие флага перед обращением к модулям оборудования:


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

Профилактика контекстных ошибок

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

  1. Откроем Конфигуратор и перейдем в главное меню: Конфигурация -> Проверка конфигурации.
  2. В списке проверок включим флаги Сервер, Внешнее соединение и Клиент (управляемое приложение).
  3. Запустим синтаксический контроль. Платформа проверит все процедуры и модули на доступность типов в заданных режимах и выведет список строк, где используются недопустимые типы вроде ДиалогВыбораФайла.
← На главную