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