Как проверить, были ли реально изменены данные перед записью объекта в 1С?

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

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

Механизм модифицированности: ожидание и реальность

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

Причина 1: Свойство команды «Изменяет сохраняемые данные»

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

Когда этот флаг установлен, платформа автоматически устанавливает Модифицированность = Истина в тот момент, когда пользователь нажимает на кнопку, но до начала выполнения программного кода в обработчике команды. Таким образом, когда управление попадает в процедуру ПередЗаписью, форма уже считается измененной самой платформой.

Как это проверить и исправить:

  1. Найдем команду, которая инициирует запись.
  2. В палитре свойств найдем пункт Изменяет сохраняемые данные.
  3. Если флаг стоит, платформа всегда будет считать форму измененной при нажатии. Чтобы избежать этого, флаг можно снять, но тогда нам придется вручную отслеживать состояние формы и доступность команды в режиме "Только просмотр".

Причина 2: Скрытое изменение реквизитов при открытии

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

Рассмотрим пример "плохого" кода:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // Это присваивание установит Модифицированность = Истина, 
    // даже если значение совпадает с тем, что в базе
    Объект.Ответственный = ПараметрыСеанса.ТекущийПользователь;
КонецПроцедуры

Чтобы избежать этой проблемы, всегда используйте проверку перед присваиванием:


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

Как найти виновника изменения данных?

Если мы не понимаем, в какой момент форма становится модифицированной, воспользуемся отладчиком. Разберем по шагам алгоритм поиска:

  1. Установим точку останова в самом начале процедуры ПриОткрытии.
  2. Откроем окно "Табло" (Ctrl+Alt+W) и добавим туда выражение Модифицированность.
  3. Будем пошагово выполнять код (клавиша F10), следя за значением в Табло.
  4. Как только значение изменится с Ложь на Истина, мы найдем строку кода, вносящую изменения.

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

Универсальный способ проверки реальных изменений

Если нам критически важно знать, изменил ли пользователь хоть один байт информации, полагаться на стандартное свойство Модифицированность нельзя. Проанализируем более надежный метод — сравнение текущего состояния объекта с его версией в базе данных.

Для этого нам потребуется серверная функция. Посмотрим на пример реализации:


&НаСервере
Функция ДанныеДействительноИзменены()
    
    // Если ссылка пустая, значит объект новый, он точно изменен
    Если Объект.Ссылка.Пустая() Тогда
        Возврат Истина;
    КонецЕсли;
    
    // Получаем текущее состояние объекта из базы данных
    ОбъектИзБазы = Объект.Ссылка.ПолучитьОбъект();
    
    // Сравниваем основные реквизиты. 
    // Можно перечислить конкретные важные реквизиты или обойти метаданные
    Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл
        Если Объект[Реквизит.Имя] <> ОбъектИзБазы[Реквизит.Имя] Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;
    
    // Не забываем про табличные части, если они важны
    // Сравнение ТЧ — более трудоемкий процесс, требующий выгрузки в таблицы значений
    
    Возврат Ложь;
КонецФункции

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

Особенности расширений в 1С

Стоит упомянуть, что при использовании расширений конфигурации (как в примере из темы), поведение может усложняться. Обработчики с типом &НаКлиенте &Перед могут срабатывать раньше, чем основной код формы. Если вы пишете расширение для типовой конфигурации (например, УТ 11), помните, что многие типовые механизмы записи используют общие модули (например, ОбщегоНазначенияУТКлиент.Записать).

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

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

Для корректной работы с модифицированностью мы рекомендуем:

Использование этих подходов позволит избежать ложных срабатываний и сделает работу вашей системы более предсказуемой и стабильной.

← На главную