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

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

Как получить объект в форме 1С: рабочие способы и примеры

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

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

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

Ниже разобраны все рабочие способы с примерами кода, ограничениями и типичными ошибками, которые приводят к сообщениям вида «Метод объекта не обнаружен» или «Недопустимое значение».

Как устроены данные в управляемой форме

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

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

Способ 1: РеквизитФормыВЗначение — универсальный метод формы

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

&НаСервере

Процедура ВыполнитьОбработкуНаСервере()

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

ДокОбъект.ЗаполнитьДанные(); // процедура из модуля объекта

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

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

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

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

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

Способ 2: ДанныеФормыВЗначение — глобальный метод

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

&НаСервере

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

ДокОбъект = ДанныеФормыВЗначение(ЭтаФорма.Объект,

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

Если Не ДокОбъект.ПроверитьЗаполнение() Тогда

ВызватьИсключение "Документ заполнен не полностью";

КонецЕсли;

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

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

Чем отличаются методы преобразования

РеквизитФормыВЗначение

Метод формы, работает только в её модуле на сервере. Тип обычно определяется автоматически. Удобен для основного реквизита Объект.

ДанныеФормыВЗначение

Глобальный метод, доступен в общих модулях. Требует явного указания типа. Подходит для любых реквизитов с данными формы.

ЭтаФорма.Объект

Прямой доступ к объекту только в обычных формах. В управляемых возвращает ДанныеФормыСтруктуру без методов объекта.

Способ 3: ЭтаФорма.Объект в обычных формах

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

Процедура КнопкаПровестиНажатие(Кнопка)

ЭтаФорма.Объект.Записать(РежимЗаписиДокумента.Проведение);

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

Частая ошибка начинающих разработчиков — переносить этот приём в управляемую форму. Там ЭтаФорма.Объект вернёт ДанныеФормыСтруктуру, и попытка вызвать Записать() или обратиться к методу модуля объекта завершится ошибкой «Метод объекта не обнаружен».

Как получить объект на клиенте и почему это невозможно

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

Правильный шаблон — клиентская процедура-обработчик вызывает серверную, которая выполняет всю работу с объектом:

&НаКлиенте

Процедура ЗаполнитьПоДанным(Команда)

ЗаполнитьПоДаннымНаСервере();

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

&НаСервере

Процедура ЗаполнитьПоДаннымНаСервере()

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

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

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

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

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

Особые случаи: динамический список, внешняя обработка, расширение

Объект в форме внешней обработки

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

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

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

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

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

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

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

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

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

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

// работаем с объектом

КонецЕсли;

Признак корректной работы: после ЗначениеВРеквизитФормы изменённые реквизиты видны в форме, а флаг модифицированности формы установлен. Если данные в форме не обновились — почти наверняка пропущено обратное преобразование.

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

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

Тип переменной после преобразования
Норма

ДокументОбъект или СправочникОбъект конкретного вида

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

ДанныеФормыСтруктура — преобразование не выполнено

Отображение изменений в форме
Норма

Поля формы обновились после ЗначениеВРеквизитФормы

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

Данные старые — забыто обратное преобразование

Контекст выполнения
Норма

Процедура с директивой &НаСервере

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

Вызов из &НаКлиенте — метод недоступен

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

Почему возникает ошибка «Метод объекта не обнаружен (Записать)»?

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

Можно ли получить объект без вызова сервера?

Нет. В управляемом приложении объектная модель существует только на сервере. На клиенте доступны лишь данные формы. Любая работа с объектом требует серверного вызова.

Что вернёт РеквизитФормыВЗначение для нового, ещё не записанного документа?

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

Чем отличается ЗначениеВРеквизитФормы от ЗначениеВДанныеФормы?

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

Как получить объект в модуле менеджера или общем модуле?

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

Влияет ли преобразование на производительность?

Каждое преобразование копирует данные, поэтому в циклах и при массовой обработке его стоит минимизировать: получить объект один раз, выполнить все операции, вернуть результат один раз. Для чтения больших объёмов данных вместо объектов используйте запросы.

Итог

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

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