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

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

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

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

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

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

Ниже разобраны основные способы обращения к другой форме: метод ОткрытьФорму(), передача параметров, работа с ЭтаФорма.Владелец, механизм оповещений Оповестить() и ОповеститьОВыборе(), а также типичные ошибки, из-за которых код «не видит» нужную форму.

Открытие формы через ОткрытьФорму()

Основной способ обратиться к другой форме — метод глобального контекста ОткрытьФорму(). Он принимает имя формы, структуру параметров, владельца, уникальность и другие аргументы, а возвращает ссылку на открытую форму (объект типа УправляемаяФорма).

Имя формы строится по шаблону: Справочник.Номенклатура.Форма.ФормаЭлемента или Обработка.МояОбработка.Форма для основной формы. Если нужна конкретная неосновная форма, указывается её имя: Документ.РеализацияТоваров.Форма.ФормаПодбора.

&НаКлиенте

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

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

ПараметрыФормы.Вставить("Ключ", ТекущийЭлементСправочника);

ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаЭлемента",

ПараметрыФормы, ЭтаФорма);

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

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

bsl
Форма = ОткрытьФорму("Справочник.Контрагенты.Форма.ФормаЭлемента", ПараметрыФормы, ЭтаФорма, Новый УникальныйИдентификатор);

Передача параметров и получение данных из открытой формы

Параметры передаются вторым аргументом в виде структуры. В открываемой форме они доступны через Параметры в обработчике ПриСозданииНаСервере. Стандартные параметры (Ключ, Отбор, РежимВыбора) платформа обрабатывает сама, произвольные — разработчик читает вручную.

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Параметры.Свойство("Организация") Тогда

ЭтотОбъект.Организация = Параметры.Организация;

КонецЕсли;

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

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

Обращение к родительской форме через Владелец

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

&НаКлиенте

Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)

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

ЭтаФорма.Владелец.ОбновитьДанныеСписка();

КонецЕсли;

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

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

Обмен данными через оповещения

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

// В форме-источнике

&НаКлиенте

Процедура ПослеЗаписи(ПараметрыЗаписи)

Оповестить("ЗаписанКонтрагент", Объект.Ссылка, ЭтаФорма);

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

// В форме-приёмнике

&НаКлиенте

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

Если ИмяСобытия = "ЗаписанКонтрагент" Тогда

Элементы.Список.Обновить();

КонецЕсли;

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

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

Порядок действий: вернуть значение из дочерней формы
  1. 1
    В родительской форме создайте ОписаниеОповещения с именем процедуры-обработчика
  2. 2
    Вызовите ОткрытьФорму() с параметрами, владельцем и этим описанием оповещения
  3. 3
    В дочерней форме по команде вызовите Закрыть(ВыбранноеЗначение)
  4. 4
    В процедуре-обработчике родительской формы примите значение и обработайте его
  5. 5
    Проверьте, что обработчик вызывается и значение не равно Неопределено

Как получить уже открытую форму

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

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

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

Сравнение способов обращения к форме

ОткрытьФорму() с параметрами

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

ЭтаФорма.Владелец

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

Оповестить()

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

ОписаниеОповещения + Закрыть()

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

Тонкий, толстый и веб-клиент: что учитывать

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

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

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

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

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

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

Если оповещение «не доходит», проверьте три вещи: совпадает ли строка имени события посимвольно (регистр не важен, но лишние пробелы ломают сравнение), открыта ли форма-приёмник в момент вызова, не перекрыт ли обработчик ОбработкаОповещения в расширении или подписке.

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

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

Форма открылась
Норма

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

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

Ошибка «Форма не найдена» — проверьте полное имя формы

Параметры переданы
Норма

В ПриСозданииНаСервере Параметры.Свойство() возвращает Истина

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

Свойство отсутствует — проверьте имя ключа в структуре параметров

Оповещение доставлено
Норма

ОбработкаОповещения срабатывает с нужным ИмяСобытия

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

Обработчик молчит — форма-приёмник закрыта или имя события не совпадает

Значение возвращено
Норма

Процедура из ОписаниеОповещения получила значение после Закрыть()

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

Пришло Неопределено — форма закрыта крестиком без передачи значения

Итог

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

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

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

Как открыть форму списка с отбором по конкретному полю?

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

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

Нет. Открытие и интерактивное взаимодействие с формами доступно только на клиенте. На сервере можно подготовить данные, поместить их во временное хранилище и вернуть адрес хранилища клиенту, который затем передаст его в параметры открываемой формы.

Почему Оповестить() срабатывает в нескольких формах сразу?

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

Как передать в форму таблицу значений или массив?

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

Чем ОповеститьОВыборе() отличается от Оповестить()?

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

Как закрыть дочернюю форму из родительской?

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