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