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

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

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

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

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

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

Ниже разобраны основные способы преобразования: универсальные методы РеквизитФормыВЗначение и ДанныеФормыВЗначение, особенности работы с основным реквизитом формы, типичные ошибки и ограничения каждого подхода.

Что представляют собой данные формы и зачем нужен объект

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

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

Важно понимать: преобразование данных формы в объект возможно только в серверном контексте. Директива &НаКлиенте для такого кода не подойдёт — там нет ни прикладных объектов, ни доступа к базе данных.

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

Если перед вами форма документа, справочника или другого объектного типа, у неё есть основной реквизит «Объект». Получить из него прикладной объект можно методом формы РеквизитФормыВЗначение. Метод доступен только на сервере, поэтому код размещают в серверной процедуре.

&НаСервере

Процедура ЗаписатьОбъектНаСервере()

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

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

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

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

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

Обратите внимание на последнюю строку. После преобразования форма и объект живут раздельно: изменения в объекте не появляются на форме автоматически. Метод ЗначениеВРеквизитФормы возвращает обновлённые данные обратно в реквизит формы, чтобы пользователь увидел актуальное состояние.

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

Способ 2. ДанныеФормыВЗначение — универсальное преобразование

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

&НаСервере

Функция ПолучитьОбъектДокумента(ДанныеФормы)

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

КонецФункции

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

Этот способ удобен при построении универсальных механизмов: обработчиков печати, процедур заполнения, служебных команд, которые должны работать с формами разных объектов без привязки к конкретному виду.

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

Способ 3. Получить объект по ссылке без данных формы

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

&НаСервере

Процедура ПрочитатьИзБазы()

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

// работа с объектом из базы

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

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

Когда ПолучитьОбъект вернёт Неопределено

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

Сравнение вариантов

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

Стандартно для формы объекта; учитывает незаписанные правки пользователя; работает только в модуле формы на сервере.

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

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

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

Даёт данные из базы без привязки к форме; не видит незаписанные изменения, для нового объекта возвращает Неопределено.

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

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

Во внешних обработках и отчётах реквизиты формы создаются разработчиком вручную. Если вы добавили реквизит объектного типа, для него также применимы РеквизитФормыВЗначение и ЗначениеВРеквизитФормы — платформа сопоставит типы автоматически, если реквизит объявлен корректно (например, ДокументОбъект.РеализацияТоваровУслуг допустим только в толстом клиенте; для управляемого приложения реквизит обычно имеет тип ДанныеФормыСтруктура).

В расширениях конфигурации правила те же: заимствованная форма сохраняет свои методы, и РеквизитФормыВЗначение доступен в обработчиках расширения. Ограничение — нельзя изменять состав основного реквизита, поэтому при необходимости хранить дополнительные данные добавляют собственные реквизиты формы.

Типичные ошибки при преобразовании данных формы в объект

Самая частая ошибка — попытка вызвать РеквизитФормыВЗначение в клиентской процедуре. Платформа выдаст ошибку «Метод объекта не обнаружен» или недоступность метода в данном контексте. Решение — вынести код в процедуру с директивой &НаСервере и вызывать её из клиентской.

Вторая группа ошибок связана с потерей данных: разработчик получил объект, изменил его, записал, но забыл вернуть данные в форму через ЗначениеВРеквизитФормы. Пользователь видит устаревшие значения, а при повторной записи из формы может затереть программные изменения.

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

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

Проверка результата и отладка

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

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

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

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

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

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

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

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

Ссылка объекта
Норма

Совпадает со ссылкой на форме для существующего элемента

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

Пустая ссылка у существующего элемента или Неопределено

Данные на форме после записи
Норма

Форма отображает изменения, выполненные программно

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

Изменения есть в базе, но на форме не видны — пропущен ЗначениеВРеквизитФормы

FAQ

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

Нет. Прикладные объекты существуют только в серверном контексте. На клиенте доступны лишь данные формы и ссылка; любое преобразование требует серверной процедуры.

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

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

Как получить объект из формы списка?

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

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

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

Можно ли записать объект, полученный из формы, минуя обработчики формы?

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

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

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

Итог

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

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