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