Как программно перехватить ответ пользователя на вопрос «Данные были изменены. Сохранить?» при закрытии формы в 1С

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

При работе с интерактивными формами в 1С разработчики часто сталкиваются с ситуацией, когда пользователь редактирует данные на форме, а затем закрывает ее. В этот момент платформа 1С автоматически задает штатный вопрос: «Данные были изменены. Сохранить изменения?» со стандартными вариантами ответа «Да», «Нет» и «Отмена».

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

Ограничение платформы 1С

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

Тем не менее, мы можем обойти это ограничение несколько архитектурными приемами:

  1. Подменить системный диалог собственным асинхронным вопросом в событии ПередЗакрытием.
  2. Скрыть системную кнопку закрытия и предложить пользователю явные кнопки управления («ОК», «Отмена»).
  3. Использовать обработку оповещений и получать актуальные данные объекта из базы данных по ссылке.

Способ 1. Отмена стандартной обработки и вызов собственного диалога

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

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


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

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

&НаКлиенте
Процедура ПослеОтветаНаВопросОСохранении(Результат, ДополнительныеПараметры) Экспорт

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

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

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

Способ 2. Замена системной кнопки закрытия на собственные кнопки

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

  1. В свойствах формы отключить или скрыть командную панель со стандартными кнопками.
  2. Добавить собственные кнопки на форму: «Сохранить и закрыть» и «Отмена».
  3. В обработчике кнопки «Сохранить и закрыть» выполнить команду Записать() или передать данные через ОповеститьОВыборе() / Закрыть(Результат).
  4. В обработчике кнопки «Отмена» установить Модифицированность = Ложь и вызвать Закрыть() без сохранения.

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

Способ 3. Получение данных из базы по ссылке

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

Если пользователь нажал «Нет», изменения на форме сбрасываются. Поэтому наиболее надежным решением в вызывающей форме будет считывание реквизитов объекта непосредственно из базы данных по ссылке после закрытия формы редактирования:


&НаСервере
Функция ПолучитьАктуальныеДанные(СсылкаНаОбъект)
    
    // Считываем записанные данные непосредственно из базы
    Возврат СсылкаНаОбъект.Заглавие;

КонецФункции

Если объект не был записан в подчиненной форме (пользователь выбрал «Нет» или «Отмена»), данные в базе данных останутся прежними, и вызывающая форма не получит невалидные промежуточные изменения.

Резюме

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

← На главную