Как найти причину изменения документа при открытии формы в 1С?

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

Нередко разработчики сталкиваются с ситуацией в обычных формах платформы 1С:Предприятие (например, в конфигурации «Управление производственным предприятием 1.3»), когда сразу после открытия существующего документа в заголовке появляется звездочка, а свойство ЭтаФорма.Модифицированность принимает значение Истина. При попытке закрыть такой документ без каких-либо действий пользователя система начинает выдавать предупреждение о несохраненных данных. Разберем по шагам, как выявить причину такой модифицированности и устранить её.

Способ 1. Использование замера производительности для локализации места изменения

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

Разберем алгоритм поиска строки, изменяющей данные:

  1. Откроем конфигуратор и запустим отладку.
  2. Поставим две контрольные точки останова в модуле формы документа: первую — в процедуре, где свойство ЭтаФорма.Модифицированность еще равно Ложь (например, в начале обработчика ОбновлениеОтображения или в событии ПередОткрытием), а вторую — в обработчике, где флаг уже взведен в значение Истина (например, в процедуре ПриВыводеСтроки табличного поля).
  3. Откроем документ в режиме «1С:Предприятие» и дождемся остановки на первой точке.
  4. В конфигураторе включим замер производительности через меню Отладка — Замер производительности.
  5. Нажмем клавишу продолжения отладки (F5), чтобы программа дошла до второй точки останова.
  6. Остановим замер производительности и внимательно проанализируем сформированный отчет.

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

Способ 2. Сравнение данных объекта в памяти с версией из базы данных

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

Посмотрим на пример отладочного кода для перебора и сравнения реквизитов шапки:


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

Аналогичным образом можно обойти строки табличных частей и сопоставить значения колонок. Однако следует учитывать, что свойство ЭтаФорма.Модифицированность может принять значение Истина даже при обычном присвоении реквизита самому себе (например, Организация = Организация;) или при изменении элемента управления с установленным свойством Изменяет данные.

Типичные причины самопроизвольной модифицированности документа

Выясним наиболее распространенные источники проблемы в типовых и доработанных конфигурациях:

  1. Переназначение типов незаполненных полей аналитики и составных типов. Это характерно для УПП и других комплексных систем. При открытии формы код типовых механизмов может проверять составные реквизиты (например, аналитику учета затрат, статьи, субконто) и принудительно задавать для них пустые ссылки конкретного типа вместо значения Неопределено или другого типа. Такое присвоение платформа расценивает как изменение данных объекта.
  2. Неправильный выбор события жизненного цикла формы. Платформа автоматически сбрасывает флаг модифицированности формы между событиями ПередОткрытием и ПриОткрытии. Если инициализация реквизитов, заполнение значений по умолчанию или расчет дополнительных параметров выполняются в процедуре ПриОткрытии, форма помечается измененной.
  3. Изменение данных строки в обработчиках отрисовки таблицы. Если внутри событий ПриВыводеСтроки или ПриПолученииДанных разработчик обращается к источнику ДанныеСтроки.ИмяКолонки = ..., изменяются сами данные объекта. Для вывода рассчитанных или визуальных данных необходимо использовать оформление ячейки: ОформлениеСтроки.Ячейки.ИмяКолонки.УстановитьТекст(...) или ОформлениеСтроки.Ячейки.ИмяКолонки.Значение = ....
  4. Связи по типу и параметры выбора в элементах формы. Настроенная «Связь по типу» у элемента управления может автоматически откорректировать тип поля ввода при визуализации, если в реквизите хранилось пустое значение другого допустимого типа.

Варианты корректного исправления

Рассмотрим, как правильно устранить лишнюю модифицированность в коде формы:

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

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

Важно помнить о разнице между ЭтаФорма.Модифицированность (свойство формы, которое можно перезаписать) и методом ЭтотОбъект.Модифицированность() (функция объекта, возвращающая реальное состояние данных объекта в памяти относительно базы данных).

← На главную