При разработке в среде 1С:Предприятие 8.3 на управляемых формах разработчики часто сталкиваются со следующей проблемой: при создании нового документа на основании другого объекта все реквизиты заполняются корректно, однако сама форма открывается «чистой» — без признака модифицированности (знаменитой «звездочки» в заголовке окна). Если пользователь случайно или намеренно закроет такую форму, система не выдаст предупреждение о необходимости сохранения данных, и документ просто исчезнет без следа.
В этой статье мы подробно разберем, почему платформа 1С ведет себя подобным образом, детально изучим разницу между модифицированностью объекта и формы, а также рассмотрим два надежных практических способа решения этой проблемы с готовыми примерами кода.
Для начала давайте проанализируем внутренние механизмы платформы 1С. Процесс создания документа на основании состоит из нескольких последовательных шагов:
ОбработкаЗаполнения в модуле объекта, где программно заполняются реквизиты и табличные части на основе переданных данных.ПриСозданииНаСервере.ПриОткрытии.Ключевой нюанс: программное изменение реквизитов объекта в транзакции его создания (в процедуре ОбработкаЗаполнения) не приводит к автоматическому взведению флага модифицированности самой управляемой формы. Платформа 1С считает, что если пользователь лично не вносил интерактивных изменений на форме (не вводил текст руками, не выбирал значения из списков), то форму можно закрывать без предупреждения. Это сделано для того, чтобы не беспокоить пользователя лишними вопросами, если он случайно нажал кнопку «Создать на основании» и решил сразу отменить действие.
Крайне важно различать два созвучных понятия в платформе, которые выполняют абсолютно разные задачи:
ЭтотОбъект.Модифицированность(): Доступен только на сервере в контексте прикладного объекта. Возвращает булево значение (Истина или Ложь). Этот метод указывает, отличаются ли текущие данные объекта в оперативной памяти от его состояния в базе данных. Для любого нового, еще не записанного документа этот метод всегда вернет Истина.ЭтаФорма.Модифицированность: Доступно на клиенте и сервере. Это свойство типа Булево, предназначенное как для чтения, так и для записи. Именно оно управляет отображением символа «*» в заголовке окна и отвечает за вывод стандартного диалога с вопросом «Данные были изменены. Сохранить изменения?» при попытке закрыть форму.Если мы хотим заставить форму реагировать на закрытие, нам нужно принудительно установить свойство ЭтаФорма.Модифицированность в значение Истина.
Рассмотрим подробнее два практических сценария реализации этой задачи.
Попытка просто написать ЭтаФорма.Модифицированность = Истина; внутри серверной процедуры ПриСозданииНаСервере часто терпит неудачу. Платформа принудительно сбрасывает этот флаг перед передачей формы клиенту. Поэтому устанавливать свойство нужно на клиенте в процедуре ПриОткрытии.
Разберем это решение по шагам:
Шаг 1. Откроем управляемую форму нашего документа, перейдем на вкладку «Реквизиты» и добавим новый реквизит формы с именем СозданНаОсновании и типом данных Булево. Этот реквизит будет служить индикатором того, что форму открыли именно по цепочке ввода на основании.
Шаг 2. В модуле формы пропишем логику анализа параметров в событии ПриСозданииНаСервере. Мы проверим наличие стандартного параметра Основание:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, передан ли параметр Основание (заполняется платформой автоматически при вводе на основании)
Если Параметры.Свойство("Основание") И ЗначениеЗаполнено(Параметры.Основание) Тогда
// Фиксируем факт создания на основании во вспомогательном реквизите формы
СозданНаОсновании = Истина;
КонецЕсли;
КонецПроцедуры
Шаг 3. Перейдем в клиентский обработчик ПриОткрытии и установим модифицированность формы, если наш вспомогательный флаг равен Истина:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если СозданНаОсновании Тогда
ЭтаФорма.Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
При таком подходе, как только форма визуализируется на экране пользователя, в заголовке появится звездочка, и при попытке закрыть окно крестиком система выдаст стандартное предупреждение платформы.
Иногда в конфигурациях, построенных на базе Библиотеки Стандартных Подсистем (БСП), стандартные механизмы закрытия или подключаемые обработчики могут сбрасывать модифицированность формы даже после выполнения кода в событии ПриОткрытии. В таких ситуациях классический метод может не сработать.
Чтобы обойти эту системную особенность, мы можем использовать технологический прием с подключением однократного обработчика ожидания с минимальной задержкой. Этот обработчик выполнится на клиенте сразу после того, как форма завершит все процедуры своей внутренней инициализации и станет доступна для взаимодействия с пользователем.
Разберем, как реализовать этот алгоритм:
Шаг 1. Точно так же, как и в первом методе, убедимся, что у нас есть реквизит формы СозданНаОсновании, который мы заполняем на сервере при инициализации:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("Основание") И ЗначениеЗаполнено(Параметры.Основание) Тогда
СозданНаОсновании = Истина;
КонецЕсли;
КонецПроцедуры
Шаг 2. В клиентском событии ПриОткрытии вместо прямой установки модифицированности мы подключаем обработчик ожидания:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если СозданНаОсновании Тогда
// Подключаем однократную процедуру с задержкой 0.1 секунды
ПодключитьОбработчикОжидания("УстановитьМодифицированностьУправляемойФормы", 0.1, Истина);
КонецЕсли;
КонецПроцедуры
Шаг 3. Добавим в модуль формы клиентскую процедуру, имя которой указали в обработчике ожидания:
&НаКлиенте
Процедура УстановитьМодифицированностьУправляемойФормы()
// Этот код сработает гарантированно после того, как платформа отрисует форму
ЭтаФорма.Модифицированность = Истина;
КонецПроцедуры
Этот метод является наиболее надежным «лайфхаком» для обхода тонкостей поведения платформы в сложных кастомизированных конфигурациях.
Если вы внедрили предложенный код, но звездочка модифицированности все равно пропадает, это означает, что какая-то другая процедура в модуле формы или в общем модуле (например, подсистема БСП при заполнении связанных реквизитов) принудительно сбрасывает флаг в значение Ложь.
Чтобы локализовать эту проблему, выполним следующие действия:
ПриОткрытии.Ctrl + Alt + W) и добавим туда выражение ЭтаФорма.Модифицированность.F11, будем внимательно следить за изменением значения в табло. Как только значение изменится с Истина на Ложь, мы мгновенно поймем, какая именно строка кода или внешняя процедура нейтрализует наши изменения.Используя предложенные методики, мы сможем гарантировать сохранность данных наших пользователей и исключить случаи случайного закрытия вновь созданных документов без их предварительной записи в информационную базу.