Почему Конструктор запросов выдает ошибку «Переменная не определена» при обращении к документу из расширения?

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

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

Причина возникновения проблемы

Проанализируем контекст исполнения кода в платформе 1С:Предприятие:

  1. Контекст компиляции модуля менеджера: Модуль менеджера ссылочного объекта (документа, справочника) компилируется платформой не только на стороне сервера, но и в контексте клиента (включая толстый клиент и внутренние интерактивные механизмы платформы).
  2. Механизм работы Конструктора запросов: При открытии консоли запросов и разворачивании дерева таблиц метаданных платформа обращается к структуре объекта, что инициирует фоновую компиляцию и инициализацию модуля менеджера.
  3. Видимость общего модуля: Серверный общий модуль (например, ПроведениеСерверУТ) имеет признак доступности только «Сервер» (или «Внешнее соединение») и недоступен на клиенте. Если в модуле менеджера метод такого модуля вызывается напрямую без инструкций препроцессора, при клиентской компиляции возникает ошибка Переменная не определена.

Способ 1. Использование директив препроцессора (Рекомендуемый)

Согласно стандартам разработки 1С, любой код модуля менеджера, обращающийся к чисто серверным контекстам и модулям, должен быть явно ограничен инструкциями препроцессора. Это предотвратит компиляцию вызова в клиентском окружении Конструктора запросов и избавит от необходимости дублировать модули в расширение.

Обернем процедуру расширения в условие препроцессора:


#Если Сервер ИЛИ ТолстыйКлиентОбычноеПриложение ИЛИ ВнешнееСоединение Тогда
&Вместо("ОбработкаПроведения")
Процедура Расш1_ОбработкаПроведенияВместо(Отказ, РежимПроведения)
    // Вызов серверного модуля основной конфигурации
    ПроведениеСерверУТ.ТиповаяФункция();
КонецПроцедуры
#КонецЕсли

Если достаточно ограничить код только серверным выполнением, применим сокращенный вариант директивы:


#Если Сервер Тогда
&Вместо("ОбработкаПроведения")
Процедура Расш1_ОбработкаПроведенияВместо(Отказ, РежимПроведения)
    ПроведениеСерверУТ.ТиповаяФункция();
КонецПроцедуры
#КонецЕсли

Способ 2. Заимствование общего модуля в расширение

Если логика расширения требует явной видимости объекта метаданных, добавим общий модуль в состав расширения. Для этого в дереве метаданных основной конфигурации нажмем правой кнопкой мыши на общий модуль ПроведениеСерверУТ и выберем команду «Добавить в расширение».

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

Способ 3. Динамический вызов через функции БСП

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


&Вместо("ОбработкаПроведения")
Процедура Расш1_ОбработкаПроведенияВместо(Отказ, РежимПроведения)
    МодульПроведения = ОбщегоНазначения.ОбщийМодуль("ПроведениеСерверУТ");
    МодульПроведения.ТиповаяФункция();
КонецПроцедуры

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

Диагностика и проверка

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

  1. В главном меню Конфигуратора перейдем в раздел Конфигурация → Проверка конфигурации.
  2. Установим флаги для проверки во всех режимах: Тонкий клиент, Сервер, Толстый клиент (управляемое приложение), Толстый клиент (обычное приложение) и Внешнее соединение.
  3. Нажмем «Выполнить» и устраним модули с неопределенными переменными с помощью директив препроцессора #Если Сервер Тогда.
← На главную