При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда стандартное свойство управляемой формы Модифицированность возвращает Истина, даже если пользователь визуально ничего не менял. Это создает сложности, если нам нужно выполнить определенные действия или проверки только при наличии реальных правок в документе или справочнике. Разберем детально, почему так происходит и как корректно определить факт изменения данных.
В идеальной ситуации свойство Модифицированность должно сигнализировать о том, что данные в форме отличаются от данных в базе. Визуально это подтверждается появлением символа "*" в заголовке окна. Однако на практике мы часто наблюдаем картину, когда "звездочки" нет, а программная проверка в обработчике ПередЗаписью выдает Истина. Проанализируем основные причины такого поведения.
Это самая распространенная и неочевидная причина. Рассмотрим ситуацию: в форме создана пользовательская кнопка (команда) для записи объекта. В свойствах этой команды в конфигураторе есть флаг «Изменяет сохраняемые данные».
Когда этот флаг установлен, платформа автоматически устанавливает Модифицированность = Истина в тот момент, когда пользователь нажимает на кнопку, но до начала выполнения программного кода в обработчике команды. Таким образом, когда управление попадает в процедуру ПередЗаписью, форма уже считается измененной самой платформой.
Как это проверить и исправить:
Изменяет сохраняемые данные.Часто модифицированность становится истинной из-за неосторожного кода в обработчиках ПриСозданииНаСервере, ПриЧтенииНаСервере или ПриОткрытии. Проанализируем ситуацию: если мы программно присваиваем значение реквизиту объекта, платформа помечает объект как измененный.
Рассмотрим пример "плохого" кода:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// Это присваивание установит Модифицированность = Истина,
// даже если значение совпадает с тем, что в базе
Объект.Ответственный = ПараметрыСеанса.ТекущийПользователь;
КонецПроцедуры
Чтобы избежать этой проблемы, всегда используйте проверку перед присваиванием:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
Если Объект.Ответственный <> ПараметрыСеанса.ТекущийПользователь Тогда
Объект.Ответственный = ПараметрыСеанса.ТекущийПользователь;
КонецЕсли;
КонецПроцедуры
Если мы не понимаем, в какой момент форма становится модифицированной, воспользуемся отладчиком. Разберем по шагам алгоритм поиска:
ПриОткрытии.Модифицированность.Ложь на Истина, мы найдем строку кода, вносящую изменения.Если же модифицированность становится истинной при нажатии на кнопку записи (как в случае автора темы), проверку нужно делать в обработчике команды до вызова стандартных процедур записи.
Если нам критически важно знать, изменил ли пользователь хоть один байт информации, полагаться на стандартное свойство Модифицированность нельзя. Проанализируем более надежный метод — сравнение текущего состояния объекта с его версией в базе данных.
Для этого нам потребуется серверная функция. Посмотрим на пример реализации:
&НаСервере
Функция ДанныеДействительноИзменены()
// Если ссылка пустая, значит объект новый, он точно изменен
Если Объект.Ссылка.Пустая() Тогда
Возврат Истина;
КонецЕсли;
// Получаем текущее состояние объекта из базы данных
ОбъектИзБазы = Объект.Ссылка.ПолучитьОбъект();
// Сравниваем основные реквизиты.
// Можно перечислить конкретные важные реквизиты или обойти метаданные
Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл
Если Объект[Реквизит.Имя] <> ОбъектИзБазы[Реквизит.Имя] Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
// Не забываем про табличные части, если они важны
// Сравнение ТЧ — более трудоемкий процесс, требующий выгрузки в таблицы значений
Возврат Ложь;
КонецФункции
Этот метод работает безотказно, так как он игнорирует "техническую" модифицированность формы и проверяет фактическую разницу в значениях реквизитов.
Стоит упомянуть, что при использовании расширений конфигурации (как в примере из темы), поведение может усложняться. Обработчики с типом &НаКлиенте &Перед могут срабатывать раньше, чем основной код формы. Если вы пишете расширение для типовой конфигурации (например, УТ 11), помните, что многие типовые механизмы записи используют общие модули (например, ОбщегоНазначенияУТКлиент.Записать).
В таких случаях модифицированность может взводиться внутри типового кода из-за заполнения служебных параметров. Если ваша задача — выполнить проверку до того, как типовой механизм начнет менять объект, делайте свои замеры в самом начале цепочки вызовов.
Для корректной работы с модифицированностью мы рекомендуем:
Если Объект.Поле <> Значение Тогда) при программной установке данных.Использование этих подходов позволит избежать ложных срабатываний и сделает работу вашей системы более предсказуемой и стабильной.