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

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

При настройке планов обмена разработчики часто сталкиваются с ситуацией, когда авторегистрация изменений для определенного регистра сведений отключена, и требуется выполнять регистрацию программно. Разберем распространенную проблему: код написан, набор записей создан, отборы установлены, вызывается метод ПланыОбмена.ЗарегистрироватьИзменения, но изменения для узла не регистрируются, при этом система не выдает никаких ошибок. Проанализируем причины такого поведения и рассмотрим рабочие способы программной регистрации данных регистра сведений.

Анализ проблемы: почему изменения не регистрируются?

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

  1. Строгое соответствие свойству "Основной отбор". При передаче набора записей в метод регистрации, состав элементов отбора должен строго соответствовать тем измерениям, у которых в конфигураторе установлен признак "Основной отбор". Если вы установите отбор по измерению, у которого этот флаг снят, или пропустите измерение, у которого он установлен, платформа не зарегистрирует изменение. Более того, в некоторых случаях это может привести к ошибке "Недопустимое значение параметра 2".
  2. Периодические регистры. Если регистр сведений является периодическим, обратите внимание на свойство "Основной отбор по периоду" в метаданных. Если этот флаг включен, то поле Период также становится обязательным участником отбора при ручной регистрации.
  3. Влияние БСП (Библиотеки стандартных подсистем). В современных типовых конфигурациях прямой вызов системного метода может перекрываться правилами регистрации данных (ПРД). Типовые подписки на события могут очищать узлы-получатели, если данные не проходят фильтрацию по правилам. В таких случаях нужно использовать программный API БСП (например, модуль ОбменДаннымиСервер).

Способ 1: Регистрация с использованием набора записей (с учетом всех отборов)

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    КомплектующиеНоменклатуры.Номенклатура,
    |    КомплектующиеНоменклатуры.ХарактеристикаНоменклатуры
    |ИЗ
    |    РегистрСведений.КомплектующиеНоменклатуры КАК КомплектующиеНоменклатуры";

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

Способ 2: Использование Ключа записи (Рекомендуемый для независимых регистров)

Вместо громоздкого создания набора записей и поштучной установки отборов, гораздо удобнее и надежнее использовать объект РегистрСведенийКлючЗаписи. Метод ЗарегистрироватьИзменения отлично понимает этот тип данных. Этот способ идеален при обходе результатов запроса или когда известны конкретные значения измерений.

Разберем по шагам, как это реализовать:


// Создаем структуру с именами и значениями измерений ключа
ЗначенияКлюча = Новый Структура;
ЗначенияКлюча.Вставить("Измерение1", Значение1);
ЗначенияКлюча.Вставить("Измерение2", Значение2);
ЗначенияКлюча.Вставить("Измерение3", Значение3);

// Получаем ключ записи регистра
КлючЗаписи = РегистрыСведений.ИмяВашегоРегистра.СоздатьКлючЗаписи(ЗначенияКлюча);

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

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

Способ 3: Регистрация внутри модуля набора записей (Штатный механизм)

Если вам нужно регистрировать изменения в момент записи самого регистра (например, при программной загрузке данных или обработке проведения), нет необходимости вызывать глобальный метод ПланыОбмена.ЗарегистрироватьИзменения. Вместо этого следует работать с коллекцией ОбменДанными.Получатели самого набора записей. Это делается в обработчиках событий ПередЗаписью или ПриЗаписи модуля набора записей регистра.

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


Процедура ПередЗаписью(Отказ, Замещение)
    
    // Опционально: анализ данных перед регистрацией
    // Например, регистрируем только если ресурс содержит определенное значение
    
    Для Каждого Узел Из МассивУзловДляРегистрации Цикл
        // Добавляем узел в получатели для текущего набора записей
        ЭтотОбъект.ОбменДанными.Получатели.Добавить(Узел);
    КонецЦикла;

КонецПроцедуры

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

Особые случаи: подчинение регистратору и отсутствие основного отбора

Проанализируем нестандартные ситуации:

  1. Регистры, подчиненные регистратору. Для таких регистров правила кардинально меняются. Изменения наборов записей регистрируются не по измерениям, а исключительно по установленному отбору поля Регистратор. Значения измерений в отборе игнорируются, и гранулой обмена выступает документ-регистратор. Регистрировать изменения в таком случае нужно передавая ссылку на сам документ-регистратор.
  2. Отсутствие измерений с основным отбором. Если в структуре независимого регистра ни у одного из измерений не установлен признак "Основной отбор", то гранулой регистрации становится вся таблица целиком. В этом случае для регистрации передается пустой набор записей (без установленных отборов).
← На главную