Как отловить отмену сохранения нового документа при закрытии обычной формы в 1С?

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

В процессе разработки учетных систем нередко возникает задача контроля действий пользователей. Типичный сценарий: оператор открыл новый документ, заполнил реквизиты или табличную часть, но в момент закрытия окна на штатный вопрос программы «Сохранить изменения?» ответил «Нет». Руководству или службе безопасности часто требуется фиксировать подобные факты — например, для предотвращения злоупотреблений или анализа причин незавершенных операций.

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

Ограничения стандартного механизма платформы

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

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

Следовательно, единственный способ зарегистрировать отказ — полностью отключить штатный диалог и подставить вместо него собственный обработчик.

Алгоритм перехвата в обработчике ПередЗакрытием

Для реализации задуманного обратимся к событию формы документа ПередЗакрытием. Разберем логику по шагам:

  1. Проверяем, является ли документ новым с помощью метода ЭтоНовый() и были ли в него внесены изменения через свойство Модифицированность.
  2. Если оба условия истинны, отключаем стандартное платформенное предупреждение, присвоив параметру СтандартнаяОбработка = Ложь.
  3. Вызываем собственный диалог через функцию Вопрос() с кнопками «Да», «Нет» и «Отмена».
  4. В зависимости от ответа пользователя управляем ходом закрытия формы:
    1. Если выбран ответ Да — вызываем штатную запись через ЗаписатьВФорме(). Если запись не удалась, прерываем закрытие установкой Отказ = Истина.
    2. Если выбран ответ Отмена — отменяем закрытие формы (Отказ = Истина), позволяя пользователю продолжить работу.
    3. Если выбран ответ Нет — регистрируем отказ пользователя в журнале или регистре сведений, после чего сбрасываем признак Модифицированность = Ложь, чтобы форма закрылась без повторных запросов.

Программная реализация в модуле обычной формы

Посмотрим на пример кода процедуры, размещаемой в модуле обычной формы документа:


Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)

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

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

Вспомогательная процедура ЗарегистрироватьОтказОтСохранения() может выполнять запись события в журнал регистрации через метод ЗаписьЖурналаРегистрации() либо производить запись реквизитов несохраненного документа в специально созданный независимый регистр сведений.

Подводные камни и краевые случаи

Рассмотрим ситуации, при которых описанный выше программный перехват может не сработать или повести себя некорректно:

  1. Закрытие всей программы: Если пользователь нажимает крестик основного окна 1С или комбинацию клавиш Alt+F4, платформа инициирует закрытие всех открытых окон. В этом сценарии возможна коллизия между диалогами формы и системным обработчиком ПередЗавершениемРаботыСистемы.
  2. Аварийное завершение процесса: Если пользователь принудительно снимает процесс 1cv8.exe через системный диспетчер задач Windows или происходит сбой питания, код в обработчиках форм вообще не вызывается. Соответственно, факт набора и отмены документа зафиксирован не будет.

Альтернативные архитектурные решения

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

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