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

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

1С: как обратиться к текущему документу

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

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

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

Как устроен доступ к документу в разных контекстах

«Текущий документ» в 1С — не единая сущность. Существует объект ДокументОбъект (данные в памяти с методами Записать, Провести), ссылка ДокументСсылка (идентификатор в базе) и представление документа на форме (ДанныеФормыСтруктура). Код, который работает с одним типом, не сработает с другим без преобразования.

Поэтому первый вопрос при написании обработчика: «Где выполняется этот код?» От ответа зависит, какие переменные доступны и какие преобразования потребуются. Ниже разобраны основные сценарии.

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

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

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

// Текущий документ — это ЭтотОбъект

Если Не ЗначениеЗаполнено(ЭтотОбъект.Контрагент) Тогда

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

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

КонецЕсли;

// Реквизиты доступны и без префикса

СуммаДокумента = Товары.Итог("Сумма");

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

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

Обращение к документу в модуле управляемой формы

В управляемой форме документа основной реквизит обычно называется Объект и имеет тип ДанныеФормыСтруктура. Через него можно читать и менять реквизиты, обращаться к табличным частям:

&НаКлиенте

Процедура РассчитатьСумму(Команда)

Объект.СуммаДокумента = Объект.Товары.Итог("Сумма");

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

Однако методов объекта (Записать, Провести, ПроверитьЗаполнение) у реквизита формы нет. Чтобы их вызвать, нужно преобразовать данные формы в объект на сервере:

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

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

Как получить ссылку текущего документа из формы

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

Обращение к документу из подписок и внешних обработок

В подписке на событие (например, «ПриЗаписи» документа) текущий документ передаётся параметром обработчика — обычно Источник. Это полноценный ДокументОбъект, методы и реквизиты доступны напрямую:

Процедура ДокументыПриЗаписи(Источник, Отказ) Экспорт

Если ТипЗнч(Источник) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда

// работаем с Источник как с объектом

КонецЕсли;

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

Из произвольного места кода (общий модуль, внешняя обработка) текущего документа как такового нет — его нужно получить по ссылке или найти. Типовой приём:

ДокСсылка = Документы.РеализацияТоваровУслуг.НайтиПоНомеру(НомерДок, ТекущаяДатаСеанса());

Если ЗначениеЗаполнено(ДокСсылка) Тогда

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

ДокОбъект.Комментарий = "Изменён обработкой";

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

КонецЕсли;

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

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

Как проверить, что обращение работает правильно

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

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

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

Запись документа из формы
Норма

Документ записывается, номер и дата актуальны, форма не блокируется

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

Ошибка «Метод объекта не обнаружен» — значит, вызов идёт у реквизита формы, а не у объекта

Доступ к реквизитам в модуле объекта
Норма

Реквизиты читаются по имени, Ссылка заполнена после записи

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

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

Изменения из внешней обработки
Норма

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

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

Данные не сохранились — пропущен вызов Записать()

Выбор подхода под задачу

Маршрут решения

Как выбрать действие

Код находится в обработчике формы документаИспользуйте реквизит формы Объект; для методов объекта — РеквизитФормыВЗначение на сервере
Код находится в модуле объекта или подписке на событиеРаботайте через ЭтотОбъект / параметр Источник напрямую
Нужно только прочитать реквизиты документа из другого местаИспользуйте запрос или обращение через точку от ссылки, без ПолучитьОбъект()
Нужно изменить документ программноПолучите объект через ПолучитьОбъект(), измените, вызовите Записать() с нужным режимом
Итог

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

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

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

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

ЭтотОбъект — контекст модуля объекта, это настоящий ДокументОбъект со всеми методами. Объект в форме — реквизит формы типа ДанныеФормыСтруктура: реквизиты читать и менять можно, но методов Записать и Провести у него нет.

Как обратиться к текущему документу в обычной форме?

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

Как из табличной части узнать, какой документ текущий?

У строки табличной части в модуле объекта контекст документа доступен через ЭтотОбъект. В форме — через тот же реквизит Объект. Отдельной «ссылки на родителя» у строки в коде формы обычно не требуется.

Можно ли получить текущий документ в фоновом задании?

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

Почему Объект.Ссылка пустая, хотя документ открыт?

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