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

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

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

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

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

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

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

Что такое активная форма и чем она отличается от ЭтаФорма

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

Переменная ЭтаФорма — это не «активная форма приложения», а ссылка на ту форму, в модуле которой выполняется код. Она доступна только внутри модуля формы (в клиентских и серверных процедурах с директивами &НаКлиенте, &НаСервере) и всегда указывает на «свою» форму, независимо от того, активна она у пользователя или нет.

Как обратиться к текущей форме из её модуля

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

bsl
&НаКлиенте
Процедура КомандаОбновить(Команда)
	ЭтаФорма.Заголовок = "Документ обработан";
	ЭтаФорма.Элементы.ГруппаИтоги.Видимость = Истина;
	ЭтаФорма.Прочитать(); // перечитать данные объекта
КонецПроцедуры

В серверных процедурах без контекста формы (&НаСервереБезКонтекста) переменная ЭтаФорма недоступна — форма туда не передаётся. Если нужно работать с данными формы на сервере, используйте процедуры &НаСервере или передавайте нужные параметры явно.

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

bsl
// В модуле формы
&НаКлиенте
Процедура ПриОткрытии(Отказ)
	ОбщийКлиентМодуль.НастроитьФормуДокумента(ЭтаФорма);
КонецПроцедуры

// В общем модуле (Клиент)
Процедура НастроитьФормуДокумента(Форма) Экспорт
	Форма.Элементы.Комментарий.ПодсказкаВвода = "Заполните при необходимости";
КонецПроцедуры

Как получить открытую форму из другой формы или модуля

Когда нужно обратиться к форме, открытой ранее, — например, из формы списка обновить открытую форму элемента, — прямого поиска «по активности» не делают. Используются три рабочих подхода.

Механизм оповещений

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

bsl
// Форма-источник
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
	Оповестить("ЗаписанЭлементСправочника", ПараметрыЗаписи.Ключ, ЭтаФорма);
КонецПроцедуры

// Форма-получатель
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
	Если ИмяСобытия = "ЗаписанЭлементСправочника" Тогда
		Элементы.Список.Обновить();
	КонецЕсли;
КонецПроцедуры

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

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

bsl
&НаКлиенте
Процедура ПодобратьТовар(Команда)
	Описание = Новый ОписаниеОповещения("ПослеПодбораТовара", ЭтаФорма);
	ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора", , ЭтаФорма, , , , Описание);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПодбораТовара(Результат, ДопПараметры) Экспорт
	Если Результат <> Неопределено Тогда
		Объект.Товар = Результат;
	КонецЕсли;
КонецПроцедуры

Поиск по уникальности формы

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

Как узнать активное окно и активную форму в толстом клиенте

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

bsl
// Только толстый клиент, обычное приложение
Окно = АктивноеОкно();
Если Окно <> Неопределено Тогда
	АктивнаяФорма = Окно.ПолучитьСодержимое();
	Если АктивнаяФорма <> Неопределено Тогда
		Сообщить("Активна форма: " + АктивнаяФорма);
	КонецЕсли;
КонецЕсли;

В управляемом приложении этот подход работать не будет — коллекция окон там недоступна в прикладном коде. Если конфигурация работает в обоих режимах, такой код нужно оборачивать проверкой режима запуска или директивами препроцессора #Если ТолстыйКлиентОбычноеПриложение Тогда.

Как определить, что форма стала активной

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

Для элементов формы активизация отслеживается штатно. Например, ПриАктивизацииСтроки динамического списка позволяет реагировать на выбор пользователя и обновлять связанные данные — это частая практическая потребность, которую ошибочно пытаются решить через «активную форму».

Маршрут решения

Как выбрать способ

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

Частые ошибки при работе с активной формой

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

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

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

Как проверить, что всё работает

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

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

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

Оповещение между формами
Норма

Форма-получатель реагирует на событие, при закрытом получателе ошибок нет

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

Ошибка обращения к форме или отсутствие реакции при совпадении имени события

Обращение через ЭтаФорма
Норма

Реквизиты и элементы формы изменяются из процедур модуля

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

Ошибка «Переменная не определена» — значит, код в контексте без формы

АктивноеОкно() в толстом клиенте
Норма

Возвращается окно, содержимое — открытая форма

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

Окно = Неопределено или метод недоступен (управляемое приложение)

Итог

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

Внутри модуля формы всегда используйте ЭтаФорма. Между формами в управляемом приложении обменивайтесь через Оповестить/ОбработкаОповещения и ОписаниеОповещения — прямого доступа к «активной форме» там нет. АктивноеОкно() работает только в толстом клиенте обычного приложения. Не храните ссылки на чужие формы — они могут быть закрыты.

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

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

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

Почему ЭтаФорма недоступна в общем модуле?

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

Как из фонового задания сообщить форме о завершении?

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

Чем отличается Владелец формы от активной формы?

Владелец — это форма, указанная при открытии как родительская; она задаёт связь и время жизни (при закрытии владельца закрываются подчинённые формы). Активная форма — та, что имеет фокус в данный момент. Это независимые понятия: активной может быть любая форма, не связанная с владельцем.

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

В форме элемента после записи вызовите ОповеститьОбИзменении(Ссылка) или Оповестить с собственным именем события. Стандартные формы списков автоматически реагируют на ОповеститьОбИзменении и обновляют строку; для произвольных списков добавьте обработчик ОбработкаОповещения с вызовом Элементы.Список.Обновить().