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