Как открыть форму диалога без модальности и передать данные в вызывающую форму в 1С:Предприятие 8.3?

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

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

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

---

Почему возникает ошибка при простом переходе с ОткрытьМодально на ОткрытьФорму

При использовании устаревшего метода ОткрытьМодально() выполнение кода в вызывающей процедуре полностью приостанавливалось до момента закрытия диалога. Это позволяло писать линейный код:


// Устаревший синхронный подход
Диалог = ПолучитьФорму("Обработка.РегламентныеИФоновыеЗадания.Форма.ДиалогОтбораФоновогоЗадания", ПараметрыФормы);
Диалог.ОткрытьМодально();
// Следующая строка выполнялась ТОЛЬКО после закрытия окна
УстановитьОтборНаСервере(Новый ФиксированнаяСтруктура(Диалог.Отбор));

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

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

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

---

Способ 1. Классический механизм через ОписаниеОповещения

Проанализируем классический подход, работающий во всех версиях платформы 1С 8.3 с управляемыми формами. Разберем по шагам код обеих форм.

Шаг 1. Вызов диалога из основной формы

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


&НаКлиенте
Процедура УстановитьОтбор(Команда)
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", Новый Структура);
    
    // Создаем описание процедуры, которая выполнится ПОСЛЕ закрытия диалога
    ОповещениеОЗакрытии = Новый ОписаниеОповещения("ЗакрытиеФормыОтбора", ЭтаФорма);
    
    // Внимание на синтаксис параметров метода ОткрытьФорму:
    // 1 - ИмяФормы
    // 2 - Параметры
    // 3 - Владелец
    // 4 - Уникальность
    // 5 - Окно
    // 6 - НавигационнаяСсылка
    // 7 - ОписаниеОповещенияОЗакрытии
    // 8 - РежимОткрытияОкна
    ОткрытьФорму(
        "Обработка.РегламентныеИФоновыеЗадания.Форма.ДиалогОтбораФоновогоЗадания",
        ПараметрыФормы,
        ЭтаФорма,
        ,
        ,
        ,
        ОповещениеОЗакрытии,
        РежимОткрытияОкнаФормы.БлокироватьОкноВладельца
    );
    
КонецПроцедуры

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

Шаг 2. Закрытие и возврат данных из формы диалога

В форме подбора или диалога отбора при нажатии кнопки «ОК» формируем структуру результата и передаем ее параметром в стандартную процедуру Закрыть().


&НаКлиенте
Процедура ОкЗакрытие(Команда)
    
    // Формируем структуру параметров на клиенте или через вызов сервера
    СтруктураОтбора = ПолучитьЗаполненныйОтбор();
    
    // Передаем заполненную структуру в метод Закрыть
    Закрыть(СтруктураОтбора);
    
КонецПроцедуры

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

Шаг 3. Обработка полученного результата в вызывающей форме

В родительской форме объявляем экспортную клиентскую процедуру с обязательными параметрами Результат и ДополнительныеПараметры. Обязательно проверяем результат на Неопределено (на случай закрытия окна крестиком или клавишей Esc).


&НаКлиенте
Процедура ЗакрытиеФормыОтбора(Результат, ДополнительныеПараметры) Экспорт
    
    // Пользователь закрыл окно без подтверждения (Esc / Крестик)
    Если Результат = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Передаем полученную структуру в серверную процедуру обработки
    УстановитьОтборНаСервере(Новый ФиксированнаяСтруктура(Результат));
    
КонецПроцедуры

&НаСервере
Процедура УстановитьОтборНаСервере(ФиксОтбор)
    
    Отбор = Новый Структура(ФиксОтбор);
    ТаблицаФоновыеЗадания.Очистить();
    
    Фоновые = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);
    Для Каждого Фоновое Из Фоновые Цикл
        НоваяСтрока = ТаблицаФоновыеЗадания.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Фоновое);
    КонецЦикла;
    
КонецПроцедуры

---

Способ 2. Современный асинхронный синтаксис (Асинх / Ждать)

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

Рассмотрим, как выглядит тот же функционал с использованием конструкции Асинх, Ждать и метода ОткрытьФормуАсинх:


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

Преимущество асинхронных методов — высокая читаемость и сохранение контекста локальных переменных внутри одной процедуры.

---

Способ 3. Механизм выбора (ОповеститьОВыборе / ОбработкаВыбора)

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

  1. При открытии формы обязательно указываем владельца: Владелец = ЭтаФорма.
  2. В форме выбора вызываем метод ОповеститьОВыборе(СтруктураОтбора) и закрываем окно.
  3. В главной форме создаем предопределенный обработчик события ОбработкаВыбора:

&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
    
    Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") Тогда
        УстановитьОтборНаСервере(Новый ФиксированнаяСтруктура(ВыбранноеЗначение));
    КонецЕсли;
    
КонецПроцедуры

---

Сравнительный анализ способов взаимодействия форм

Проанализируем, в каких ситуациях предпочтительнее применять каждый из рассмотренных подходов:

  1. ОписаниеОповещения (классический): универсальный способ, поддерживается всеми версиями 1С 8.3, гарантирует независимость вызывающего кода от глобальных событий.
  2. ОткрытьФормуАсинх (современный): наилучший выбор для конфигураций на платформе 8.3.18 и выше с включенной поддержкой асинхронности. Код остается компактным и линейным.
  3. ОповеститьОВыборе: оптимален при разработке специализированных форм подбора и выбора элементов справочников или документов.

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

← На главную