Как исправить ошибку «Переменная не определена (Перечисления)» в общем модуле 1С?

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

При разработке в управляемом приложении на платформе «1С:Предприятие 8» программисты часто сталкиваются с ошибками компиляции в общих модулях. Одна из самых распространенных ошибок — «Переменная не определена (Перечисления)» или аналогичные ошибки для объектов Справочники, Документы и других менеджеров метаданных. Обычно эта проблема возникает при переносе кода из обычного приложения в управляемое или при создании обработчиков подписок на события.

В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем механизмы работы контекстов «клиент-сервер» и рассмотрим три способа решения проблемы — от быстрого обходного пути до методологически правильной настройки архитектуры конфигурации по стандартам фирмы «1С».

Выясняем причину: почему возникает ошибка компиляции?

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

Дело в том, что в управляемом приложении менеджеры метаданных, такие как Перечисления, Справочники и Документы, физически отсутствуют на клиенте (в тонком и веб-клиенте). Они доступны исключительно на стороне сервера или в толстом клиенте.

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

---

Решение 1. Правильная настройка свойств общего модуля (Рекомендуемый способ)

Создание универсальных общих модулей «для всего» — это грубая архитектурная ошибка. Для подписок на события и серверных обработчиков должен быть выделен отдельный неглобальный общий модуль.

Рассмотрим по шагам, как правильно настроить свойства общего модуля подписок на события в соответствии со стандартами разработки фирмы «1С»:

  1. Найдите ваш общий модуль в дереве метаданных конфигуратора и откройте его палитру свойств (клавиша F4).
  2. Установите флаг Сервер в значение Истина. Это обеспечит выполнение кода на стороне сервера.
  3. Установите флаг Внешнее соединение в значение Истина. Это необходимо для того, чтобы подписки на события корректно отрабатывали при обменах данными, работе через API, COM-соединения или в фоновых заданиях.
  4. Снимите флаг Клиент (управляемое приложение) (установите в Ложь). Это ключевой шаг: платформа перестанет компилировать этот модуль на стороне клиента, и ошибка компиляции исчезнет.
  5. Убедитесь, что флаг Вызов сервера снят (Ложь). Модулям подписок на события этот флаг не требуется.
  6. Убедитесь, что флаг Глобальный снят (Ложь).

После такой настройки компилятор клиента больше не будет обращаться к этому модулю. Вы сможете свободно использовать прямой доступ к перечислениям в вашем коде:


Если Источник.ВидОперации = Перечисления.ЛМБ_ВидыОпераций.Залог Тогда
    // Ваш серверный код обработки
КонецЕсли;

---

Решение 2. Использование функции ПредопределенноеЗначение()

Если по каким-то исключительным причинам общий модуль обязательно должен быть доступен на клиенте, вы можете использовать системную функцию ПредопределенноеЗначение(). Она предназначена для получения ссылок на предопределенные элементы (включая значения перечислений) в любом контексте — как на сервере, так и на клиенте.

Посмотрим на пример использования этой функции:


Если Источник.ВидОперации = ПредопределенноеЗначение("Перечисление.ЛМБ_ВидыОпераций.Залог") Тогда
    // Код, который будет успешно скомпилирован и на клиенте, и на сервере
КонецЕсли;

Важное предупреждение: Несмотря на то, что этот способ решает проблему с компиляцией, использовать его на сервере без крайней необходимости считается плохим тоном по следующим причинам:

---

Решение 3. Использование инструкций препроцессора

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

Проанализируем следующий пример:


#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
Если Источник.ВидОперации = Перечисления.ЛМБ_ВидыОпераций.Залог Тогда
    // Данный блок кода будет полностью проигнорирован клиентским компилятором
КонецЕсли;
#КонецЕсли

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

---

Дополнительная оптимизация: проверка типа источника в подписке

Разберем еще один важный нюанс производительности, который часто встречается в коде начинающих разработчиков. Проанализируем строку кода:

Если ТипЗнч(Источник) = Тип("ДокументОбъект.ЛМБ_ОперацияПоЗалогу") Тогда

Если ваша подписка на событие в дереве метаданных настроена индивидуально для одного конкретного документа ЛМБ_ОперацияПоЗалогу, то данная проверка в коде абсолютно избыточна. Она выполняется при каждом срабатывании события и зря тратит процессорное время.

Правильное решение:

  1. Откройте свойства вашей подписки на событие в конфигураторе.
  2. В поле Источник выберите конкретный тип объекта — ДокументОбъект.ЛМБ_ОперацияПоЗалогу (вместо общего типа ДокументОбъект).
  3. После этого удалите проверку типа ТипЗнч(Источник) из кода общего модуля. Платформа сама гарантирует, что данный метод будет вызван только при записи нужного документа.

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

← На главную