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

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

Как получить текущий объект в 1С

Как получить текущий объект в 1С: ЭтотОбъект в модуле формы, ТекущиеДанные в таблице, ПолучитьОбъект по ссылке, типичные ошибки и примеры кода.

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

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

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

Что такое «текущий объект» в 1С и почему контекст решает всё

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

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

ЭтотОбъект в модуле объекта

Если код находится в модуле объекта (например, в обработчиках ПередЗаписью, ПриЗаписи, ОбработкаПроведения), текущий объект доступен напрямую через ключевое слово ЭтотОбъект. Это и есть тот самый экземпляр, который сейчас записывается или проводится.

Обращаться к реквизитам можно и без явного указания ЭтотОбъект — в модуле объекта реквизиты доступны по имени. Однако явное обращение полезно, когда нужно передать объект целиком в процедуру общего модуля или сравнить с другим экземпляром.

bsl
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если ЭтотОбъект.ЭтоНовый() Тогда
        ЭтотОбъект.Комментарий = "Создан автоматически";
    КонецЕсли;
КонецПроцедуры

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

Реквизит Объект в модуле формы

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

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

bsl
&НаСервере
Процедура ПересчитатьНаСервере()
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    ДокОбъект.СуммаДокумента = ДокОбъект.Товары.Итог("Сумма");
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры

ТекущиеДанные в табличных частях и динамических списках

Когда пользователь редактирует строку табличной части на форме, текущая строка доступна через Элементы.ИмяТаблицы.ТекущиеДанные. Это самый частый способ получить «текущий объект» строки в обработчиках ПриИзменении, ПриНачалеРедактирования, ПередУдалением.

ТекущиеДанные — это структура данных строки, доступная и на клиенте. Через неё можно читать и менять поля строки: ТекущиеДанные.Сумма = ТекущиеДанные.Цена * ТекущиеДанные.Количество. Если строка не выбрана (таблица пустая или фокус снят), ТекущиеДанные возвращает Неопределено — это нужно проверять всегда.

bsl
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
    ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    ТекущиеДанные.Сумма = ТекущиеДанные.Цена * ТекущиеДанные.Количество;
КонецПроцедуры

Текущая строка динамического списка

В форме списка Элементы.Список.ТекущаяСтрока возвращает ссылку на выделенный элемент, а не объект. Чтобы изменить его программно, потребуется получить объект на сервере через ПолучитьОбъект(), изменить и записать — после чего оповестить список вызовом ОповеститьОбИзменении(Ссылка), чтобы интерфейс обновился.

Получение объекта из ссылки в произвольном коде

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

Метод ПолучитьОбъект() возвращает Неопределено, если запись удалена или ссылка битая. Поэтому безопасный шаблон выглядит так: проверить ссылку на пустоту, получить объект, проверить результат, изменить, записать. Для документов при записи указывайте режим: Записать(РежимЗаписиДокумента.Проведение) или РежимЗаписиДокумента.Запись.

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

Для записи в транзакции с обработкой ошибок оборачивайте Записать() в попытку: при исключении откатывайте транзакцию и фиксируйте текст ошибки в журнале регистрации. Это особенно важно в фоновых заданиях, где ошибка иначе пройдёт незамеченной.

Текущий объект в обработчиках событий и подписках

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

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

Сравнение способов и типичные ошибки

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

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

Тип полученного значения
Норма

ТипЗнч возвращает ДокументОбъект или СправочникОбъект — можно изменять

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

Тип Ссылка — попытка присвоения реквизита ни к чему не приведёт

Сохранение изменений
Норма

После Записать() данные видны в базе и в открытой форме списка

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

Изменения пропадают после закрытия — Записать() не вызван или отменён

Работа при пустой таблице
Норма

Код корректно завершается при ТекущиеДанные = Неопределено

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

Ошибка «Поле объекта не обнаружено» при пустой табличной части

Итог

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

Способ получения текущего объекта определяется контекстом: ЭтотОбъект — в модуле объекта, Объект — в форме, ТекущиеДанные — в таблицах, ПолучитьОбъект() — из ссылки. Ссылка только читается, объект изменяется и требует Записать().

Частые вопросы

Чем ЭтотОбъект отличается от Объект в форме?

ЭтотОбъект доступен в модуле объекта и ссылается на сам записываемый экземпляр. Объект — это реквизит управляемой формы, содержащий данные редактируемой записи; в клиентском контексте он не поддерживает методы объекта, для серверной обработки его преобразуют через РеквизитФормыВЗначение.

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

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

Как получить текущий объект в обычной (неуправляемой) форме?

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

Можно ли получить текущий объект на клиенте в управляемой форме?

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

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

В модуле объекта — ЭтотОбъект.ЭтоНовый(). В управляемой форме — проверка Параметры.Ключ.Пустая() в обработчике ПриСозданииНаСервере или проверка Объект.Ссылка.Пустая() в любой серверной процедуре.

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

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