Как сделать форму нового документа модифицированной при создании на основании в 1С 8.3?

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

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

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

Почему так происходит? Особенности платформы 1С

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

  1. На сервере создается новый экземпляр прикладного объекта.
  2. Вызывается обработчик ОбработкаЗаполнения в модуле объекта, где программно заполняются реквизиты и табличные части на основе переданных данных.
  3. Создается и инициализируется управляемая форма документа. Вызывается серверное событие формы ПриСозданииНаСервере.
  4. Данные передаются на клиент, и отрабатывает клиентское событие формы ПриОткрытии.

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

Различие между модифицированностью объекта и управляемой формы

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

  1. Метод объекта ЭтотОбъект.Модифицированность(): Доступен только на сервере в контексте прикладного объекта. Возвращает булево значение (Истина или Ложь). Этот метод указывает, отличаются ли текущие данные объекта в оперативной памяти от его состояния в базе данных. Для любого нового, еще не записанного документа этот метод всегда вернет Истина.
  2. Свойство управляемой формы ЭтаФорма.Модифицированность: Доступно на клиенте и сервере. Это свойство типа Булево, предназначенное как для чтения, так и для записи. Именно оно управляет отображением символа «*» в заголовке окна и отвечает за вывод стандартного диалога с вопросом «Данные были изменены. Сохранить изменения?» при попытке закрыть форму.

Если мы хотим заставить форму реагировать на закрытие, нам нужно принудительно установить свойство ЭтаФорма.Модифицированность в значение Истина.

Рассмотрим подробнее два практических сценария реализации этой задачи.

Решение 1. Использование вспомогательного реквизита и обработчика «ПриОткрытии» (Рекомендуемый способ)

Попытка просто написать ЭтаФорма.Модифицированность = Истина; внутри серверной процедуры ПриСозданииНаСервере часто терпит неудачу. Платформа принудительно сбрасывает этот флаг перед передачей формы клиенту. Поэтому устанавливать свойство нужно на клиенте в процедуре ПриОткрытии.

Разберем это решение по шагам:

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

Шаг 2. В модуле формы пропишем логику анализа параметров в событии ПриСозданииНаСервере. Мы проверим наличие стандартного параметра Основание:


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

Шаг 3. Перейдем в клиентский обработчик ПриОткрытии и установим модифицированность формы, если наш вспомогательный флаг равен Истина:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    Если СозданНаОсновании Тогда
        ЭтаФорма.Модифицированность = Истина;
    КонецЕсли;
    
КонецПроцедуры

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

Решение 2. Обходной путь через обработчик ожидания (для сложных форм и БСП)

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

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

Разберем, как реализовать этот алгоритм:

Шаг 1. Точно так же, как и в первом методе, убедимся, что у нас есть реквизит формы СозданНаОсновании, который мы заполняем на сервере при инициализации:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("Основание") И ЗначениеЗаполнено(Параметры.Основание) Тогда
        СозданНаОсновании = Истина;
    КонецЕсли;
    
КонецПроцедуры

Шаг 2. В клиентском событии ПриОткрытии вместо прямой установки модифицированности мы подключаем обработчик ожидания:


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

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


&НаКлиенте
Процедура УстановитьМодифицированностьУправляемойФормы()
    
    // Этот код сработает гарантированно после того, как платформа отрисует форму
    ЭтаФорма.Модифицированность = Истина;
    
КонецПроцедуры

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

Как отлаживать модифицированность управляемой формы?

Если вы внедрили предложенный код, но звездочка модифицированности все равно пропадает, это означает, что какая-то другая процедура в модуле формы или в общем модуле (например, подсистема БСП при заполнении связанных реквизитов) принудительно сбрасывает флаг в значение Ложь.

Чтобы локализовать эту проблему, выполним следующие действия:

  1. Откроем конфигуратор и перейдем в модуль формы нашего документа.
  2. Установим точку останова в процедуре ПриОткрытии.
  3. Запустим сеанс отладки и создадим документ на основании.
  4. При остановке выполнения откроем панель Табло (клавиши Ctrl + Alt + W) и добавим туда выражение ЭтаФорма.Модифицированность.
  5. Используя пошаговый обход кода с помощью клавиши F11, будем внимательно следить за изменением значения в табло. Как только значение изменится с Истина на Ложь, мы мгновенно поймем, какая именно строка кода или внешняя процедура нейтрализует наши изменения.

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

← На главную