Как проверить изменение определенного реквизита или табличной части справочника в 1С

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

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

Способ 1. Сравнение текущего значения объекта и значения из базы через свойство Ссылка

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

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

Рассмотрим важные нюансы, которые необходимо учесть:

  1. Проверка на новый элемент: Если создается новый элемент справочника, метод ЭтоНовый() возвращает Истина. В этом случае обращение к реквизитам через ссылку не имеет смысла, так как объекта в базе еще не существует.
  2. Производительность: Обращение вида Ссылка.ИмяРеквизита считывает из базы всю запись объекта целиком в кэш. Если требуется проверить только один-два реквизита у единичного объекта, это не создает заметной нагрузки.

Посмотрим на пример кода в модуле справочника:


Процедура ПередЗаписью(Отказ)
    
    Если Не ЭтоНовый() Тогда
        // Проверяем, изменился ли конкретный реквизит
        Если Реквизит1 <> Ссылка.Реквизит1 Тогда
            // Выполняем необходимое действие при изменении
            ЗафиксироватьИзменениеРеквизита(Ссылка, Реквизит1, Ссылка.Реквизит1);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Способ 2. Проверка изменения группы реквизитов через запрос

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

Разберем по шагам, как это реализовать в модуле объекта или в подписке на событие:

  1. Проверяем, что объект не является новым.
  2. Формируем запрос к таблице справочника с отбором по текущей ссылке.
  3. Выбираем только те поля, изменение которых необходимо отследить.
  4. Сравниваем поля выборки с текущими значениями объекта.

Посмотрим на пример реализации:


Процедура ПередЗаписью(Отказ)
    
    Если ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Спр.Реквизит1 КАК Реквизит1,
        |   Спр.Реквизит2 КАК Реквизит2,
        |   Спр.Статус КАК Статус
        |ИЗ
        |   Справочник.Номенклатура КАК Спр
        |ГДЕ
        |   Спр.Ссылка = &Ссылка";
        
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Если Реквизит1 <> Выборка.Реквизит1 Тогда
            // Изменился Реквизит1
        КонецЕсли;
        
        Если Статус <> Выборка.Статус Тогда
            // Изменился Статус
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Проверка изменения табличной части через временные таблицы в запросе

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

Разберем алгоритм запроса:

  1. Выгружаем текущую табличную часть объекта в таблицу значений с помощью метода Выгрузить().
  2. Передаем полученную таблицу значений в запрос как параметр.
  3. Используем конструкцию ПОЛНОЕ СОЕДИНЕНИЕ между переданной таблицей и реальной табличной частью объекта из базы (Справочник.ИмяСправочника.ИмяТЧ) по ключевым реквизитам или номерам строк.
  4. Если в результате соединения обнаруживаются поля со значением NULL или расхождения в значениях реквизитов, значит, строки были добавлены, удалены или изменены.

Посмотрим на пример кода проверки табличной части:


Функция ТабличнаяЧастьИзменена(Объект)
    
    Если Объект.ЭтоНовый() Тогда
        Возврат Истина;
    КонецЕсли;
    
    МенеджерВТ = Новый МенеджерВременныхТаблиц;
    
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ТЧ_Текущая.Номенклатура КАК Номенклатура,
        |   ТЧ_Текущая.Количество КАК Количество,
        |   ТЧ_Текущая.Цена КАК Цена
        |ПОМЕСТИТЬ ВТ_ТекущиеДанные
        |ИЗ
        |   &ТЧ КАК ТЧ_Текущая
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |   1 КАК ЕстьРазличия
        |ИЗ
        |   ВТ_ТекущиеДанные КАК Тек
        |       ПОЛНОЕ СОЕДИНЕНИЕ Справочник.Спецификации.Состав КАК База
        |       ПО Тек.Номенклатура = База.Номенклатура
        |           И (База.Ссылка = &Ссылка)
        |ГДЕ
        |   Тек.Номенклатура ЕСТЬ NULL
        |   ИЛИ База.Номенклатура ЕСТЬ NULL
        |   ИЛИ Тек.Количество <> База.Количество
        |   ИЛИ Тек.Цена <> База.Цена";
        
    Запрос.УстановитьПараметр("ТЧ", Объект.Состав.Выгрузить());
    Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
    
    Результат = Запрос.Выполнить();
    Возврат Не Результат.Пустой();
    
КонецФункции

Способ 4. Проверка на клиенте в управляемой форме

Если требуется отреагировать на изменение реквизита непосредственно в момент ввода пользователем (до нажатия кнопки «Записать»), используются средства управляемой формы:

  1. Событие ПриИзменении: Назначается на конкретный элемент управления (поле ввода, флажок, переключатель). Код выполняется сразу после того, как пользователь завершил редактирование значения в элементе.
  2. Фиксация исходного состояния: В обработчике ПриЧтенииСозданииНаСервере или ПриСозданииНаСервере начальные значения критически важных реквизитов можно сохранить в реквизит формы типа Структура. Перед отправкой данных на сервер или при валидации сравниваем текущие данные на форме с сохраненной структурой.

Таким образом, для простых проверок единичных реквизитов достаточно использовать сравнение Реквизит <> Ссылка.Реквизит в событии ПередЗаписью, а при масштабном контроле реквизитов и табличных частей оптимально применять пакетные запросы с временными таблицами.

← На главную