Как исправить ошибку Переменная не определена Объект в модуле документа

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

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

Причина возникновения ошибки: разница контекстов

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

В модуле объекта (модуле документа) контекст совершенно иной. Здесь код исполняется внутри самого экземпляра данных. Понятия «реквизит формы Объект» тут просто не существует, так как вы уже находитесь «внутри» этого объекта. Именно поэтому система выдает ошибку, не понимая, к какой переменной вы обращаетесь.

Решение 1: Прямое обращение к реквизитам

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

Разберем на примере. Если в форме ваш код выглядел так:


Процедура РассчитатьСумму()
    Объект.СуммаДокумента = Объект.Цена * Объект.Количество;
КонецПроцедуры

То в модуле объекта его следует переписать следующим образом:


Процедура РассчитатьСумму() Экспорт
    СуммаДокумента = Цена * Количество;
КонецПроцедуры

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

Решение 2: Использование ЭтотОбъект

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

Рассмотрим пример использования:


Процедура ЗаполнитьРеквизиты()
    ЭтотОбъект.Дата = ТекущаяДата();
    ЭтотОбъект.Ответственный = Пользователи.ТекущийПользователь();
КонецПроцедуры

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

Работа с табличными частями

При работе с табличными частями (ТЧ) нужно быть особенно внимательными. В форме ТЧ представлена типом ДанныеФормыКоллекция, а в модуле объекта — типом ТабличнаяЧасть. Разберем основные отличия:

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

Пример обхода строк табличной части в модуле объекта:


Для Каждого СтрокаТовар Из Товары Цикл
    СтрокаТовар.Сумма = СтрокаТовар.Цена * СтрокаТовар.Количество;
КонецЦикла;

Что нельзя переносить в модуль объекта

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

Передача параметров через ДополнительныеСвойства

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

Пример в модуле формы:


Объект.ДополнительныеСвойства.Вставить("ПропуститьПроверку", Истина);
Объект.Записать();

Пример в модуле объекта (в событии ПередЗаписью):


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

Рекомендации по массовому исправлению

Если процедура большая и в ней много обращений к Объект., можно воспользоваться глобальной заменой (Ctrl + H). Однако будьте осторожны: не заменяйте Объект. там, где это часть другого слова или обращения к метаданным (например, Справочники.Номенклатура.СоздатьОбъект()).

Проанализируем итоговый алгоритм действий при переносе кода:

  1. Скопируйте процедуру в модуль объекта.
  2. Добавьте ключевое слово Экспорт, если процедура будет вызываться извне.
  3. Удалите все префиксы Объект..
  4. Проверьте код на наличие обращений к элементам интерфейса и удалите их.
  5. Замените интерактивные диалоги на логику с параметром Отказ = Истина, если требуется отменить действие при несоблюдении условий.

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

← На главную