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

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

Как передать параметр в уже открытую форму в 1С

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

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

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

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

Почему параметры формы не работают для открытой формы

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

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

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

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

Пример отправителя — например, форма обработки, которая подобрала товар и должна передать его в открытый документ:

&НаКлиенте

Процедура ПередатьВыбор(Команда)

Оповестить("ПодборТовараВДокумент", ВыбранныйТовар, ЭтаФорма);

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

Пример получателя — форма документа, которая добавляет строку в табличную часть:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ПодборТовараВДокумент" Тогда

НоваяСтрока = Объект.Товары.Добавить();

НоваяСтрока.Номенклатура = Параметр;

КонецЕсли;

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

Имя события — произвольная строка, но она должна быть уникальной в рамках прикладного решения, иначе чужие формы с совпадающим именем тоже среагируют. Хорошая практика — префиксовать имена, например "МойПроект_ПодборТовара", и проверять параметр Источник, если реагировать нужно только на конкретную форму.

Передача сложных данных через параметр оповещения

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

&НаКлиенте

Процедура ПередатьДанные(Команда)

Данные = Новый Структура;

Данные.Вставить("Номенклатура", ТекущийТовар);

Данные.Вставить("Количество", 5);

Данные.Вставить("Цена", ПолучитьЦену(ТекущийТовар));

Оповестить("ЗаполнитьСтрокуДокумента", Данные, ЭтаФорма);

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

На стороне получателя обязательно защититесь от неполных данных: структура может прийти без ожидаемого ключа, если событие шлёт другой источник с тем же именем. Используйте проверку через Свойство():

Если ИмяСобытия = "ЗаполнитьСтрокуДокумента"

И ТипЗнч(Параметр) = Тип("Структура")

И Параметр.Свойство("Номенклатура") Тогда

// обработка

КонецЕсли;

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

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

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

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

// в модуле формы-получателя

&НаКлиенте

Процедура ПринятьДанные(Данные) Экспорт

Объект.Комментарий = Данные.Текст;

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

// в вызывающем коде

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

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

КонецЕсли;

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

Закрытие формы с возвратом результата: ОповеститьОВыборе

Частный, но очень частый случай — форма выбора, которая должна вернуть значение той форме, что её открыла. Для этого предназначены методы ОповеститьОВыборе() и Закрыть() с параметром. Форма-владелец получает результат в том же ОбработкаОповещения, если форма открыта с указанием владельца.

// в форме выбора

&НаКлиенте

Процедура Выбрать(Команда)

ОповеститьОВыборе(ТекущаяСтрока.Ссылка);

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

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

Оповещение = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", , ЭтаФорма, , , , Оповещение);

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

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

Универсально, слабая связность; минус — событие получают все формы, нужна фильтрация по имени и источнику

Экспортная процедура формы

Точечная передача в конкретную форму; минус — жёсткая связность и риск обращения к закрытой форме

ОписаниеОповещения при ОткрытьФорму

Идеально для пары «открывающая — открываемая»; не подходит, если форма уже открыта независимо

Проверка результата и типичные ошибки

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

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

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

Срабатывание ОбработкаОповещения
Норма

Точка останова в обработчике ловит событие с правильным именем

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

Обработчик не вызывается — проверьте контекст вызова Оповестить и имя события

Содержимое параметра
Норма

Структура содержит все ожидаемые ключи с корректными типами

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

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

Реакция формы
Норма

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

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

Данные пришли, но форма не обновилась — проверьте логику внутри обработчика

Когда оповещения не подходят: альтернативы

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

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

Итог

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

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

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

Можно ли передать параметр в форму другого пользователя?

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

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

Чаще всего причина в том, что Оповестить вызван в серверной процедуре — клиентские формы такого события не получат. Также проверьте точное совпадение имени события и то, что форма-получатель действительно открыта в этот момент.

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

Для обновления списка после изменения объекта есть стандартное событие: вызовите ОповеститьОбИзменении(Ссылка) или Оповестить("Запись_ИмяОбъекта") — динамические списки реагируют на них автоматически без ручного обработчика.

Можно ли передать таблицу значений через оповещение?

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

Что лучше: Оповестить или прямой вызов экспортной процедуры формы?

Если отправитель и получатель известны заранее и связаны жёстко — прямой вызов проще и прозрачнее. Если событие может интересовать несколько форм или состав получателей меняется, используйте оповещения: они не требуют от отправителя знать, кто слушает.

Теряются ли данные, если форма-получатель закрыта?

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