Как реализовать оповещение пользователя перед записью или проведением документа в 1С 8.3

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

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

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

Разберем причину проблемы: почему стандартный подход не работает

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

Для решения этой задачи нам потребуется реализовать механизм повторного входа в процедуру записи.

Способ 1. Использование флага на форме (Паттерн "Повторный вызов")

Это наиболее гибкий и правильный способ, который используется в типовых конфигурациях (БП 3.0, УТ 11, КА 2.4). Суть метода заключается в том, чтобы при первом вызове прервать запись, дождаться ответа пользователя и, если ответ положительный, вызвать запись программно, установив специальный флаг, разрешающий выполнение.

Рассмотрим пошагово реализацию этого алгоритма:

  1. Создадим переменную на уровне модуля формы (не путать с реквизитом документа), которая будет служить флагом проверки.
  2. В обработчике ПередЗаписью проверим этот флаг.
  3. Если флаг не установлен — прервем запись и покажем вопрос.
  4. В процедуре обработки ответа установим флаг и вызовем метод Записать() (при работе с дополнительными реквизитами это наиболее частый сценарий).

Посмотрим на пример кода:


&НаКлиенте
Перем ПроверкаПередЗаписьюВыполнена; // Переменная модуля формы

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

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

Важные нюансы работы с параметрами записи

Обратите внимание на объект ПараметрыЗаписи в процедуре ПередЗаписью. Это структура, которая содержит важные флаги платформы:

Когда мы вызываем Записать(ДополнительныеПараметры.ПараметрыЗаписи) в процедуре оповещения, мы передаем эти флаги обратно системе. Благодаря этому, если пользователь нажимал "Провести и закрыть", форма корректно проведется и закроется после того, как отработает наш программный вызов.

Как избежать системного сообщения "Не удалось записать"

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

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

Способ 2. Подмена стандартной команды формы

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

  1. В редакторе формы найдите стандартную командную панель.
  2. Отключите видимость стандартных кнопок Записать и Провести и закрыть.
  3. Создайте свои команды (например, МояЗаписатьИЗакрыть).
  4. В обработчике команды сначала вызывайте диалог, и только внутри обработчика оповещения (при успешном выборе) вызывайте метод ЭтотОбъект.Записать(Параметры).

Этот способ "чище" с точки зрения логики событий, так как мы не входим в стандартный цикл записи до тех пор, пока не получим все данные от пользователя. Однако он требует аккуратности, чтобы не нарушить стандартное поведение формы (например, горячие клавиши Ctrl+Enter все равно будут вызывать стандартное проведение, если их не перехватить).

Заключение

Мы рассмотрели основной механизм работы с асинхронными вызовами в формах 1С 8.3. Использование флага повторного входа в сочетании с сохранением ПараметрыЗаписи является наиболее надежным и рекомендуемым способом реализации интерактивных проверок. Это позволяет сохранить привычный пользователю функционал кнопок "Провести и закрыть", обеспечивая при этом корректное заполнение данных и выполнение бизнес-логики.

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

← На главную