К статье
Практический материал

Разработка и Конфигурация · 10 мин

1С: как в модуле объекта обратиться к объекту

Как в модуле объекта 1С обратиться к самому объекту: ЭтотОбъект, Ссылка, реквизиты, табличные части, ПолучитьОбъект. Примеры кода, типичные ошибки и проверка результата.

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

Главная особенность: в модуле объекта все реквизиты, табличные части и стандартные свойства доступны напрямую, без создания переменной-ссылки на объект. Ключевое слово ЭтотОбъект позволяет явно указать текущий экземпляр, а свойство Ссылка даёт доступ к ссылке на объект в базе данных.

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

Как устроен контекст модуля объекта

Модуль объекта выполняется на сервере (или в толстом клиенте) в момент, когда с объектом происходит событие: запись, проведение, заполнение, проверка заполнения. В этот момент в памяти существует экземпляр объекта — например, ДокументОбъект.РеализацияТоваровУслуг — и весь код модуля работает с его данными.

Это значит, что к любому реквизиту можно обратиться просто по имени, без префиксов:

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

// Прямое обращение к реквизитам текущего объекта

Если Не ЗначениеЗаполнено(Контрагент) Тогда

Сообщить("Не заполнен контрагент");

Отказ = Истина;

КонецЕсли;

// Обращение к табличной части

Для Каждого СтрокаТовара Из Товары Цикл

СтрокаТовара.Сумма = СтрокаТовара.Цена * СтрокаТовара.Количество;

КонецЦикла;

КонецПроцедуры

Имена реквизитов (Контрагент), табличных частей (Товары) и стандартных свойств (Дата, Номер, Проведен) разрешаются в контексте текущего объекта автоматически. Явно создавать переменную и присваивать ей объект не нужно.

Ключевое слово ЭтотОбъект: когда оно нужно

Ключевое слово ЭтотОбъект возвращает сам текущий объект целиком. В простых обращениях к реквизитам оно избыточно — запись ЭтотОбъект.Контрагент равнозначна просто Контрагент. Но есть ситуации, где без него не обойтись.

Первая ситуация — передача текущего объекта как параметра в процедуру или функцию общего модуля:

Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)

// Передаём сам объект в общий модуль

ЗаполнениеДокументов.ЗаполнитьШапкуПоУмолчанию(ЭтотОбъект);

КонецПроцедуры

Вторая ситуация — обход коллекции реквизитов через метаданные, когда нужно работать с объектом как со структурой данных:

Для Каждого Реквизит Из ЭтотОбъект.Метаданные().Реквизиты Цикл

ЗначениеРеквизита = ЭтотОбъект[Реквизит.Имя];

КонецЦикла;

Обратите внимание на обращение через квадратные скобки: ЭтотОбъект["ИмяРеквизита"]. Такой синтаксис позволяет обращаться к реквизитам по имени, хранящемуся в строковой переменной, — это стандартный приём для универсальных алгоритмов.

Обращение к ссылке текущего объекта

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

Процедура ПриЗаписи(Отказ)

// Ссылка на текущий документ

ТекущаяСсылка = Ссылка;

// Типичное применение — параметр запроса

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрСведений.Статусы ГДЕ Документ = &Документ";

Запрос.УстановитьПараметр("Документ", Ссылка);

КонецПроцедуры

Важный нюанс: для нового, ещё не записанного объекта свойство Ссылка содержит пустую ссылку. Если логика зависит от ссылки (например, запрос к регистрам), проверяйте ЭтоНовый() или используйте ПолучитьСсылкуНового() после вызова УстановитьСсылкуНового().

Обращение к другому объекту из модуля объекта

Частая задача: в модуле объекта документа нужно прочитать или изменить данные другого объекта, на который указывает реквизит. Здесь работает стандартная пара «ссылка → объект».

Только чтение данных

Если нужно только прочитать реквизиты другого объекта, получать объект не обязательно — доступ через точку от ссылки выполняется автоматически (платформа сама считывает данные):

// Контрагент — реквизит текущего объекта, содержит ссылку

НаименованиеКонтрагента = Контрагент.Наименование;

ИНН = Контрагент.ИНН;

Однако каждое такое обращение через точку — отдельное обращение к базе. При чтении нескольких реквизитов в цикле эффективнее запрос или единоразовое получение объекта.

Изменение другого объекта

Для изменения нужно явно получить объект и записать его:

ЗаказОбъект = ЗаказПокупателя.ПолучитьОбъект();

ЗаказОбъект.Статус = Перечисления.СтатусыЗаказа.ВРаботе;

ЗаказОбъект.Записать();

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

Порядок действий при изменении другого объекта
  1. 1
    Проверьте, что реквизит-ссылка заполнен: ЗначениеЗаполнено(ЗаказПокупателя)
  2. 2
    Получите объект: ЗаказОбъект = ЗаказПокупателя.ПолучитьОбъект()
  3. 3
    Измените нужные реквизиты объекта
  4. 4
    Вызовите ЗаказОбъект.Записать() внутри попытки с обработкой исключения
  5. 5
    Проверьте результат в базе: откройте изменённый объект в режиме предприятия

