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

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

Как обратиться к реквизиту другой формы в 1С

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

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

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

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

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

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

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

Важно понимать различие между реквизитом формы и реквизитом объекта. Если форма редактирует документ, то данные документа доступны через реквизит формы типа ДанныеФормыСтруктура (обычно «Объект»), и работать с ним на сервере нужно через преобразование РеквизитФормыВЗначение. Собственные реквизиты формы (добавленные разработчиком) доступны только в контексте этой формы либо через переданную ссылку на форму.

Способ 1. Обращение через Владельца формы

Самый простой случай: форма А открывает форму Б, и из формы Б нужно прочитать или изменить реквизит формы А. Платформа автоматически заполняет у формы Б свойство Владелец — это ссылка на форму А. Обращение выглядит так:

&НаКлиенте

Процедура КомандаПередать(Команда)

Если ВладелецФормы <> Неопределено Тогда

ВладелецФормы.ВыбранноеЗначение = Значение;

ВладелецФормы.ОбновитьОтображениеДанных();

КонецЕсли;

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

Через ВладелецФормы доступны реквизиты, команды и экспортные процедуры клиентского модуля формы-владельца. Это работает только на клиенте: на сервере свойство ВладелецФормы содержит не форму, а её описание, и обратиться к реквизитам через него нельзя.

Условия применения: форма должна быть реально открыта из формы-владельца (при открытии из командного интерфейса ВладелецФормы будет Неопределено), а форма-владелец должна быть ещё открыта. Если пользователь закрыл родительскую форму, обращение вызовет ошибку — поэтому проверка на Неопределено обязательна, а для надёжности стоит обернуть обращение в попытку.

Способ 2. Передача данных через Оповестить

Механизм оповещений — рекомендуемый способ, когда форма должна сообщить другой форме о событии и передать данные, не зная о её внутреннем устройстве. Форма-источник вызывает Оповестить, форма-приёмник реализует обработчик ОбработкаОповещения.

// Форма-источник (например, форма подбора)

&НаКлиенте

Процедура Выбрать(Команда)

Оповестить("ПодборНоменклатуры", ВыбраннаяНоменклатура, ЭтотОбъект);

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

// Форма-приёмник (например, форма документа)

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ПодборНоменклатуры" Тогда

ДобавитьСтрокуТовара(Параметр);

КонецЕсли;

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

Преимущество подхода — слабая связанность: форма-источник не обязана знать, открыта ли форма-приёмник и сколько таких форм существует. Все открытые формы с подходящим обработчиком получат оповещение. Это же и риск: если имя события выбрано слишком общее, обработку выполнят посторонние формы. Используйте уникальные префиксы имён событий и проверяйте параметр Источник.

Для модальных сценариев вместо Оповестить лучше подходит ОповеститьОЗавершении с описанием оповещения: форма открывается с ОписаниеОповещенияОЗакрытии, а при закрытии вызывается указанная процедура с результатом. Это стандартный паттерн для диалогов выбора значения.

Порядок действий для передачи через оповещение
  1. 1
    В форме-источнике вызовите Оповестить с уникальным именем события и данными в параметре
  2. 2
    В форме-приёмнике создайте обработчик ОбработкаОповещения
  3. 3
    Отфильтруйте события по имени и при необходимости по источнику
  4. 4
    Обновите реквизиты формы-приёмника и вызовите Модифицированность или ОбновитьОтображениеДанных
  5. 5
    Проверьте поведение при закрытой форме-приёмнике — ошибок быть не должно

Способ 3. Передача через параметры при открытии формы

Если данные нужны форме один раз — в момент открытия, — правильнее передать их через параметры, а не обращаться к реквизитам после открытия. Параметры формируются в структуре и передаются в ОткрытьФорму:

&НаКлиенте

Процедура ОткрытьПодбор(Команда)

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Организация", Объект.Организация);

ПараметрыФормы.Вставить("ДатаДокумента", Объект.Дата);

ОткрытьФорму("Обработка.Подбор.Форма.ФормаПодбора", ПараметрыФормы, ЭтотОбъект);

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

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

Третий параметр ОткрытьФорму — владелец. Передавая ЭтотОбъект, вы автоматически связываете формы, и открытая форма сможет обратиться к вашей через ВладелецФормы, как описано в первом способе. Четвёртым параметром можно передать уникальность: тогда повторный вызов не откроет дубликат, а активизирует уже открытую форму.

