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