Как вручную отследить изменение конкретных реквизитов и табличных частей в 1С

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

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

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

Метод 1: Сравнение через «ДополнительныеСвойства» объекта

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

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


// В модуле объекта или при инициализации
ДополнительныеСвойства.Вставить("СтарыеЗначения", Новый Структура("Склад, Контрагент, СуммаДокумента"));
ЗаполнитьЗначенияСвойств(ДополнительныеСвойства.СтарыеЗначения, ЭтотОбъект);

Затем, непосредственно перед записью, мы сравниваем текущие значения с сохраненными. Проанализируем ситуацию в обработчике ПередЗаписью:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    Если ДополнительныеСвойства.Свойство("СтарыеЗначения") Тогда
        СтарыеДанные = ДополнительныеСвойства.СтарыеЗначения;
        
        Если ЭтотОбъект.Склад <> СтарыеДанные.Склад 
            Или ЭтотОбъект.Контрагент <> СтарыеДанные.Контрагент Тогда
            
            // Логика, если значимые реквизиты изменились
            ЭтотОбъект.ТребуетсяПеревыгрузка = Истина;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

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

Метод 2: Использование ссылки для сравнения с данными в БД

Если объект уже существует в базе (не новый), мы можем сравнить текущие данные объекта в памяти с теми, что еще записаны в базе данных, обратившись к ним через Ссылка. Рассмотрим этот пример подробнее:

Этот способ хорош тем, что нам не нужно ничего хранить в памяти при открытии. Мы просто делаем запрос к базе в момент записи. Выясним, как это выглядит на практике:


// Пример сравнения реквизитов через ссылку
Если НЕ ЭтоНовый() Тогда
    ДанныеБД = Ссылка.ПолучитьОбъект(); // Или лучше использовать Запрос для экономии ресурсов
    
    Если ЭтотОбъект.Организация <> ДанныеБД.Организация Тогда
        // Реквизит изменен
    КонецЕсли;
КонецЕсли;

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

Метод 3: Сериализация и вычисление Хеш-суммы

Когда список отслеживаемых параметров велик или включает табличные части, ручное сравнение каждого поля становится неэффективным. Здесь на помощь приходит хеширование. Суть метода: собрать все значимые данные в одну строку или структуру, сериализовать её в XML или JSON и вычислить короткий хеш (контрольную сумму).

Рассмотрим пошагово, как реализовать универсальную функцию получения хеша для части объекта:

  1. Выбираем значимые реквизиты и выгружаем их в структуру.
  2. Для табличных частей используем метод Выгрузить(), чтобы получить таблицу значений.
  3. Сериализуем полученные данные в строку.
  4. Вычисляем хеш.

Пример реализации функции получения контрольной суммы (используя встроенные средства платформы 8.3):


Функция ПолучитьХешСостояния(ДокОбъект) Экспорт
    
    // Собираем данные в структуру для сериализации
    ДанныеДляКонтроля = Новый Структура;
    ДанныеДляКонтроля.Вставить("Склад", ДокОбъект.Склад);
    ДанныеДляКонтроля.Вставить("Товары", ДокОбъект.Товары.Выгрузить());
    
    // Используем ЗаписьXML для превращения данных в строку
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ДанныеДляКонтроля);
    СтрокаДанных = ЗаписьXML.Закрыть();
    
    // Вычисляем хеш-сумму. 
    // Внимание: CRC32 может давать коллизии, для надежности используйте SHA256
    Хеширование = Новый ХешированиеДанных(ХешФункция.SHA256);
    Хеширование.Добавить(СтрокаДанных);
    
    Возврат НРег(СтрЗаменить(Строка(Хеширование.ХешСумма), " ", ""));
КонецФункции

Теперь мы можем сохранить этот хеш при открытии формы в переменную, а при записи — вычислить его заново и сравнить с исходным. Если строки не совпадают — значит, в "значимой" части документа произошли изменения.

Метод 4: Работа с табличными частями через Запрос

Если табличные части документа содержат тысячи строк, сериализация их в XML может быть медленной. В таких случаях проанализируем альтернативный путь: использование временных таблиц в запросе. Мы можем передать текущую табличную часть как параметр запроса и сравнить её с данными в базе данных с помощью оператора ПОЛНОЕ СОЕДИНЕНИЕ.

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

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

Этот метод считается наиболее производительным для "тяжелых" документов, так как вся работа по сравнению ложится на плечи СУБД, а не интерпретатора 1С.

Современные подходы и рекомендации

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

Если же вы создаете свою систему мониторинга, обратите внимание на следующие советы:

Таким образом, мы рассмотрели основные инструменты для "ручного" контроля изменений. Выбор конкретного метода зависит от объема данных: для пары реквизитов хватит ДополнительныхСвойств, для сложной структуры — Хеширования, а для больших таблиц — Запросов.

← На главную