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

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

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

Как в 1С получить список открытых форм: метод ПолучитьОкна, обход форм, поиск открытой формы объекта, особенности тонкого клиента и управляемого приложения.

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

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

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

Как устроены окна и формы в клиентском приложении

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

Объект формы, полученный таким способом, — это управляемая форма со всеми её свойствами: ИмяФормы, Заголовок, КлючУникальности, Параметры. По этим свойствам можно идентифицировать нужную форму среди всех открытых.

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

Базовый пример обхода всех открытых окон и вывода информации о формах выглядит так:

&НаКлиенте

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

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

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

Форма = Окно.ПолучитьСодержимое();

Если Форма = Неопределено Тогда

Продолжить;

КонецЕсли;

Сообщить("Форма: " + Форма.ИмяФормы + " | Заголовок: " + Окно.Заголовок);

КонецЦикла;

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

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

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

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

Поиск конкретной открытой формы

На практике чаще нужен не полный список, а ответ на вопрос «открыта ли форма конкретного документа». Для этого перебор окон комбинируют с проверкой параметров формы:

&НаКлиенте

Функция НайтиФормуДокумента(СсылкаНаДокумент)

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

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

Форма = Окно.ПолучитьСодержимое();

Если Форма = Неопределено Тогда

Продолжить;

КонецЕсли;

Если Форма.Параметры.Свойство("Ключ")

И Форма.Параметры.Ключ = СсылкаНаДокумент Тогда

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

КонецЕсли;

КонецЦикла;

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

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

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

Активация найденной формы

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

Альтернатива: уникальность при открытии формы

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

&НаКлиенте

Процедура ОткрытьДокументБезДубликата(Ссылка)

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

ОткрытьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента",

ПараметрыФормы, , Ссылка.УникальныйИдентификатор());

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

Это предпочтительный способ, потому что проверку выполняет платформа на уровне ядра — без обхода коллекций и без риска пропустить форму в нестандартном окне.

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

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

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

Уникальность в ОткрытьФорму()

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

Оповестить() и ОбработкаОповещения

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

Обновление и закрытие открытых форм

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

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

Особенности и ограничения

Метод ПолучитьОкна() доступен только на клиенте — в тонком, толстом и веб-клиенте. В серверном контексте и во внешнем соединении его вызов приведёт к ошибке. Если логика должна работать и на сервере, разделяйте код: серверная часть готовит данные, клиентская работает с окнами.

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

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

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

Проверка результата и отладка

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

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

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

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

Количество форм в списке
Норма

Совпадает с числом открытых окон с формами

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

В списке лишние пустые элементы или формы пропущены

Поиск формы по ключу объекта
Норма

Находится ровно одна форма открытого объекта

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

Находится форма другого объекта или ничего не находится при открытой форме

Повторное открытие с уникальностью
Норма

Активируется существующая форма

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

Открывается вторая копия формы того же объекта

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

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

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

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

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

Почему ПолучитьСодержимое() возвращает Неопределено?

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

Как обновить данные во всех открытых формах списка?

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

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

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

Работает ли перебор окон в веб-клиенте?

Да, метод доступен, но поведение активации и модальных окон в браузере может отличаться от тонкого клиента. Код с активацией окон следует тестировать именно в целевом клиенте.

Итог

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

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