Как правильно задать вопрос пользователю в 1С:Бухгалтерии 3.0 без использования модальных окон?

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

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

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

Почему вызов функции Вопрос() вызывает ошибку

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

  1. Поддержка веб-клиента: современные браузеры блокируют модальные всплывающие окна или не поддерживают блокировку потока исполнения JavaScript, что приводит к зависанию интерфейса.
  2. Работа мобильных клиентов: на мобильных устройствах концепция блокирующих диалоговых окон конфликтует с интерфейсными гайдлайнами операционных систем.
  3. Эргономика и стабильность: синхронная модальность полностью замораживает поток взаимодействия пользователя с интерфейсом системы.

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

Способ 1. Использование процедуры ПоказатьВопрос() с описанием оповещения

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

Разберем по шагам создание обработчика оповещения и вызов диалога:


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

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

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

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


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

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

Способ 2. Асинхронные процедуры и функция ВопросАсинх() (начиная с 8.3.18)

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

Посмотрим на пример использования функции ВопросАсинх():


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

В данном случае перед объявлением процедуры обязательно указывается модификатор Асинх, а перед вызовом функции глобального контекста — оператор Ждать. Код выглядит как классический модальный вызов, но на уровне платформы выполняется полностью асинхронно и не блокирует интерфейс.

Способ 3. Механизмы Библиотеки стандартных подсистем (БСП)

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

Этот метод предоставляет расширенные возможности по сравнению со стандартным диалогом платформы:

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

Рассмотрим пример формирования такого вопроса:


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

&НаКлиенте
Процедура ПослеОтветаНаВопросБСП(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = КодВозвратаДиалога.Да Тогда
        // Действие при согласии
    КонецЕсли;
    
КонецПроцедуры

Способ 4. Автоматический рефакторинг в конфигураторе

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

Важные нюансы и ограничения при работе с вопросами

При проектировании интерактивных диалогов учитывайте особенности архитектуры клиент-серверной модели 1С:

  1. Только клиентский контекст: любые диалоги (ПоказатьВопрос(), ВопросАсинх()) доступны исключительно на стороне клиента (директива &НаКлиенте). Серверный код, регламентные задания, фоновые процессы и веб-сервисы не могут взаимодействовать с пользователем через окна. Все проверки, требующие подтверждения, должны производиться на клиенте до отправки тяжелых данных на сервер.
  2. Произвольные варианты кнопок: в качестве параметра кнопок можно передавать не только стандартное перечисление РежимДиалогаВопрос, но и объект СписокЗначений. Это позволяет выводить собственные названия кнопок (например, «Перезаписать», «Создать копию», «Пропустить») и получать их значения в обработчике.
  3. Особенности обработчиков событий форм: в стандартных обработчиках, таких как ПередЗаписью или ПередЗакрытием, где передается параметр Отказ, асинхронный вопрос не приостанавливает завершение процедуры. Чтобы задать вопрос перед записью или закрытием, сначала устанавливают Отказ = Истина;, задают вопрос асинхронно, а затем, если пользователь ответил положительно, повторно инициируют запись или закрытие формы уже с установленным программным флагом обхода вопроса.
← На главную