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