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