При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью переноса логики из модуля управляемой формы в модуль объекта (модуль документа или справочника). Это делается для автоматизации процессов, выноса бизнес-логики на сервер или обеспечения корректной работы при программном создании документов. Однако простой копипаст кода часто приводит к ошибке «Переменная не определена (Объект)». Рассмотрим подробно, почему это происходит и как правильно переписать код.
Для начала проанализируем ситуацию. В управляемой форме существует основной реквизит Объект. Он имеет тип ДанныеФормыСтруктура и является лишь временной программной оболочкой над данными документа, с которыми работает пользователь в интерфейсе. Поэтому в модуле формы мы пишем Объект.Дата или Объект.Товары.
В модуле объекта (модуле документа) контекст совершенно иной. Здесь код исполняется внутри самого экземпляра данных. Понятия «реквизит формы Объект» тут просто не существует, так как вы уже находитесь «внутри» этого объекта. Именно поэтому система выдает ошибку, не понимая, к какой переменной вы обращаетесь.
Самый простой и правильный способ исправить ошибку — это убрать префикс Объект. перед именами реквизитов и табличных частей. В модуле документа все его реквизиты доступны напрямую по именам.
Разберем на примере. Если в форме ваш код выглядел так:
Процедура РассчитатьСумму()
Объект.СуммаДокумента = Объект.Цена * Объект.Количество;
КонецПроцедуры
То в модуле объекта его следует переписать следующим образом:
Процедура РассчитатьСумму() Экспорт
СуммаДокумента = Цена * Количество;
КонецПроцедуры
Важный нюанс: если вы планируете вызывать эту процедуру из модуля формы, обязательно добавьте ключевое слово Экспорт.
Иногда для повышения читаемости кода или при возникновении конфликтов имен (когда в процедуре есть локальная переменная с тем же именем, что и реквизит документа) используется ключевое слово ЭтотОбъект. Это полный аналог обращения Объект в форме, но работающий в контексте серверного модуля.
Рассмотрим пример использования:
Процедура ЗаполнитьРеквизиты()
ЭтотОбъект.Дата = ТекущаяДата();
ЭтотОбъект.Ответственный = Пользователи.ТекущийПользователь();
КонецПроцедуры
Хотя технически это работает, в стандартах разработки 1С рекомендуется обращаться к реквизитам напрямую без ЭтотОбъект, если в этом нет крайней необходимости. Это делает код менее громоздким.
При работе с табличными частями (ТЧ) нужно быть особенно внимательными. В форме ТЧ представлена типом ДанныеФормыКоллекция, а в модуле объекта — типом ТабличнаяЧасть. Разберем основные отличия:
Выгрузить(), Загрузить() или НайтиСтроки() напрямую.Пример обхода строк табличной части в модуле объекта:
Для Каждого СтрокаТовар Из Товары Цикл
СтрокаТовар.Сумма = СтрокаТовар.Цена * СтрокаТовар.Количество;
КонецЦикла;
Выясним причину, по которой некоторые участки кода нельзя просто так переместить из формы. Модуль объекта работает на сервере и не имеет визуального интерфейса. Поэтому при переносе кода проанализируем следующие моменты:
Вопрос(), Предупреждение(), Сообщить() в их интерактивном виде работать не будут. Если Сообщить() еще допустим (сообщение выведется пользователю после завершения серверного вызова), то Вопрос() вызовет критическую ошибку.Элементы (например, Элементы.Товары.Видимость = Ложь) должно быть удалено. Модуль объекта отвечает только за данные, но не за их отображение.РежимОтладки), они не будут доступны в модуле документа.Если вам все же нужно передать какую-то информацию из формы в модуль объекта (например, признак того, что документ записывается из специальной обработки), используйте коллекцию ДополнительныеСвойства. Это структура, которая «путешествует» вместе с объектом в рамках одной транзакции.
Пример в модуле формы:
Объект.ДополнительныеСвойства.Вставить("ПропуститьПроверку", Истина);
Объект.Записать();
Пример в модуле объекта (в событии ПередЗаписью):
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ДополнительныеСвойства.Свойство("ПропуститьПроверку") Тогда
// Логика пропуска проверки
КонецЕсли;
КонецПроцедуры
Если процедура большая и в ней много обращений к Объект., можно воспользоваться глобальной заменой (Ctrl + H). Однако будьте осторожны: не заменяйте Объект. там, где это часть другого слова или обращения к метаданным (например, Справочники.Номенклатура.СоздатьОбъект()).
Проанализируем итоговый алгоритм действий при переносе кода:
Экспорт, если процедура будет вызываться извне.Объект..Отказ = Истина, если требуется отменить действие при несоблюдении условий.Соблюдение этих правил позволит вам создавать чистый, отказоустойчивый код, который будет корректно работать как в ручном режиме, так и при автоматизированных операциях в фоновых заданиях.