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

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

1С: как передать параметры из закрываемой формы

Как передать параметры из закрываемой формы в 1С 8.3: ОповеститьОВыборе, Закрыть(параметр), ОписаниеОповещения, обработчики ПриЗакрытии. Примеры кода и типичные ошибки.

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

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

Как устроена передача данных при закрытии формы

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

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

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

Способ 1. Закрыть форму с возвращаемым значением

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

Код в вызывающей форме:

&НаКлиенте

Процедура ОткрытьДиалог(Команда)

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

ОткрытьФорму("Обработка.ПодборТоваров.Форма.ФормаПодбора", , ЭтотОбъект, , , , Оповещение);

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

&НаКлиенте

Процедура ПослеЗакрытияДиалога(Результат, ДополнительныеПараметры) Экспорт

Если Результат = Неопределено Тогда

Возврат; // пользователь закрыл форму крестиком

КонецЕсли;

Для Каждого СтрокаТовара Из Результат.Товары Цикл

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

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

НоваяСтрока.Количество = СтрокаТовара.Количество;

КонецЦикла;

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

Код в закрываемой форме:

&НаКлиенте

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

Результат = Новый Структура;

Результат.Вставить("Товары", СобратьВыбранныеТовары());

Закрыть(Результат);

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

Ключевой момент: если пользователь закрыл форму крестиком или клавишей Esc без вызова Закрыть(Результат), в обработчик придёт Неопределено. Всегда проверяйте это значение первой строкой обработчика, иначе получите ошибку обращения к полям структуры.

bsl
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытия", ЭтотОбъект);
ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора", , ЭтотОбъект, , , , Оповещение);
// В закрываемой форме: Закрыть(СтруктураСРезультатом);

Способ 2. ОповеститьОВыборе и обработчик ОбработкаВыбора

Если форма открывается из поля ввода (кнопка выбора) или должна работать как стандартная форма выбора, используется метод ОповеститьОВыборе(Значение). Он вызывает в форме-владельце событие ОбработкаВыбора, а если форма открыта для выбора из поля ввода — платформа сама подставит значение в поле.

В закрываемой форме:

&НаКлиенте

Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;

ДанныеСтроки = Элементы.Список.ДанныеСтроки(ВыбраннаяСтрока);

ОповеститьОВыборе(ДанныеСтроки.Ссылка);

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

В форме-владельце:

&НаКлиенте

Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)

Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Номенклатура") Тогда

Объект.ОсновнойТовар = ВыбранноеЗначение;

КонецЕсли;

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

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

Когда выбрать этот способ

ОповеститьОВыборе уместен, когда форма работает как селектор одного значения и логика выбора должна быть совместима со стандартным механизмом полей ввода. Для сложных диалогов с множеством настроек удобнее первый способ через Закрыть(Структура) — он позволяет вернуть произвольный набор данных и явно разделяет «выбрал» и «отменил».

Способ 3. Метод Оповестить для широковещательных сообщений

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

&НаКлиенте

Процедура ПриЗакрытии(ЗавершениеРаботы)

Если ЗавершениеРаботы Тогда

Возврат;

КонецЕсли;

Оповестить("ИзмененыНастройкиОтбора", НастройкиОтбора, ЭтотОбъект);

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

Подписчик в другой форме:

&НаКлиенте

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

Если ИмяСобытия = "ИзмененыНастройкиОтбора" Тогда

ПрименитьОтбор(Параметр);

КонецЕсли;

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

Главное правило: имя события должно быть уникальным и описательным, иначе разные подсистемы начнут реагировать на чужие оповещения. Рекомендуется включать в имя префикс подсистемы, например "ПодборПерсонала_ЗаписанСотрудник". Также проверяйте параметр Источник, если одно и то же событие могут генерировать разные формы.

Способ 4. Модальное открытие и обработчик ПриЗакрытии

В конфигурациях, где разрешён синхронный режим, форму можно открыть через ОткрытьФормуМодально() — метод вернёт значение, переданное в Закрыть(), непосредственно в точку вызова:

