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

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

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

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

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

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

Как устроена идентификация форм в 1С

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

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

Способ 1. Уникальный ключ при открытии формы

Самый чистый подход — не проверять открытость вручную, а поручить это платформе. Метод ОткрытьФорму принимает третьим параметром уникальный ключ. Если форма с таким ключом уже открыта, новая не создаётся — активируется существующая.

КлючУникальности = "МояОбработка_ОсновнаяФорма";

ОткрытьФорму("Обработка.МояОбработка.Форма.Форма", , , КлючУникальности);

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

Проверка результата: после вызова ОткрытьФорму повторно в интерфейсе должно остаться одно окно обработки. Если окон стало два — ключ передан неверно или в разных местах кода используются разные значения ключа.

Порядок действий с уникальным ключом
  1. 1
    Определите, что однозначно идентифицирует форму: сама обработка или связанный объект
  2. 2
    Сформируйте строку ключа, например "Обработка_X_" + Строка(Объект.УникальныйИдентификатор())
  3. 3
    Передайте ключ четвёртым параметром в ОткрытьФорму во всех местах, где форма открывается
  4. 4
    Проверьте: повторный вызов активирует существующее окно, а не создаёт новое

Способ 2. Перебор окон клиентского приложения

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

Функция ФормаОбработкиОткрыта(ИмяОбработки)

Для Каждого Окно Из ОкнаКлиентскогоПриложения Цикл

Если Окно.Содержимое.Количество() > 0 Тогда

Форма = Окно.Содержимое[0];

Если СтрНайти(Форма.ИмяФормы, ИмяОбработки) > 0 Тогда

Возврат Истина;

КонецЕсли;

КонецЕсли;

КонецЦикла;

Возврат Ложь;

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

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

Ограничение способа: он работает только на клиенте и «видит» окна текущего сеанса. На сервере коллекция окон недоступна, поэтому функцию размещают в клиентском модуле.

1c
Для Каждого Окно Из ОкнаКлиентскогоПриложения Цикл
    Для Каждого Форма Из Окно.Содержимое Цикл
        Если Форма.ИмяФормы = "Обработка.МояОбработка.Форма.Форма" Тогда
            Окно.Активизировать();
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Способ 3. Хранение ссылки на форму в переменной

Если ваш код сам открывает форму, проще всего сохранить возвращаемое значение ОткрытьФорму — это и есть объект формы. У него есть метод Открыта(), который возвращает Истина, пока форма не закрыта.

// При открытии

ФормаОбработки = ОткрытьФорму("Обработка.МояОбработка.Форма.Форма");

// При проверке

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

ФормаОбработки.Активизировать();

Иначе

ФормаОбработки = ОткрытьФорму("Обработка.МояОбработка.Форма.Форма");

КонецЕсли;

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

Типичная ошибка — проверять только ФормаОбработки <> Неопределено. Переменная продолжает ссылаться на объект формы даже после её закрытия, поэтому без вызова Открыта() проверка неполна.

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

Способ 4. Обработка исключения при повторном открытии

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

Форма = ПолучитьФорму("ВнешняяОбработка.МояОбработка.Форма.Форма", , , "Ключ1");

Если Не Форма.Открыта() Тогда

Форма.Открыть();

Иначе

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

КонецЕсли;

Такой подход удобен в толстом клиенте и в модальных сценариях. В тонком и веб-клиенте предпочтительнее асинхронные методы (НачатьОткрытиеФормы в новых версиях платформы), но принцип уникального ключа сохраняется.

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

Уникальный ключ в ОткрытьФорму

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

Перебор ОкнаКлиентскогоПриложения

Находит любые открытые формы, включая открытые сторонним кодом. Только на клиенте, требует аккуратного сравнения имён

Ссылка на форму + Открыта()

Самый быстрый и надёжный, если открытие делает ваш код. Не работает для форм, открытых извне

ПолучитьФорму с уникальностью

Удобен для внешних обработок и толстого клиента, сочетает получение и проверку в одном вызове

Особенности для внешних обработок и веб-клиента

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

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

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

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

Для отладки выведите в окно сообщений имена всех открытых форм: переберите ОкнаКлиентскогоПриложения и содержимое каждого окна. Это покажет точное значение ИмяФормы, которое нужно использовать в сравнении, и поможет обнаружить несовпадение регистра или лишние символы.

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

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

Повторный вызов открытия
Норма

Активируется существующее окно, количество окон не растёт

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

Появляется вторая копия формы — ключ не совпадает или не передан

Закрытие формы пользователем
Норма

Следующий вызов открывает форму заново без ошибок

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

Ошибка обращения к закрытой форме — не проверяется Открыта()

Имя формы в сравнении
Норма

Точное совпадение с полным именем из отладочного вывода

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

Ложные срабатывания или промахи из-за подстроки и регистра

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

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

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

Чем УникальныйКлюч отличается от ИмяФормы?

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

Почему ОткрытьФорму всё равно создаёт вторую копию, хотя ключ задан?

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

Как активировать уже открытую форму вместо открытия новой?

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

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

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

Что делать, если форма открывается из подсистемы БСП «Дополнительные отчеты и обработки»?

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

Итог

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

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