Разработка и Конфигурация · 10 мин
1С: как в модуле объекта обратиться к объекту
Как в модуле объекта 1С обратиться к самому объекту: ЭтотОбъект, Ссылка, реквизиты, табличные части, ПолучитьОбъект. Примеры кода, типичные ошибки и проверка результата.
Модуль объекта в 1С — это программный модуль, который выполняется в контексте конкретного экземпляра прикладного объекта: документа, справочника, плана видов характеристик и т.д. Внутри этого модуля разработчик уже «находится» внутри объекта, поэтому обращение к его данным отличается от работы в модуле формы или общем модуле.
Главная особенность: в модуле объекта все реквизиты, табличные части и стандартные свойства доступны напрямую, без создания переменной-ссылки на объект. Ключевое слово ЭтотОбъект позволяет явно указать текущий экземпляр, а свойство Ссылка даёт доступ к ссылке на объект в базе данных.
Путаница возникает чаще всего в двух ситуациях: когда из модуля объекта нужно обратиться к другому объекту (например, к объекту по ссылке из реквизита), и когда разработчик смешивает контексты формы и объекта. Ниже разобраны оба сценария с примерами кода и проверкой результата.
Как устроен контекст модуля объекта
Модуль объекта выполняется на сервере (или в толстом клиенте) в момент, когда с объектом происходит событие: запись, проведение, заполнение, проверка заполнения. В этот момент в памяти существует экземпляр объекта — например, ДокументОбъект.РеализацияТоваровУслуг — и весь код модуля работает с его данными.
Это значит, что к любому реквизиту можно обратиться просто по имени, без префиксов:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Прямое обращение к реквизитам текущего объекта
Если Не ЗначениеЗаполнено(Контрагент) Тогда
Сообщить("Не заполнен контрагент");
Отказ = Истина;
КонецЕсли;
// Обращение к табличной части
Для Каждого СтрокаТовара Из Товары Цикл
СтрокаТовара.Сумма = СтрокаТовара.Цена * СтрокаТовара.Количество;
КонецЦикла;
КонецПроцедуры
Имена реквизитов (Контрагент), табличных частей (Товары) и стандартных свойств (Дата, Номер, Проведен) разрешаются в контексте текущего объекта автоматически. Явно создавать переменную и присваивать ей объект не нужно.
Ключевое слово ЭтотОбъект: когда оно нужно
Ключевое слово ЭтотОбъект возвращает сам текущий объект целиком. В простых обращениях к реквизитам оно избыточно — запись ЭтотОбъект.Контрагент равнозначна просто Контрагент. Но есть ситуации, где без него не обойтись.
Первая ситуация — передача текущего объекта как параметра в процедуру или функцию общего модуля:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
// Передаём сам объект в общий модуль
ЗаполнениеДокументов.ЗаполнитьШапкуПоУмолчанию(ЭтотОбъект);
КонецПроцедуры
Вторая ситуация — обход коллекции реквизитов через метаданные, когда нужно работать с объектом как со структурой данных:
Для Каждого Реквизит Из ЭтотОбъект.Метаданные().Реквизиты Цикл
ЗначениеРеквизита = ЭтотОбъект[Реквизит.Имя];
КонецЦикла;
Обратите внимание на обращение через квадратные скобки: ЭтотОбъект["ИмяРеквизита"]. Такой синтаксис позволяет обращаться к реквизитам по имени, хранящемуся в строковой переменной, — это стандартный приём для универсальных алгоритмов.
Обращение к ссылке текущего объекта
Объект и ссылка — разные сущности. Ссылка — это «адрес» записи в базе данных, лёгкий идентификатор. Объект — полная копия данных в памяти с возможностью изменения и записи. В модуле объекта ссылка доступна через свойство Ссылка:
Процедура ПриЗаписи(Отказ)
// Ссылка на текущий документ
ТекущаяСсылка = Ссылка;
// Типичное применение — параметр запроса
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрСведений.Статусы ГДЕ Документ = &Документ";
Запрос.УстановитьПараметр("Документ", Ссылка);
КонецПроцедуры
Важный нюанс: для нового, ещё не записанного объекта свойство Ссылка содержит пустую ссылку. Если логика зависит от ссылки (например, запрос к регистрам), проверяйте ЭтоНовый() или используйте ПолучитьСсылкуНового() после вызова УстановитьСсылкуНового().
Обращение к другому объекту из модуля объекта
Частая задача: в модуле объекта документа нужно прочитать или изменить данные другого объекта, на который указывает реквизит. Здесь работает стандартная пара «ссылка → объект».
Только чтение данных
Если нужно только прочитать реквизиты другого объекта, получать объект не обязательно — доступ через точку от ссылки выполняется автоматически (платформа сама считывает данные):
// Контрагент — реквизит текущего объекта, содержит ссылку
НаименованиеКонтрагента = Контрагент.Наименование;
ИНН = Контрагент.ИНН;
Однако каждое такое обращение через точку — отдельное обращение к базе. При чтении нескольких реквизитов в цикле эффективнее запрос или единоразовое получение объекта.
Изменение другого объекта
Для изменения нужно явно получить объект и записать его:
ЗаказОбъект = ЗаказПокупателя.ПолучитьОбъект();
ЗаказОбъект.Статус = Перечисления.СтатусыЗаказа.ВРаботе;
ЗаказОбъект.Записать();
Здесь ЗаказПокупателя — реквизит текущего объекта (ссылка), метод ПолучитьОбъект() загружает данные в память, а Записать() фиксирует изменения. Без вызова Записать() изменения потеряются.
- 1Проверьте, что реквизит-ссылка заполнен: ЗначениеЗаполнено(ЗаказПокупателя)
- 2Получите объект: ЗаказОбъект = ЗаказПокупателя.ПолучитьОбъект()
- 3Измените нужные реквизиты объекта
- 4Вызовите ЗаказОбъект.Записать() внутри попытки с обработкой исключения
- 5Проверьте результат в базе: откройте изменённый объект в режиме предприятия
Обращение из модуля формы к объекту
Отдельный частый вопрос — как обратиться к объекту из модуля формы, ведь там контекст другой. В управляемой форме данные объекта хранятся в реквизите формы (обычно Объект типа ДанныеФормыСтруктура), и методы объекта напрямую недоступны.
Чтобы получить настоящий объект на сервере, используют РеквизитФормыВЗначение:
&НаСервере
Процедура ПересчитатьНаСервере()
ДокОбъект = РеквизитФормыВЗначение("Объект");
ДокОбъект.ПересчитатьСуммы(); // метод из модуля объекта
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры
Обратное преобразование ЗначениеВРеквизитФормы обязательно, иначе изменения не вернутся в форму. В обычных (неуправляемых) формах объект доступен проще — через свойство ЭтотОбъект или ДокументОбъект в зависимости от версии платформы.
Способы обратиться к объекту
Основной способ внутри модуля объекта. Ограничение: работает только в контексте текущего объекта.
Когда нужно передать объект целиком в процедуру или обратиться к реквизиту по строковому имени. Избыточен для простых обращений.
Для чтения/изменения ДРУГОГО объекта по ссылке. Нельзя применять к собственной ссылке внутри модуля объекта.
Единственный способ получить объект из управляемой формы. Требует обратного преобразования и работает только на сервере.
Типичные ошибки и как их избежать
Большинство проблем при обращении к объекту из его модуля связано с непониманием границы между объектом и ссылкой, а также с попытками использовать клиентский контекст там, где выполняется серверный код.
Ещё одна распространённая ситуация — обращение к объекту из подписки на событие. В обработчике подписки объект приходит как параметр (например, Источник), и работать с ним нужно именно через этот параметр, а не пытаться получить объект заново по ссылке.
Проверка результата
После внесения изменений в модуль объекта проверьте поведение на копии базы: создайте новый документ, заполните его, запишите и проведите. Логика в ПередЗаписью и ОбработкаПроведения должна отработать без ошибок, а изменённые данные других объектов — реально сохраниться в базе.
Как проверить результат
Код компилируется, значения читаются и изменяются без ЭтотОбъект
Ошибка 'Переменная не определена' — код находится не в модуле объекта
После записи основного документа изменения видны в связанном объекте
Связанный объект не изменился — забыли вызвать Записать()
Перед использованием ссылки проверяется ЭтоНовый()
Запросы по ссылке возвращают пустоту для новых документов
FAQ
Чем ЭтотОбъект отличается от Ссылка в модуле объекта?
ЭтотОбъект — это сам объект данных в памяти с возможностью изменения (тип ДокументОбъект, СправочникОбъект). Ссылка — только идентификатор записи в базе, пригодный для запросов и сравнений, но не для изменения данных.
Можно ли из модуля объекта обратиться к форме документа?
Напрямую — нет, модуль объекта выполняется на сервере и не знает о форме. Обратная связь реализуется через параметры записи, оповещения (Оповестить) на клиенте или дополнительные свойства объекта, которые форма читает после записи.
Как обратиться к реквизиту, чьё имя хранится в переменной?
Через квадратные скобки: ЭтотОбъект[ИмяРеквизита]. Это работает и для реквизитов, и для табличных частей текущего объекта, что удобно для универсальных алгоритмов обхода данных.
Почему ПолучитьОбъект() возвращает Неопределено?
Метод возвращает Неопределено, если по ссылке в базе нет объекта — например, это битая ссылка на удалённый элемент. Перед использованием результата проверяйте его на Неопределено, а саму ссылку — через ЗначениеЗаполнено.
Нужно ли вызывать Записать() для текущего объекта в конце модуля объекта?
Нет. Если код выполняется в обработчиках событий записи или проведения, платформа сама завершит запись текущего объекта. Явный вызов Записать() внутри этих событий приведёт к рекурсии или ошибке.
Что важно запомнить
В модуле объекта текущий объект доступен напрямую по именам реквизитов и через ЭтотОбъект, его ссылка — через свойство Ссылка. Другие объекты изменяются через СсылкаНаЭлемент.ПолучитьОбъект() с обязательным Записать(). Никогда не вызывайте ПолучитьОбъект() для собственной ссылки текущего объекта.