&НаКлиенте

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

Результат = ОткрытьФормуМодально("ОбщаяФорма.ВыборПериода");

Если Результат <> Неопределено Тогда

Объект.ДатаНачала = Результат.ДатаНачала;

Объект.ДатаОкончания = Результат.ДатаОкончания;

КонецЕсли;

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

Этот способ прост, но блокирует весь интерфейс и не работает в веб-клиенте при запрещённой модальности, а также в тонком клиенте с настройкой «Не использовать» режима модальности. В новых разработках его применять не рекомендуется — заменяйте на описание оповещения.

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

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

Закрыть(Результат) + ОписаниеОповещения

Универсальный вариант для диалогов и подбора. Работает в асинхронном режиме, позволяет вернуть структуру любой сложности. Требует проверки на Неопределено.

ОповеститьОВыборе

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

Оповестить

Для уведомления нескольких открытых окон. Нет гарантии доставки конкретному получателю, нужны уникальные имена событий.

ОткрытьФормуМодально

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

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

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

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

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

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

Подтверждение выбора кнопкой
Норма

Обработчик получает структуру с данными, вызывающая форма обновляется

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

Приходит Неопределено или пустое значение — проверьте, что Закрыть() вызывается с параметром

Закрытие крестиком или Esc
Норма

Обработчик получает Неопределено и корректно завершается без изменений

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

Ошибка выполнения — нет проверки на Неопределено

Повторное открытие формы
Норма

Каждый раз создаётся новое описание оповещения, данные возвращаются корректно

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

Обработчик срабатывает несколько раз или не срабатывает — проверьте, где создаётся оповещение

Ограничения и безопасные границы

Через параметры закрытия нельзя передавать объекты, привязанные к времени жизни формы: элементы формы, данные формы после её уничтожения, COM-объекты между сеансами. Передавайте примитивные типы, ссылки, структуры, массивы и соответствия. Если нужно вернуть таблицу — преобразуйте её в массив структур до вызова Закрыть().

Будьте осторожны при изменении типовых форм конфигураций на поддержке. Доработка обработчиков выбора в типовых объектах усложняет обновление. По возможности используйте расширения конфигурации или подписки на события, а перед изменением типового кода сделайте копию информационной базы и проверьте сценарий на тестовых данных.

FAQ

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

Да. Соберите значения в структуру и передайте её параметром метода Закрыть(): Закрыть(Новый Структура("Товар, Количество, Цена", Товар, Количество, Цена)). В обработчике оповещения обращайтесь к полям структуры по именам.

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

Чаще всего процедура объявлена без директивы Экспорт, указано неверное имя процедуры в конструкторе ОписаниеОповещения, либо форма закрывается без вызова Закрыть(Результат). Также проверьте, что форма открыта именно через ОткрытьФорму с передачей описания оповещения, а не через ОткрытьФормуМодально.

Чем отличается ОповеститьОВыборе от Оповестить?

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

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

Напрямую таблицу значений формы передавать не стоит — после закрытия она может быть очищена. Перед закрытием обойдите таблицу в цикле и соберите массив структур с нужными колонками, затем передайте этот массив в структуре результата через Закрыть().

Работает ли Закрыть(Результат) в обычном приложении?

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

Как отличить «пользователь выбрал» от «пользователь отменил»?

Если форма закрыта крестиком или Esc, обработчик получает Неопределено. Если вызван Закрыть(Результат) — приходит переданное значение. Для надёжности в самой форме можно дополнительно передавать в структуре признак, например Результат.Вставить("ВыборВыполнен", Истина), и проверять его.

Итог

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

Стандартный способ вернуть данные из закрываемой формы — Закрыть(Результат) в связке с ОписаниеОповещения при открытии. Для форм выбора используйте ОповеститьОВыборе, для уведомления нескольких окон — Оповестить. Всегда проверяйте результат на Неопределено, объявляйте обработчики с директивой Экспорт и передавайте данные в новых структурах, а не ссылками на данные формы.