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