При разработке механизмов синхронизации данных в системе 1С:Предприятие программисты часто сталкиваются с необходимостью вручную добавить записи в таблицу регистрации изменений плана обмена. Если для ссылочных типов данных (справочники, документы) эта процедура интуитивно понятна и выполняется через передачу ссылки, то работа с регистрами сведений имеет ряд особенностей. В этой статье мы подробно разберем, как правильно регистрировать изменения для регистров сведений, учитывая их структуру и способ записи данных.
Прежде чем переходить к коду, проанализируем, как 1С отслеживает изменения. Для каждого плана обмена платформа создает служебные таблицы регистрации. Когда мы вызываем метод ПланыОбмена.ЗарегистрироватьИзменения(), система добавляет запись в эту таблицу. Для регистров сведений единицей обмена является не одна запись, а набор записей, ограниченный определенным фильтром (отбором). Это критически важный момент для понимания логики работы.
Рассмотрим ситуацию, когда нам нужно зарегистрировать данные в независимом регистре сведений. В таких регистрах ключевыми полями являются измерения. Для программной регистрации мы должны использовать объект РегистрСведенийНаборЗаписей. Выясним, как это реализовать на практике.
Для начала создадим набор записей и установим необходимые фильтры по измерениям. Важно помнить: чтобы платформа могла зарегистрировать изменения по конкретным измерениям, у этих измерений в метаданных должен быть установлен флаг "Основной отбор".
// Создаем объект набора записей для нужного регистра
НаборЗаписей = РегистрыСведений.ЛичныеДанныеФизЛиц.СоздатьНаборЗаписей();
// Устанавливаем отбор по ключевому измерению (например, ФизЛицо)
НаборЗаписей.Отбор.ФизЛицо.Установить(СсылкаНаФизЛицо);
// Выполняем регистрацию изменений на конкретном узле плана обмена
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, НаборЗаписей);
Проанализируем этот пример. Мы не записываем данные в базу, а лишь подготавливаем "маску" отбора, по которой платформа поймет, какие именно записи регистра должны быть отправлены на узел УзелОбмена при следующем сеансе синхронизации.
Ситуация меняется, если регистр сведений является подчиненным (режим записи "Запись по регистратору"). В таких регистрах основным и зачастую единственным полем отбора является Регистратор. Попытка установить отбор по другим измерениям для целей регистрации приведет к ошибке, так как платформа ожидает именно документ-основание.
Разберем по шагам, как действовать в этом случае:
Регистратор.
// Пример для подчиненного регистра (например, РаботникиОрганизаций в ЗУП)
НаборЗаписей = РегистрыСведений.РаботникиОрганизаций.СоздатьНаборЗаписей();
// Устанавливаем отбор ТОЛЬКО по регистратору
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
// Регистрируем изменения
ПланыОбмена.ЗарегистрироватьИзменения(МойУзел, НаборЗаписей);
Если вам нужно зарегистрировать данные по конкретному сотруднику в подчиненном регистре, вам сначала придется найти все регистраторы (документы), которые делали записи по этому сотруднику (например, с помощью запроса), и зарегистрировать каждый набор записей по этим регистраторам отдельно.
В среде разработчиков часто возникает спор: нужно ли вызывать метод НаборЗаписей.Прочитать() перед регистрацией изменений? Проанализируем техническую сторону вопроса. Метод ЗарегистрироватьИзменения анализирует только метаданные набора и его отбор. Сами данные, содержащиеся в памяти объекта (коллекция записей), в момент регистрации в таблицу регистрации не записываются. Они будут прочитаны из базы данных непосредственно в момент формирования файла обмена (выгрузки).
Следовательно, вызов НаборЗаписей.Прочитать() является избыточным и лишь создает лишнюю нагрузку на сервер БД. Однако, если ваша логика подразумевает проверку наличия записей перед регистрацией, использование этого метода оправдано.
Существует еще один, более "легковесный" способ регистрации для независимых регистров — использование объекта РегистрСведенийКлючЗаписи. Это удобно, когда нужно зарегистрировать ровно одну строку регистра, зная значения всех её измерений.
Посмотрим на пример реализации:
// Формируем структуру со значениями всех измерений
ПараметрыКлюча = Новый Структура;
ПараметрыКлюча.Вставить("ФизЛицо", СсылкаФизЛицо);
ПараметрыКлюча.Вставить("ВидДокумента", СсылкаВидДокумента);
// Создаем ключ записи
КлючЗаписи = РегистрыСведений.ПаспортныеДанные.СоздатьКлючЗаписи(ПараметрыКлюча);
// Регистрируем изменения по ключу
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, КлючЗаписи);
Этот метод работает быстрее, чем создание набора записей, так как требует меньше ресурсов системы для инициализации объекта.
Иногда требуется отправить на узел абсолютно все данные конкретного регистра (например, при инициализации нового узла или пересчете остатков). В этом случае не нужно перебирать записи или создавать наборы. Рассмотрим самый эффективный способ — регистрацию по метаданным.
Достаточно передать объект метаданных регистра в качестве второго параметра:
// Регистрируем весь регистр целиком для узла
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Метаданные.РегистрыСведений.КурсыВалют);
Это действие мгновенно создаст одну запись в таблице регистрации, указывающую на необходимость выгрузки всей таблицы регистра для данного узла.
Проанализируем ситуацию, с которой часто сталкиваются новички: "Поле не найдено" при установке отбора. Если вы пытаетесь установить отбор по измерению Сотрудник, а система выдает ошибку, проверьте тип регистра. Скорее всего, регистр подчинен регистратору, и в его Отбор доступно только поле Регистратор. В этом случае, как мы выяснили выше, регистрация возможна только через документ.
Также обратите внимание на флаг "Основной отбор" в свойствах измерений независимого регистра. Если этот флаг снят у всех измерений, платформа не позволит зарегистрировать "часть" регистра через набор записей с фильтром — вам придется либо регистрировать весь регистр через метаданные, либо каждую запись отдельно через ключ записи.
Подводя итог, выбор метода регистрации зависит от типа регистра и объема данных. Использование РегистрСведенийНаборЗаписей является универсальным и наиболее распространенным подходом, обеспечивающим гибкость через механизмы отборов. Если требуется выполнить регистрацию данных и связанных объектов без написания кода, можно использовать обработку для массовой регистрации объектов к обмену.