Как закрыть форму документа в 1С без системного вопроса о сохранении изменений?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

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

Разберем причину появления вопроса: свойство Модифицированность

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

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

Решение 1: Сброс флага Модифицированность программно

Самый простой и быстрый способ решить проблему «испуганного пользователя» — это принудительно сказать системе, что форма не была изменена (даже если мы только что заполнили в ней десяток полей). Для этого используется свойство формы Модифицированность.

Посмотрим на пример кода, который можно разместить в конце процедуры ПриОткрытии:


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

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

Решение 2: Использование события ОбработкаЗаполнения

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

Правильнее использовать механизм Обработки заполнения в модуле самого объекта. Разберем по шагам, как это работает:

  1. Переходим в модуль документа (не формы!).
  2. Находим или создаем процедуру ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка).
  3. Размещаем логику заполнения значений по умолчанию там.

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

Решение 3: Умная проверка в событии ПередЗакрытием

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

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


Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
    // Если сумма документа нулевая, мы считаем, что документ не важен
    Если ЭтотОбъект.Товары.Количество() = 0 И ЭтотОбъект.СуммаДокумента = 0 Тогда
        ЭтаФорма.Модифицированность = Ложь;
    КонецЕсли;
КонецПроцедуры

Здесь мы проверяем: если табличная часть пуста и сумма равна нулю, мы сбрасываем Модифицированность в Ложь. Система «подумает», что ничего не менялось, и закроет окно без лишних вопросов.

Почему метод Удалить() не подходит для решения задачи?

Выясним причину ошибки, с которой столкнулся автор темы при попытке использовать метод Удалить(). Метод ЭтотОбъект.Удалить() предназначен для физического удаления записи из базы данных. Если вы только что открыли форму нового документа, его еще нет в базе (он существует только в оперативной памяти). Попытка удалить то, чего не существует, логично приводит к ошибке.

В 1С не существует метода «Отменить изменения» для объекта в памяти, так как до момента нажатия кнопки «Записать» никаких изменений в базе и так нет. Достаточно просто закрыть форму, обеспечив Модифицированность = Ложь.

Проверка заполнения: защита от «мусорных» данных

Чтобы избежать захламления базы пустыми документами, если пользователь все же нажал «Да» в окне сохранения, обязательно используйте стандартный механизм ПроверитьЗаполнение(). Для критически важных реквизитов (например, Склад или Контрагент) в конфигураторе установите свойство Проверка заполнения в значение Выдавать ошибку.

В этом случае, даже если возникнет диалог сохранения и пользователь нажмет «Да», система выдаст предупреждение: «Поле не заполнено!» и не даст записать пустой документ. Это вторая линия обороны вашей базы данных.

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

Для корректной работы с формой и предотвращения назойливых вопросов системы:

  1. Используйте ЭтаФорма.Модифицированность = Ложь после программного изменения реквизитов в форме.
  2. Старайтесь переносить логику заполнения значений по умолчанию в ОбработкуЗаполнения модуля объекта.
  3. Контролируйте состояние документа в событии ПередЗакрытием, если требуется сложная логика отмены.
  4. Никогда не используйте Удалить() для отмены создания нового документа.

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

← На главную