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

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

Как в 1С получить ссылку на открытую форму

Как в 1С получить ссылку на открытую форму: ПолучитьФорму, ОткрытьФорму, ЭтаФорма, уникальность формы и параметры. Примеры кода на встроенном языке.

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

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

Ниже разобраны рабочие способы с примерами кода, ограничения каждого подхода и типичные ошибки, из-за которых ссылка оказывается недействительной или форма открывается повторно.

Что такое «ссылка на форму» и чем она отличается от ссылки на объект

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

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

Способ 1. Сохранить ссылку при открытии формы

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

&НаКлиенте

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

ПараметрыФормы = Новый Структура("РежимПодбора", Истина);

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

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

// ссылка на форму сохранена в переменной ФормаПодбора

ФормаПодбора.Заголовок = "Подбор товаров";

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

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

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

Порядок действий
  1. 1
    Откройте форму через ОткрытьФорму() и сохраните возвращаемое значение в переменную
  2. 2
    Если ссылка нужна долго — запишите её в реквизит формы или переменную модуля
  3. 3
    Для связи между формами передавайте текущую форму как владельца (параметр Владелец)
  4. 4
    Перед использованием проверяйте, что форма ещё открыта (свойство Открыта())

Способ 2. Использовать уникальность формы

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

&НаКлиенте

Функция ПолучитьФормуНастроек()

// один экземпляр формы на всё приложение

Возврат ОткрытьФорму("Обработка.НастройкиОбмена.Форма.ФормаНастроек",

, , "ЕдинственнаяФормаНастроек");

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

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

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

Способ 3. Передать данные без ссылки: Оповестить и ОповеститьОЗаписи

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

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

// в форме, которая изменила данные

Оповестить("ИзмененыНастройкиОбмена", НовыеНастройки, ЭтаФорма);

// в форме-получателе

&НаКлиенте

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

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

ПрочитатьНастройкиИзПараметра(Параметр);

КонецЕсли;

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

Для стандартной задачи «обновить список после записи элемента» используйте ОповеститьОбИзменении(Ссылка) или ОповеститьОЗаписиНового(Ссылка) — динамические списки реагируют на эти события автоматически, без написания обработчиков.

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

Сохранение ссылки при открытии

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

Ключ уникальности

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

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

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

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

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

Способ 4. Доступ к форме через владельца и родителя

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

&НаКлиенте

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

// ВладелецФормы — ссылка на форму, которая открыла текущую

ВладелецФормы.ВыбранныйТовар = ТекущийТовар;

Закрыть();

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

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

Проверка, что ссылка на форму ещё действительна

Хранимая ссылка на форму «протухает»: пользователь закрыл окно — и обращение к свойствам формы вызовет ошибку. Перед использованием проверяйте состояние:

Если ФормаПодбора <> Неопределено

И ФормаПодбора.Открыта() Тогда

ФормаПодбора.Активизировать();

Иначе

// форма закрыта — открываем заново

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

, ЭтаФорма);

КонецЕсли;

Метод Открыта() возвращает Истина, пока форма отображается пользователю. Также полезно обнулять сохранённую ссылку в обработчике ПередЗакрытием или ПриЗакрытии самой формы — тогда внешний код не обратится к мёртвому объекту.

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

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

Ссылка получена
Норма

Переменная содержит объект типа ФормаКлиентскогоПриложения

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

Неопределено — форма не была открыта или ключ уникальности не совпал

Форма доступна для обращения
Норма

Метод Открыта() возвращает Истина

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

Ошибка при обращении к свойствам — форма уже закрыта

Данные дошли до формы
Норма

ОбработкаОповещения срабатывает, реквизиты формы обновлены

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

Событие не приходит — проверьте имя события и наличие обработчика

Типичные ошибки и ограничения

Первая и самая частая ошибка — попытка получить форму с сервера. Вся работа с формами выполняется только в клиентском контексте (&НаКлиенте); в директиве &НаСервере методы ОткрытьФорму, Оповестить и объекты форм недоступны. Данные для открытия готовьте на сервере, а само открытие выполняйте на клиенте.

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

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

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

Можно ли получить список всех открытых форм приложения?

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

Как передать данные в уже открытую форму, если ссылки на неё нет?

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

Почему ОткрытьФорму() возвращает Неопределено?

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

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

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

Работает ли ссылка на форму в тонком и веб-клиенте одинаково?

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

Как закрыть конкретную открытую форму из другого места программы?

Нужна сохранённая ссылка: вызовите у неё метод Закрыть(), предварительно проверив Открыта(). Если ссылка не сохранялась, закрыть «чужую» форму программно нельзя — поэтому для форм, которыми нужно управлять, ссылку сохраняйте в момент открытия.

Итог

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

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