Как проверить закрытие формы и факт записи документа в немодальном режиме в 1С

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

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

Проблема блокировки интерфейса и «зависания» системы

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

Решение 1. Использование обработчика ожидания

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

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


Перем ФормаДок; // Глобальная переменная модуля

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

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

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

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

Решение 2. Проверка факта записи через «ВерсияДанных»

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

Проанализируем ситуацию с использованием свойства ВерсияДанных. Это системное поле, которое меняется каждый раз при успешной записи объекта в базу данных. Сравним состояние версии до открытия и после закрытия формы.


Перем ФормаДок, СтараяВерсия;

Процедура ЗапуститьРедактирование()
    ФормаДок = Док.ПолучитьФорму("ФормаДокумента");
    // Фиксируем текущую версию данных перед редактированием
    СтараяВерсия = Док.ВерсияДанных; 
    ФормаДок.Открыть();
    ПодключитьОбработчикОжидания("КонтрольЗакрытия", 2);
КонецПроцедуры

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

Решение 3. Использование признака модифицированности

Рассмотрим еще один важный инструмент — свойство Модифицированность. В 1С это свойство формы или объекта показывает, были ли внесены изменения в данные, которые еще не сохранены в базу.

Важные моменты работы с модифицированностью:

  1. Она автоматически устанавливается в Истина, когда пользователь меняет данные в полях ввода.
  2. Она сбрасывается в Ложь автоматически после успешного выполнения метода Записать().
  3. Если пользователь закрыл форму и Модифицированность осталась истинной в момент перед закрытием (и пользователь отказался от сохранения), мы можем это отловить.

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

Решение 4. Механизм оповещений (Оповестить и ОбработкаОповещения)

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

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


Процедура ПослеЗаписи()
    // Отправляем оповещение системе
    Оповестить("ЗаписьДокументаЗавершена", Ссылка, ЭтаФорма);
КонецПроцедуры

А в вашей исходной обработке, из которой вы открывали документ, нужно создать процедуру ОбработкаОповещения:


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

Этот метод не требует таймеров и работает мгновенно. Он особенно полезен, когда нужно отследить не просто закрытие, а именно факт успешного совершения транзакции в базе данных.

Подведение итогов

Мы рассмотрели несколько способов контроля состояния формы и данных без использования модальных окон. Выбор конкретного метода зависит от ваших ограничений:

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

← На главную