Как программно изменить или сбросить номер сообщения в таблице регистрации изменений?

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

При работе с распределенными информационными базами (РИБ) или произвольными планами обмена в 1С:Предприятие 8.3 разработчики часто сталкиваются с необходимостью управлять состоянием регистрации изменений. Одной из специфических задач является изменение или «сброс» номера сообщения для объектов, которые уже были включены в пакет выгрузки, но по каким-то причинам должны быть выгружены снова. В этой статье мы подробно разберем, как устроена таблица изменений, за что отвечает поле НомерСообщения и какими программными способами можно им манипулировать.

Механизм работы таблицы регистрации изменений

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

  1. Узел — ссылка на узел плана обмена, для которого зарегистрировано изменение.
  2. Номер сообщения — числовое поле, которое изначально равно NULL.

Проанализируем жизненный цикл записи в этой таблице. Когда данные только изменяются в базе, платформа записывает ссылку в таблицу изменений и устанавливает НомерСообщения в значение NULL. Это означает, что изменение «новое» и еще не выгружалось. В момент вызова метода ВыбратьИзменения() платформа берет все записи с NULL и заменяет его на номер сообщения, который вы передали в параметрах метода. Таким образом, записи «помечаются» как отправленные в конкретном пакете.

Способ 1: Сброс номера сообщения через повторную регистрацию

Если нам необходимо программно сбросить НомерСообщения обратно в NULL для конкретной записи (чтобы объект снова считался «новым» и ушел со следующим обменом), самым правильным и безопасным способом является повторная регистрация изменений. Рассмотрим, как это реализовать программно.

Выясним причину, почему это работает: метод ЗарегистрироватьИзменения() выполняет операцию «Insert or Update». Если запись для данного узла и объекта уже существует, платформа просто обновляет её, при этом поле НомерСообщения принудительно очищается (устанавливается в NULL).

Разберем пример кода для справочника Номенклатура:


// Определим узел, для которого нужно сбросить номера сообщений
УзелСсылка = ПланыОбмена.СинхронизацияДанных.НайтиПоНаименованию("Узел для обмена");

// Объект, регистрацию которого нужно изменить
ОбъектСсылка = Справочники.Номенклатура.НайтиПоКоду("00001");

// Выполняем повторную регистрацию
ПланыОбмена.ЗарегистрироватьИзменения(УзелСсылка, ОбъектСсылка);

После выполнения этого кода в таблице регистрации изменений для данного узла поле НомерСообщения у записи с номенклатурой станет равным NULL. Это наиболее «чистый» способ решения задачи, так как он использует штатные механизмы платформы.

Способ 2: Удаление регистрации изменений

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

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


// Удаление регистрации конкретного объекта для конкретного узла
УзелСсылка = ПланыОбмена.СинхронизацияДанных.НайтиПоНаименованию("Филиал_Север");
ОбъектСсылка = Справочники.Контрагенты.НайтиПоНаименованию("Тестовый контрагент");

ПланыОбмена.УдалитьРегистрациюИзменений(УзелСсылка, ОбъектСсылка);

Важно помнить: если вы укажете только первый параметр (Узел), то будет удалена вся регистрация изменений для этого узла по всем объектам. Будьте осторожны с этим методом в рабочей базе.

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

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


УзелОбмена = ПланыОбмена.СинхронизацияДанных.НайтиПоНаименованию("Узел_Офис");
НомерСбойногоСообщения = 100;

// Выбираем изменения, которые были закреплены за конкретным номером сообщения
ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена, НомерСбойногоСообщения);

Пока ВыборкаИзменений.Следующий() Цикл
    Данные = ВыборкаИзменений.Получить();
    
    // Если это справочник, перерегистрируем его, чтобы сбросить номер сообщения
    Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Данные)) Тогда
        ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Данные);
        Сообщить("Сброшен номер сообщения для: " + Данные);
    КонецЕсли;
КонецЦикла;

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

Важные замечания о целостности данных

Во-первых, никогда не пытайтесь изменить номер сообщения напрямую через SQL-запросы к таблицам базы данных (например, к таблицам вида _ReferenceChngR). Это нарушает логику работы платформы 1С и может привести к непредсказуемым ошибкам, вплоть до невозможности дальнейшего использования узла обмена без его полной переинициализации.

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

Использование стандартных инструментов для анализа

Если вы не хотите писать код для разовой операции, рекомендуем использовать универсальную обработку «Регистрация изменений для обмена данными», которая входит в состав «Библиотеки стандартных подсистем» (БСП). С её помощью можно визуально проанализировать, какие объекты зарегистрированы, какие номера сообщений им присвоены, и там же можно выполнить «отмену регистрации» или «перерегистрацию» выделенных строк, что фактически выполнит те действия, которые мы разобрали выше.

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

← На главную