Часто при разработке на платформе 1С:Предприятие возникает задача: как сделать так, чтобы пользователь не мог открыть несколько одинаковых окон одной и той же обработки. Если пользователь по ошибке кликнет по команде открытия несколько раз, откроется множество копий формы, в которых он начнет путаться. Наша цель — сделать так, чтобы при попытке повторного открытия происходила активация (переход на передний план) уже открытого окна, а не создание нового.
Разберем эту задачу по шагам и проанализируем несколько способов её решения: от использования стандартных механизмов платформы до программного перебора окон.
Самый правильный и стандартный подход — использование параметра уникальности при вызове метода ОткрытьФорму(). По умолчанию встроенные обработки должны открываться в единственном экземпляре, если вызывать их из стандартного интерфейса. Но если форма открывается программно (например, из общей команды), платформе нужно явно указать ключ уникальности.
Рассмотрим синтаксис метода. Четвертым параметром в метод передается ключ уникальности. Это может быть произвольное значение: строка, число или УИД. Если платформа находит уже открытое окно с таким же ключом уникальности, она просто активирует его.
// Открывает новое окно, так как Уникальность = Истина (не искать форму)
ОткрытьФорму("Обработка.МояОбработка.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, Истина, ПараметрыВыполненияКоманды.Окно, ПараметрыВыполненияКоманды.НавигационнаяСсылка);
// Открывает уникальное окно по переданному ключу
ОткрытьФорму("Обработка.МояОбработка.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, "УникальныйКлючМоейОбработки", ПараметрыВыполненияКоманды.Окно, ПараметрыВыполненияКоманды.НавигационнаяСсылка);
Важная ошибка, которую часто допускают: попытка использовать генерацию нового уникального идентификатора в параметрах вызова.
// НЕПРАВИЛЬНО: каждый раз генерируется новый УИД, будут открываться дубли!
ОткрытьФорму("Обработка.МояОбработка.Форма", ПараметрыФормы, Источник, Новый УникальныйИдентификатор(), Окно, НавигационнаяСсылка);
Если вы хотите использовать УИД в качестве ключа, зафиксируйте его в виде строки или передавайте жестко заданную строку (хардкод), например "ФормаОбработкиОсновная".
Проанализируем ситуацию: вы вызываете ОткрытьФорму(), не передаете никаких ключей, или передаете один и тот же ключ, а форма все равно открывается бесконечное количество раз. Почему это происходит?
Дело может быть в ключевых параметрах формы. Зайдите в модуль формы обработки, перейдите на вкладку "Параметры". Если у какого-либо параметра установлена галочка Ключевой параметр, платформа 1С меняет логику контроля уникальности. Форма будет считаться уникальной только в разрезе значений этого параметра.
Посмотрим на пример. Если ключевым является параметр Организация, то вызов формы с параметром ООО "Ромашка" и вызов этой же формы с параметром ООО "Василек" откроют два разных окна. Если же вы открываете форму вообще без передачи этого параметра, механизм уникальности может ломаться, и система будет каждый раз создавать новую форму. Внимательно проверьте параметры вашей формы — возможно, лишняя галочка мешает нормальной работе окна.
Если вы не используете метод ОткрытьФорму(), а обработка открывается пользователем напрямую из подсистемы (через интерфейс), мы можем принудительно задать ключ уникальности при создании формы на сервере.
Рассмотрим, как это сделать. В обработчике ПриСозданииНаСервере пропишите фиксированное значение для свойства формы КлючУникальности:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Жестко фиксируем ключ уникальности для текущей формы
ЭтаФорма.КлючУникальности = "ЕдинственныйЭкземплярОбработки";
КонецПроцедуры
Теперь платформа будет знать, что у данного окна есть конкретный ключ. При повторном клике пользователя в интерфейсе система найдет окно с этим ключом и просто выведет его на передний план.
Выясним, как быть, если у нас внешняя обработка (для которых механизмы уникальности 1С часто работают нестабильно из-за генерации временных файлов), или если другие способы по каким-то причинам недоступны.
Мы можем использовать коллекцию ОкнаКлиентскогоПриложения и перебрать все открытые на данный момент формы. Если форма с нужным именем найдена — мы её активизируем и отменяем открытие новой.
Реализуем данный метод в событии ПриОткрытии клиентского модуля формы:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Получаем полное имя текущей формы
ИмяИскомойФормы = ЭтаФорма.ИмяФормы;
// Перебираем все открытые окна в клиентском приложении
Для Каждого ОткрытоеОкно Из ПолучитьОкна() Цикл
Для Каждого ЧужаяФорма Из ОткрытоеОкно.Содержимое Цикл
// Если находим окно с таким же именем и это не текущее окно
Если ЧужаяФорма.ИмяФормы = ИмяИскомойФормы И ЧужаяФорма <> ЭтаФорма Тогда
ЧужаяФорма.Активизировать(); // Выводим найденное окно вперед
Отказ = Истина; // Отменяем открытие нового окна
Возврат;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Данный метод участники форума часто называют "костылем", так как перебор всех окон клиента может потребовать ресурсов (хотя на практике это происходит мгновенно). Однако для самописных конфигураций или внешних обработок это самое надежное решение, которое гарантирует 100% результат.
В некоторых случаях множественное открытие окон провоцируется неправильно заданным режимом открытия. Проверьте параметр РежимОткрытияОкна в свойствах самой формы (или передайте его в структуре параметров вызова формы).
Если задать РежимОткрытияОкна.Независимый, система будет более корректно отрабатывать логику уникальности стандартного интерфейса. Это особенно полезно при открытии отчетов и сложных аналитических обработок.
Подведем итог: Платформа 1С опирается на совокупность факторов для определения уникальности: полное имя формы, значения ключевых параметров и переданный параметр уникальности. Если у вас открываются дубли, в первую очередь откажитесь от динамической генерации УИДов в параметрах, проверьте галочки "Ключевой параметр" в свойствах формы, а в крайнем случае — используйте программный перебор через ПолучитьОкна().