Как получить параметры формы при её повторном открытии в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

В этой статье мы подробно разберем, почему ПриПовторномОткрытии не видит новые параметры «напрямую», и рассмотрим профессиональные способы решения этой задачи.

Почему параметры «застревают»?

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

Важный нюанс: Коллекция ЭтаФорма.Параметры внутри этого события будет содержать ровно те значения, которые были переданы при самом первом открытии. Новая структура параметров, переданная во втором вызове, просто не доходит до объекта формы. Это архитектурное ограничение управляемых форм.

Рассмотрим по шагам основные способы решения этой проблемы.

Способ 1. Использование механизма оповещений (Оповестить и ОбработкаОповещения)

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

В исходной форме (откуда открываем) пишем следующий код:


// Сначала пробуем открыть форму (если не открыта — откроется, если открыта — активируется)
ПараметрыФормы = Новый Структура("Номенклатура", ТекущаяНоменклатура);
ОткрытьФорму("ВнешнийОтчет.МойОтчет.Форма.ФормаОтчета", ПараметрыФормы, ЭтаФорма, "УникальныйКлючМоейФормы");

// Сразу после этого посылаем оповещение с данными
Оповестить("ОбновитьДанныеОтчета", ПараметрыФормы, "ИнициаторЗаказ");

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


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    
    // Проверяем, что это именно наше событие
    Если ИмяСобытия = "ОбновитьДанныеОтчета" Тогда
        // Здесь мы получаем доступ к новым данным в переменной "Параметр"
        НоваяНоменклатура = Параметр.Номенклатура;
        
        // Вызываем серверный метод для переформирования данных
        ОбновитьОтчетНаСервере(НоваяНоменклатура);
    КонецЕсли;
    
КонецПроцедуры

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

Способ 2. Явный вызов экспортного метода через ПолучитьФорму

Если вы хотите иметь более строгий контроль и не использовать глобальные оповещения, которые слышат все открытые окна, можно использовать метод ПолучитьФорму(). Рассмотрим этот алгоритм подробнее.

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

В вызывающем модуле:


ПараметрыДляПередачи = Новый Структура("Товар", Объект.Товары.Получить(0).Номенклатура);
// Получаем экземпляр (если форма открыта, вернется существующая)
ФормаПриемник = ПолучитьФорму("Справочник.Номенклатура.Форма.ФормаСписка", ПараметрыДляПередачи, ЭтаФорма, "МойID");

// Проверяем, открыта ли она уже. Если да — вызываем экспортный метод
Если ФормаПриемник.Открыта() Тогда
    ФормаПриемник.ОбновитьКонтент(ПараметрыДляПередачи);
КонецЕсли;

ФормаПриемник.Открыть();

В модуле открываемой формы (ФормаПриемник) нужно создать процедуру с ключевым словом Экспорт:


&НаКлиенте
Процедура ОбновитьКонтент(НовыеПараметры) Экспорт
    // Обрабатываем полученную структуру
    Сообщить("Получены новые данные: " + НовыеПараметры.Товар);
    // Выполняем действия по обновлению интерфейса
КонецПроцедуры

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

Способ 3. Ключ уникальности (если нужно открывать несколько копий)

Иногда задача стоит иначе: пользователь хочет видеть отчет по Номенклатуре А и отчет по Номенклатуре Б в разных окнах одновременно. В этом случае проблема «повторного открытия» исчезает, так как нам нужно создавать новый экземпляр формы каждый раз.

Для этого используется параметр УникальныйИдентификатор (или КлючУникальности). Рассмотрим пример:


// Используем ссылку на объект как ключ уникальности. 
// Каждое новое значение ссылки будет открывать отдельное окно.
Ключ = ТекущаяСтрока.Номенклатура; 
ОткрытьФорму("Обработка.ПросмотрДанных.Форма", Параметры, ЭтаФорма, Ключ);

В этом случае при нажатии на другую номенклатуру 1С увидит, что формы с таким «Ключом» еще нет, и создаст новую, вызвав ПриСозданииНаСервере, где вы сможете штатно обработать параметры.

Способ 4. Обращение к владельцу формы (ВладелецФормы)

Разберем ситуацию, упомянутую в обсуждении, когда подчиненная форма при повторном открытии «заглядывает» в родительское окно. В событии ПриПовторномОткрытии можно обратиться к свойству ВладелецФормы.


&НаКлиенте
Процедура ПриПовторномОткрытии()
    // Пытаемся получить данные напрямую из элементов формы владельца
    Попытка
        ВыбраннаяНоменклатура = ВладелецФормы.Элементы.Список.ТекущиеДанные.Ссылка;
        // Дальнейшая логика обновления
    Исключение
        // Обработка случая, если владелец не тот или форма изменилась
    КонецПопытки;
КонецПроцедуры

Важное предостережение: Проанализируем этот подход. Хотя он кажется простым, в профессиональной разработке это считается «плохим тоном» (антипаттерн). Если вы измените имя таблицы в основной форме или переименуете реквизит, подчиненная форма «сломается». Старайтесь передавать данные в форму, а не заставлять форму «шпионить» за владельцем.

Итоги и рекомендации

Подведем итог нашему исследованию. Для корректной работы с повторным открытием форм рекомендуется следовать этим правилам:

  1. Если вам нужно обновить данные в уже существующем окне — используйте Оповестить() или экспортный метод через ПолучитьФорму().
  2. Если данные объемные (таблицы значений, файлы) — помещайте их во Временное хранилище, а через параметры или оповещение передавайте только АдресХранилища.
  3. Помните, что процедура ПриПовторномОткрытии работает только на клиенте. Любые тяжелые расчеты или запросы к БД должны быть вынесены в серверные методы (&НаСервере).
  4. Используйте КлючУникальности, если бизнес-логика предполагает работу с несколькими объектами одновременно в разных окнах.

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

← На главную