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

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

Как в 1С определить, открыта ли форма

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

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

Ключевая сложность в том, что «форма открыта» может означать разное: форма конкретного объекта, любая форма данного вида, форма с определённым ключом уникальности. Ниже разобраны рабочие сценарии с примерами кода, ограничениями каждого метода и типичными ошибками.

Проверка через метод Открыта(), когда форма доступна

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

Если ФормаДокумента <> Неопределено И ФормаДокумента.Открыта() Тогда

ФормаДокумента.Активизировать();

Иначе

ОткрытьЗначение(СсылкаНаДокумент);

КонецЕсли;

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

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

Поиск открытой формы через ПолучитьОкна()

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

Функция НайтиОткрытуюФорму(ИскомыйОбъект)

Окна = ПолучитьОкна();

Для Каждого Окно Из Окна Цикл

Для Каждого Форма Из Окно.Содержимое Цикл

Если ТипЗнч(Форма) = Тип("УправляемаяФорма")

И Форма.Объект.Ссылка = ИскомыйОбъект Тогда

Возврат Форма;

КонецЕсли;

КонецЦикла;

КонецЦикла;

Возврат Неопределено;

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

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

Более надёжный вариант фильтрации — сначала сравнить Форма.ИмяФормы с ожидаемым именем (например, "Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента"), и только потом анализировать данные объекта.

Порядок поиска формы через окна
  1. 1
    Получите массив окон вызовом ПолучитьОкна()
  2. 2
    Переберите окна и их Содержимое
  3. 3
    Сравните ИмяФормы с ожидаемым
  4. 4
    Сравните ключевые данные (ссылку, параметры формы)
  5. 5
    Верните найденную форму или Неопределено

Ключ уникальности формы как защита от дублей

Часто проверка «открыта ли форма» нужна не сама по себе, а чтобы не открыть дубликат. Платформа умеет делать это автоматически через ключ уникальности — параметр КлючУникальности в методе ОткрытьФорму() или ПолучитьФорму().

ПараметрыФормы = Новый Структура("Ключ", СсылкаНаОбъект);

ОткрытьФорму("Обработка.МояОбработка.Форма", ПараметрыФормы, , СсылкаНаОбъект.УникальныйИдентификатор());

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

Для форм объектов (документов, справочников) ключ уникальности формируется автоматически по ссылке, поэтому ОткрытьЗначение() и стандартное открытие формы объекта уже защищены от дублей. Ручной ключ нужен в основном для форм обработок и произвольных форм.

Сравнение способов проверки

Метод Открыта()

Подходит, когда есть ссылка на форму. Быстро и просто, но не работает без хранимой ссылки и недоступно на сервере.

Перебор через ПолучитьОкна()

Подходит, когда ссылки нет. Требует аккуратной фильтрации по ИмяФормы и защиты от форм без реквизита Объект.

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

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

Проверка из обычного приложения и толстого клиента

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

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

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

Оповещения как альтернатива проверке состояния

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

// В форме, изменившей данные:

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

// В форме-подписчике:

&НаКлиенте

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

Если ИмяСобытия = "ИзмененСтатусДокумента" Тогда

ЭтаФорма.Прочитать();

КонецЕсли;

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

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

Если логика строится на связке «форма-владелец хранит подчинённую форму», сохраняйте ссылку на форму при её создании через ОписаниеОповещения при открытии. Тогда проверка Открыта() займёт одну строку и не потребует перебора окон.
ПЗ
Практическое замечание

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

Первая распространённая ошибка — попытка проверить состояние формы с сервера. Управляемые формы существуют только на клиенте, и любой код вида &НаСервере, обращающийся к форме другого объекта, не сработает. Проверку выполняйте в клиентском контексте.

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

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

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

Как убедиться, что проверка работает

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

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

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

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

Повторное открытие той же формы
Норма

Активируется уже открытый экземпляр, дублей нет

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

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

Обращение к ранее закрытой форме
Норма

Открыта() возвращает Ложь, открывается новая форма

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

Ошибка обращения к объекту или устаревшие данные

Поиск через ПолучитьОкна()
Норма

Форма находится по ИмяФормы и ссылке

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

Поиск возвращает Неопределено при открытой форме или падает с ошибкой

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

Можно ли проверить, открыта ли форма, из серверной процедуры?

Нет. Управляемые формы — клиентские объекты, на сервере они не существуют. Логику проверки размещайте в клиентских процедурах, а на сервер передавайте только результат или данные для решения.

Чем Открыта() отличается от проверки ВводДоступен()?

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

Как не открывать форму обработки дважды?

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

Почему перебор ПолучитьОкна() не находит открытую форму?

Частые причины: сравнение идёт по заголовку вместо ИмяФормы, форма открыта в другом сеансе или другом пользователем (окна видны только в текущем сеансе), либо условие поиска обращается к реквизиту Объект, которого нет у данной формы, и цикл прерывается ошибкой.

Можно ли узнать, открыта ли форма у другого пользователя?

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

Итог

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

При наличии ссылки на форму используйте Открыта() с предварительной проверкой на Неопределено. Без ссылки ищите форму перебором ПолучитьОкна() по ИмяФормы и данным объекта. Для защиты от дублей надёжнее всего ключ уникальности при ОткрытьФорму(). Все проверки выполняются только на клиенте.