Способ 4. Обращение через ПолучитьФорму и уникальный идентификатор

Когда формы не связаны отношением владения, но у вас есть ссылка на объект данных (например, ссылка на документ), можно получить форму этого объекта методом ПолучитьФорму и обратиться к её реквизитам:

&НаКлиенте

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

ФормаДокумента = ПолучитьФорму("Документ.РеализацияТоваров.ФормаОбъекта",

Новый Структура("Ключ", ДокументСсылка));

Если ФормаДокумента.Открыта() Тогда

ТекущийКонтрагент = ФормаДокумента.Объект.Контрагент;

КонецЕсли;

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

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

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

Сравнение способов

ВладелецФормы

Подходит для простой пары «родитель — подчинённая». Ограничение: только клиент и только если форма открыта из владельца.

Оповестить / ОбработкаОповещения

Универсальный обмен событиями между любыми открытыми формами. Ограничение: приёмник должен быть открыт в момент оповещения.

Параметры открытия

Передача данных один раз при создании формы. Не подходит для обратной связи после открытия.

ПолучитьФорму по ключу

Доступ к форме конкретного объекта без связи владения. Ограничение: риск создать скрытый экземпляр формы.

Работа с реквизитом объекта на сервере

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

Для серверной логики реквизит преобразуют в прикладной объект, работают с ним и при необходимости возвращают обратно:

&НаСервере

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

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

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

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

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

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

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

Первая ошибка — обращение к ВладелецФормы без проверки на Неопределено. Форма, открытая из интерфейса, а не из другой формы, вызовет исключение. Всегда проверяйте владельца и дополнительно оборачивайте обращение в Попытка/Исключение, если закрытие родительской формы вероятно.

Вторая ошибка — попытка вызвать серверную процедуру чужой формы с клиента. Экспортные серверные процедуры модуля формы недоступны через ссылку на форму: через ВладелецФормы можно вызывать только клиентские экспортные процедуры. Серверную логику выносите в общий модуль и вызывайте её из обеих форм независимо.

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

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

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

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

После внедрения обмена данными проверьте сценарий целиком: откройте обе формы, выполните передачу значения и убедитесь, что в форме-приёмнике изменился реквизит и интерфейс обновился. Если данные переданы, но на экране не видно изменений, вызовите ОбновитьОтображениеДанных или установите признак Модифицированность.

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

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

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

Передача значения в открытую форму
Норма

Реквизит приёмника изменился, отображение обновилось

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

Значение не меняется или форма падает с ошибкой

Закрытая форма-приёмник
Норма

Оповещение игнорируется без ошибок

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

Исключение при обращении к форме

Открытие без владельца
Норма

Проверка на Неопределено пропускает обращение

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

Ошибка «Поле объекта не обнаружено»

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

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

Нет. После закрытия форма уничтожается, и любые ссылки на неё становятся недействительными. Если данные нужны после закрытия, передавайте их заранее через оповещение о закрытии, временное хранилище или сохраняйте в базу данных.

Как передать данные из формы списка в форму элемента?

Если элемент открывается из списка стандартно, форма элемента уже получает ключ записи. Для дополнительных данных используйте Оповестить из формы списка либо открывайте форму элемента вручную через ОткрытьФорму с параметрами и владельцем.

Почему ВладелецФормы равен Неопределено?

Форма открыта не из другой формы, а из командного интерфейса, либо при вызове ОткрытьФорму не был передан третий параметр-владелец. Передавайте ЭтотОбъект владельцем явно.

Можно ли вызвать процедуру модуля другой формы?

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

Как вернуть большой объём данных из подчинённой формы?

Поместите данные во временное хранилище с привязкой к УникальныйИдентификатор родительской формы и передайте родителю только адрес хранилища через оповещение или параметр закрытия. Родительская форма заберёт данные из хранилища на сервере.

Работает ли обращение к реквизитам формы в тонком и веб-клиенте?

Механизмы ВладелецФормы, Оповестить и параметры открытия работают во всех клиентах. Ограничения касаются только недоступных в конкретном клиенте типов данных и директив компиляции — проверяйте контекстные директивы процедур.

Итог

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

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