Как убрать звездочку (*) и сбросить флаг модифицированности формы после открытия в 1С?

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

Часто перед разработчиками 1С встает задача: при открытии формы документа или справочника нужно программно заполнить какие-либо поля. Например, подставить значение по умолчанию, рассчитать показатель или загрузить связанную информацию. Проблема в том, что после таких действий платформа считает форму измененной, ставит в заголовке окна звездочку (*) и при закрытии задает пользователю стандартный вопрос: "Данные были изменены. Сохранить изменения?". Это сбивает с толку, ведь сам пользователь ничего не менял.

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

Почему форма становится модифицированной?

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

  1. Прямое изменение данных: Пользователь или программный код меняет значение реквизита, который связан с данными объекта в базе данных (например, реквизит документа "Контрагент" или "Сумма").
  2. Взаимодействие с элементами: Пользователь взаимодействует с элементом управления на форме (например, полем ввода), у которого в свойствах установлен флаг "Изменяет данные".

В нашем случае, когда мы в обработчике события ПриОткрытии или ПриСозданииНаСервере меняем значение реквизита, срабатывает первый пункт. Платформа честно фиксирует изменение и взводит флаг. Наша задача — сообщить ей, что это "служебное" изменение, которое не должно считаться пользовательской модификацией.

Важно также понимать разницу между двумя похожими, но разными понятиями:

В контексте нашей задачи мы будем работать именно со свойством ЭтаФорма.Модифицированность.

Решение 1: Прямой сброс флага (самый простой способ)

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

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

Посмотрим на пример. Предположим, при открытии формы документа мы хотим заполнить поле "Комментарий" служебной информацией.

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


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

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

Этот способ надежен, понятен и подходит для большинства простых случаев.

Решение 2: Использование правильных событий (рекомендуемый способ)

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

Для управляемых форм это событие ПриСозданииНаСервере. Логика платформы такова, что любые изменения данных в этом обработчике считаются частью инициализации объекта и не взводят флаг модифицированности формы.

Давайте перенесем наш код из предыдущего примера в правильный обработчик.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Проверяем, что это не новая форма, а открытие существующего документа
    Если НЕ ЭтоНовый() Тогда
        // Все изменения данных здесь НЕ установят флаг Модифицированность
        Объект.Комментарий = "Форма открыта пользователем " + ИмяПользователя() + " в " + ТекущаяДата();
    КонецЕсли;
КонецПроцедуры

Преимущества этого подхода:

В большинстве случаев для задачи начального заполнения полей следует использовать именно этот метод.

Решение 3: Использование режима загрузки данных

Существует еще один мощный, но более специфичный механизм. Он предназначен для ситуаций, когда нужно программно изменить данные объекта, обойдя при этом некоторые стандартные проверки платформы и без установки флага модифицированности. Это режим загрузки данных, который активируется свойством ОбменДанными.Загрузка.

Когда вы устанавливаете Объект.ОбменДанными.Загрузка = Истина;, вы как бы говорите системе: "Сейчас происходит не интерактивная работа, а программная загрузка данных, не нужно выполнять стандартные проверки и устанавливать флаги".

Крайне важно после завершения всех операций вернуть это свойство в значение Ложь.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Включаем режим загрузки
    Объект.ОбменДанными.Загрузка = Истина;
    
    // Выполняем изменения
    Объект.Комментарий = "Служебная информация, установленная при открытии";
    // Можно менять и другие реквизиты
    // Объект.Ответственный = ...;
    
    // ОБЯЗАТЕЛЬНО выключаем режим загрузки
    Объект.ОбменДанными.Загрузка = Ложь;
КонецПроцедуры

Этот метод стоит использовать с осторожностью, так как он может отключать важную бизнес-логику, заложенную в обработчиках событий объекта (например, в ПередЗаписью или ОбработкаПроверкиЗаполнения), если в них есть стандартная проверка `Если ОбменДанными.Загрузка Тогда Возврат;`.

Решение 4: Нерекомендуемый способ с транзакцией

На форуме был предложен трюк с использованием транзакции:


НачатьТранзакцию();
Записать(); // Метод Записать() сбрасывает флаг модифицированности
ОтменитьТранзакцию();

Почему этот способ плох и его следует избегать:

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

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

← На главную