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

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

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

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

Выясняем причину: исторический контекст и поведение платформы

Для того чтобы понять суть проблемы, нам необходимо обратиться к истории развития встроенного языка «1С:Предприятие». Поведение ключевого слова ЭтотОбъект существенно менялось от версии к версии:

  1. В версиях платформы 8.2 и более ранних: ключевое слово ЭтотОбъект могло использоваться исключительно в модулях прикладных объектов (например, в модуле документа, справочника, отчета или обработки) и в модулях обычных форм. Оно указывало на конкретный экземпляр объекта базы данных (например, на конкретный документ ДокументОбъект.РеализацияТоваровУслуг), предоставляя доступ к его свойствам, реквизитам и методам. В общих модулях использование этого слова приводило к ошибке компиляции.
  2. Начиная с версии платформы 8.3.3: разработчики фирмы «1С» значительно расширили область применения этого свойства. Ключевое слово ЭтотОбъект стало доступно в модулях управляемых форм, модулях команд, а главное — в общих модулях. В контексте общего модуля данное ключевое слово возвращает ссылку на сам этот общий модуль (тип значения ОбщийМодуль). Это нововведение позволило разработчикам писать более универсальный и гибкий код, особенно при работе с асинхронными вызовами и описанием оповещений.

Давайте проанализируем ситуацию, описанную автором темы. При переносе процедуры из конфигурации УНФ 1.6 в новую базу данных, разработчик перенес следующий фрагмент кода:


Процедура НачатьВыполнениеКоманды_ВыбратьСменуЗавершение(СтруктураПараметровСмены, Параметры) Экспорт
    
    Если СтруктураПараметровСмены = Неопределено Тогда
        Если Параметры.ОповещениеПриЗавершении <> Неопределено Тогда
            ОписаниеОшибки = НСтр("ru='Кассовая смена не выбрана'");
            РезультатОперации = ПараметрыВыполненияОперацииНаОборудовании(Ложь, ОписаниеОшибки);
            ВыполнитьОбработкуОповещения(Параметры.ОповещениеПриЗавершении, РезультатОперации);
        КонецЕсли;
    Иначе
        Параметры.Вставить("КассоваяСмена", СтруктураПараметровСмены.КассоваяСмена);
        Параметры.Вставить("ИдентификаторУстройства", СтруктураПараметровСмены.ИдентификаторУстройства);
        ОписаниеОповещения = Новый ОписаниеОповещения("НачатьВыполнениеКоманды_ПодключениеЗавершение", ЭтотОбъект, Параметры);
        НачатьПодключениеОборудованиеПоИдентификатору(ОписаниеОповещения, Параметры.УникальныйИдентификатор, СтруктураПараметровСмены.ИдентификаторУстройства);
    КонецЕсли;
    
КонецПроцедуры

В строке инициализации объекта ОписаниеОповещения вторым параметром передается ЭтотОбъект:


ОписаниеОповещения = Новый ОписаниеОповещения("НачатьВыполнениеКоманды_ПодключениеЗавершение", ЭтотОбъект, Параметры);

В целевой конфигурации, куда переносился модуль, компилятор выдает ошибку: Переменная не определена (ЭтотОбъект). Это происходит потому, что в целевой базе установлен режим совместимости с версией платформы ниже, чем 8.3.3 (например, «Версия 8.2» или «Версия 8.3.2»). При работе в режиме совместимости платформа принудительно отключает все новые возможности языка и компилирует код по правилам старых версий, где использование ЭтотОбъект в общих модулях было недопустимо.

---

Способ 1. Изменение режима совместимости конфигурации

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

Давайте разберем этот процесс по шагам:

  1. Откройте целевую конфигурацию в режиме Конфигуратор.
  2. В дереве метаданных нажмите правой кнопкой мыши на самый корневой элемент (имя вашей конфигурации) и выберите пункт Свойства.
  3. В открывшейся панели свойств прокрутите список до самого низа, где находится раздел Совместимость.
  4. Найдите свойство Режим совместимости.
  5. Измените его значение на Не использовать или установите версию 8.3.3 (или выше, например, 8.3.10, 8.3.24 в зависимости от версии вашей установленной платформы).
  6. Выполните синтаксический контроль модулей (клавиши Ctrl + F7) и обновите конфигурацию базы данных (клавиша F7).

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

---

Способ 2. Рефакторинг кода без изменения режима совместимости

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

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

Вариант А. Явное указание имени общего модуля

В конструкторе объекта ОписаниеОповещения вторым параметром должен передаваться модуль, в котором объявлена процедура обратного вызова (в нашем примере это процедура НачатьВыполнениеКоманды_ПодключениеЗавершение). Вместо универсального контекстного слова ЭтотОбъект мы можем явно написать имя нашего общего модуля.

Предположим, наш общий модуль называется МенеджерОборудованияКлиент. Давайте посмотрим, как изменится строка инициализации описания оповещения:

Было:


ОписаниеОповещения = Новый ОписаниеОповещения("НачатьВыполнениеКоманды_ПодключениеЗавершение", ЭтотОбъект, Параметры);

Стало:


ОписаниеОповещения = Новый ОписаниеОповещения("НачатьВыполнениеКоманды_ПодключениеЗавершение", МенеджерОборудованияКлиент, Параметры);

Такой код без проблем пройдет проверку синтаксиса даже на самых старых версиях платформы и в любых режимах совместимости, поскольку имя общего модуля является глобально доступным идентификатором.

Вариант Б. Использование «ЭтаФорма» вместо «ЭтотОбъект» (для модулей форм)

Иногда аналогичная ошибка с объявлением ЭтотОбъект возникает при переносе кода из модулей управляемых форм. В управляемых формах на старых режимах совместимости обращение к контексту самой формы через ЭтотОбъект также может вызывать сбои.

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

---

Важное предупреждение о поддержке асинхронности

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

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

← На главную