Разработка и Конфигурация · 8 мин
1С: как обратиться к текущему документу
Как обратиться к текущему документу в 1С: ЭтотОбъект, РеквизитФормыВЗначение, контекст формы и модуля объекта. Примеры кода, типичные ошибки и проверка результата.
Встроенный язык 1С даёт несколько разных способов обратиться к текущему документу, и выбор зависит от того, где выполняется код: в модуле формы, в модуле объекта, в подписке на событие или во внешней обработке. Ошибка на этом этапе — самая частая причина сообщений вида «Поле объекта не обнаружено» и «Переменная не определена».
Ключевой принцип: в управляемой форме документа нет прямого доступа к объекту — есть реквизит формы типа «ДанныеФормыСтруктура». В модуле объекта, наоборот, доступ к данным идёт через контекст самого объекта (ЭтотОбъект). Путать эти два контекста нельзя: они живут на разных сторонах клиент-серверного взаимодействия.
Как устроен доступ к документу в разных контекстах
«Текущий документ» в 1С — не единая сущность. Существует объект ДокументОбъект (данные в памяти с методами Записать, Провести), ссылка ДокументСсылка (идентификатор в базе) и представление документа на форме (ДанныеФормыСтруктура). Код, который работает с одним типом, не сработает с другим без преобразования.
Поэтому первый вопрос при написании обработчика: «Где выполняется этот код?» От ответа зависит, какие переменные доступны и какие преобразования потребуются. Ниже разобраны основные сценарии.
Обращение к текущему документу в модуле объекта
В модуле объекта документа (обработчики ПриЗаписи, ОбработкаПроведения, ПередЗаписью и другие) текущий документ — это сам контекст модуля. Явно писать «ЭтотОбъект» необязательно: реквизиты доступны напрямую по имени.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Текущий документ — это ЭтотОбъект
Если Не ЗначениеЗаполнено(ЭтотОбъект.Контрагент) Тогда
Сообщить("Не заполнен контрагент");
Отказ = Истина;
КонецЕсли;
// Реквизиты доступны и без префикса
СуммаДокумента = Товары.Итог("Сумма");
КонецПроцедуры
Обратите внимание: ссылка на самого себя доступна через свойство Ссылка. Для нового, ещё не записанного документа она может быть пустой — проверяйте ЭтоНовый(), прежде чем использовать ссылку в запросах или сравнениях.
Обращение к документу в модуле управляемой формы
В управляемой форме документа основной реквизит обычно называется Объект и имеет тип ДанныеФормыСтруктура. Через него можно читать и менять реквизиты, обращаться к табличным частям:
&НаКлиенте
Процедура РассчитатьСумму(Команда)
Объект.СуммаДокумента = Объект.Товары.Итог("Сумма");
КонецПроцедуры
Однако методов объекта (Записать, Провести, ПроверитьЗаполнение) у реквизита формы нет. Чтобы их вызвать, нужно преобразовать данные формы в объект на сервере:
&НаСервере
Процедура ЗаписатьОбъектНаСервере()
ДокОбъект = РеквизитФормыВЗначение("Объект");
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедурыОбратное преобразование ЗначениеВРеквизитФормы обязательно, иначе изменения, сделанные объектом при записи (например, заполнение номера), не отобразятся на форме.
Как получить ссылку текущего документа из формы
Ссылка доступна прямо из реквизита формы: Объект.Ссылка. Это удобно для передачи в запросы, открытия связанных форм и проверок. Для нового документа ссылка будет пустой — используйте ЗначениеЗаполнено(Объект.Ссылка) как проверку «документ уже записан».
Обращение к документу из подписок и внешних обработок
В подписке на событие (например, «ПриЗаписи» документа) текущий документ передаётся параметром обработчика — обычно Источник. Это полноценный ДокументОбъект, методы и реквизиты доступны напрямую:
Процедура ДокументыПриЗаписи(Источник, Отказ) Экспорт
Если ТипЗнч(Источник) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда
// работаем с Источник как с объектом
КонецЕсли;
КонецПроцедуры
Из произвольного места кода (общий модуль, внешняя обработка) текущего документа как такового нет — его нужно получить по ссылке или найти. Типовой приём:
ДокСсылка = Документы.РеализацияТоваровУслуг.НайтиПоНомеру(НомерДок, ТекущаяДатаСеанса());
Если ЗначениеЗаполнено(ДокСсылка) Тогда
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ДокОбъект.Комментарий = "Изменён обработкой";
ДокОбъект.Записать();
КонецЕсли;
Типичные ошибки и как их избежать
Как проверить, что обращение работает правильно
После внесения кода проверьте три вещи: документ открывается и записывается без ошибок, изменённые реквизиты реально сохраняются в базе (переоткройте документ), а в журнале регистрации нет ошибок от фоновых обработчиков и подписок.
Как проверить результат
Документ записывается, номер и дата актуальны, форма не блокируется
Ошибка «Метод объекта не обнаружен» — значит, вызов идёт у реквизита формы, а не у объекта
Реквизиты читаются по имени, Ссылка заполнена после записи
Пустая ссылка у нового документа используется в логике до записи
После ПолучитьОбъект() и Записать() данные видны при повторном открытии
Данные не сохранились — пропущен вызов Записать()
Выбор подхода под задачу
Как выбрать действие
Что важно запомнить
В модуле объекта текущий документ — это ЭтотОбъект, в управляемой форме — реквизит Объект с преобразованием через РеквизитФормыВЗначение, извне — ссылка и ПолучитьОбъект(). Главная ошибка новичков — путать эти контексты; вторая по частоте — работа с пустой ссылкой незаписанного документа.
Частые вопросы
Чем ЭтотОбъект отличается от Объект в форме?
ЭтотОбъект — контекст модуля объекта, это настоящий ДокументОбъект со всеми методами. Объект в форме — реквизит формы типа ДанныеФормыСтруктура: реквизиты читать и менять можно, но методов Записать и Провести у него нет.
Как обратиться к текущему документу в обычной форме?
В обычной (неуправляемой) форме доступен объект напрямую — реквизит формы связан с ДокументОбъект, поэтому методы вроде Записать() вызываются без преобразований. Преобразования нужны только в управляемых формах.
Как из табличной части узнать, какой документ текущий?
У строки табличной части в модуле объекта контекст документа доступен через ЭтотОбъект. В форме — через тот же реквизит Объект. Отдельной «ссылки на родителя» у строки в коде формы обычно не требуется.
Можно ли получить текущий документ в фоновом задании?
Нет, фоновое задание не знает о «текущем» документе формы. Передайте в фоновое задание ссылку параметром, а внутри получите объект через ПолучитьОбъект() или читайте данные запросом.
Почему Объект.Ссылка пустая, хотя документ открыт?
Документ создан, но ещё не записан в базу — ссылки у него нет. Проверяйте ЭтоНовый() или ЗначениеЗаполнено(Объект.Ссылка) перед использованием ссылки в запросах и сравнениях.