Почему при открытии документа в 1С появляется «звездочка» модифицированности и как это исправить?

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

Каждый разработчик 1С рано или поздно сталкивается с загадочной ситуацией: пользователь открывает документ, ничего в нем не меняет, но в заголовке формы сразу появляется символ «*» (звездочка), а при попытке закрытия система настойчиво предлагает сохранить изменения. Это состояние называется модифицированностью. В данной статье мы подробно разберем, почему это происходит, где «прячется» причина, если отладчик молчит, и какими методами можно вычислить виновника программного изменения данных.

Понятие модифицированности: Форма против Объекта

Прежде всего, нам необходимо разграничить два понятия: Модифицированность формы и Модифицированность самого объекта. В управляемом приложении за визуальную «звездочку» отвечает свойство формы. Однако важно понимать, что признак изменения формы может взводиться не только при редактировании данных пользователем, но и программно.

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

Метод «исключения»: самый надежный способ поиска

Если стандартная проверка через отладчик в процедуре ПриОткрытии не дает результатов и значение ЭтаФорма.Модифицированность кажется неизменным, воспользуемся проверенным практикой методом последовательного исключения кода. Разберем этот алгоритм по шагам:

  1. Перейдем в модуль формы документа и найдем процедуру ПриОткрытии() (для обычных форм) или ПриСозданииНаСервере() и ПриЧтенииНаСервере() (для управляемых форм).
  2. Временно закомментируем весь код внутри этих процедур.
  3. Запустим документ. Если «звездочка» исчезла, значит, причина кроется в одной из строк кода.
  4. Начнем постепенно «открывать» (раскомментировать) блоки кода по 2–5 строк, каждый раз перезапуская документ.

Этот кропотливый, но эффективный метод позволяет точно локализовать строку, после исполнения которой объект считается измененным. Как отмечают опытные разработчики, часто проблема кроется в заполнении каких-то служебных реквизитов, которые не видны пользователю, но влияют на статус документа.

Типичные ошибки при программном изменении реквизитов

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


Процедура ПриОткрытии()
    // ОШИБКА: Реквизит меняется при каждом открытии, 
    // даже если документ уже был проведен и закрыт.
    Ответственный = ПараметрыСеанса.ТекущийПользователь;
КонецПроцедуры

Чтобы избежать появления «звездочки» в уже существующих документах, необходимо всегда добавлять проверку на новизну объекта. Перепишем код правильно:


Процедура ПриОткрытии()
    Если ЭтоНовый() Тогда
        Ответственный = ПараметрыСеанса.ТекущийПользователь;
    КонецЕсли;
КонецПроцедуры

В управляемых формах аналогичная логика должна применяться в событии ПриСозданииНаСервере, где мы проверяем Объект.Ссылка.Пустая().

Скрытые причины: точность типов и невидимые символы

Иногда код кажется чистым, но модифицированность все равно возникает. Выясним, какие неочевидные факторы на это влияют:

  1. Разница в точности чисел. Если в базе данных (через прямые запросы или загрузку извне) сохранено число с 5 знаками после запятой, а в метаданных 1С у реквизита стоит точность «2», то при чтении платформа округлит значение. Это округление будет воспринято как изменение данных.
  2. Пробелы и переносы строк. Строковые реквизиты могут содержать невидимые символы в конце строки (пробелы, знаки табуляции). При загрузке в элементы управления формы платформа может автоматически «обрезать» их (Trim), что мгновенно взведет флаг Модифицированность.
  3. Дата с миллисекундами. В редких случаях в СУБД попадают даты, содержащие доли секунд. Стандартные механизмы 1С работают с точностью до секунды. Обрезание миллисекунд при чтении — это тоже модификация объекта.

Влияние серверных событий: ПриЧтенииНаСервере

В управляемых формах крайне важно проверить обработчик ПриЧтенииНаСервере. Это событие происходит до того, как управление передается в ПриСозданииНаСервере или ПриОткрытии на клиенте. Если в этом обработчике происходит расчет каких-то итогов или заполнение дополнительных колонок табличной части, которые связаны с данными объекта, форма сразу станет «грязной».

Посмотрим на пример, как можно отловить момент изменения свойства. Используйте «Остановку по условию» в отладчике или добавьте в подозрительные места следующий фрагмент:


Если ЭтаФорма.Модифицированность Тогда
    // Здесь ставим точку останова
    Сообщить("Форма изменена!"); 
КонецЕсли;

Проблема табличных частей и значений по умолчанию

Разберем еще одну ситуацию: наличие «мусорных» данных в табличных частях. Иногда при открытии формы срабатывает инициализация строк. Если в табличной части есть скрытые колонки, которые заполняются значениями по умолчанию программно, и эти значения отличаются от физически записанных в базе (например, 0 вместо NULL), платформа пометит документ как измененный.

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


// Пример сравнения реквизита в форме и в базе
ОбъектВБазе = Объект.Ссылка.ПолучитьОбъект();
Для каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл
    Имя = Реквизит.Имя;
    Если Объект[Имя] <> ОбъектВБазе[Имя] Тогда
        Сообщить("Изменен реквизит: " + Имя);
    КонецЕсли;
КонецЦикла;

Заключение

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

← На главную