Обращение из модуля формы к объекту

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

Чтобы получить настоящий объект на сервере, используют РеквизитФормыВЗначение:

&НаСервере

Процедура ПересчитатьНаСервере()

ДокОбъект = РеквизитФормыВЗначение("Объект");

ДокОбъект.ПересчитатьСуммы(); // метод из модуля объекта

ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

КонецПроцедуры

Обратное преобразование ЗначениеВРеквизитФормы обязательно, иначе изменения не вернутся в форму. В обычных (неуправляемых) формах объект доступен проще — через свойство ЭтотОбъект или ДокументОбъект в зависимости от версии платформы.

Способы обратиться к объекту

Прямое обращение по имени реквизита

Основной способ внутри модуля объекта. Ограничение: работает только в контексте текущего объекта.

ЭтотОбъект

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

Ссылка.ПолучитьОбъект()

Для чтения/изменения ДРУГОГО объекта по ссылке. Нельзя применять к собственной ссылке внутри модуля объекта.

РеквизитФормыВЗначение("Объект")

Единственный способ получить объект из управляемой формы. Требует обратного преобразования и работает только на сервере.

Типичные ошибки и как их избежать

Большинство проблем при обращении к объекту из его модуля связано с непониманием границы между объектом и ссылкой, а также с попытками использовать клиентский контекст там, где выполняется серверный код.

Типичные ошибки
01
Вызов Ссылка.ПолучитьОбъект() для текущего объекта внутри его модуля — создаёт дубль объекта и приводит к конфликту при записи
02
Изменение другого объекта без вызова Записать() — изменения теряются без сообщений об ошибке
03
Обращение к реквизитам нового объекта через Ссылка до первой записи — ссылка пустая, запросы возвращают пустой результат
04
Попытка вызвать метод объекта из управляемой формы напрямую — ошибка 'Метод объекта не обнаружен', нужен РеквизитФормыВЗначение
05
Чтение реквизитов через точку от ссылки в цикле по тысячам строк — резкое падение производительности, нужен запрос

Ещё одна распространённая ситуация — обращение к объекту из подписки на событие. В обработчике подписки объект приходит как параметр (например, Источник), и работать с ним нужно именно через этот параметр, а не пытаться получить объект заново по ссылке.

Проверка результата

После внесения изменений в модуль объекта проверьте поведение на копии базы: создайте новый документ, заполните его, запишите и проведите. Логика в ПередЗаписью и ОбработкаПроведения должна отработать без ошибок, а изменённые данные других объектов — реально сохраниться в базе.

Контрольные точки

Как проверить результат

Обращение к реквизитам текущего объекта
Норма

Код компилируется, значения читаются и изменяются без ЭтотОбъект

Тревожный признак

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

Изменение другого объекта по ссылке
Норма

После записи основного документа изменения видны в связанном объекте

Тревожный признак

Связанный объект не изменился — забыли вызвать Записать()

Работа с ссылкой нового объекта
Норма

Перед использованием ссылки проверяется ЭтоНовый()

Тревожный признак

Запросы по ссылке возвращают пустоту для новых документов

FAQ

Чем ЭтотОбъект отличается от Ссылка в модуле объекта?

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

Можно ли из модуля объекта обратиться к форме документа?

Напрямую — нет, модуль объекта выполняется на сервере и не знает о форме. Обратная связь реализуется через параметры записи, оповещения (Оповестить) на клиенте или дополнительные свойства объекта, которые форма читает после записи.

Как обратиться к реквизиту, чьё имя хранится в переменной?

Через квадратные скобки: ЭтотОбъект[ИмяРеквизита]. Это работает и для реквизитов, и для табличных частей текущего объекта, что удобно для универсальных алгоритмов обхода данных.

Почему ПолучитьОбъект() возвращает Неопределено?

Метод возвращает Неопределено, если по ссылке в базе нет объекта — например, это битая ссылка на удалённый элемент. Перед использованием результата проверяйте его на Неопределено, а саму ссылку — через ЗначениеЗаполнено.

Нужно ли вызывать Записать() для текущего объекта в конце модуля объекта?

Нет. Если код выполняется в обработчиках событий записи или проведения, платформа сама завершит запись текущего объекта. Явный вызов Записать() внутри этих событий приведёт к рекурсии или ошибке.

Итог

Что важно запомнить

В модуле объекта текущий объект доступен напрямую по именам реквизитов и через ЭтотОбъект, его ссылка — через свойство Ссылка. Другие объекты изменяются через СсылкаНаЭлемент.ПолучитьОбъект() с обязательным Записать(). Никогда не вызывайте ПолучитьОбъект() для собственной ссылки текущего объекта.