К статье
Практический материал

Разработка и Конфигурация · 11 мин

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

Как программно получить состав плана обмена в 1С: методы ПолучитьСостав, метаданные, выборка узлов, регистрация изменений. Примеры кода и типичные ошибки.

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

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

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

Что такое состав плана обмена и где он хранится

Состав плана обмена определяется на этапе разработки конфигурации: в конфигураторе откройте ветку «Планы обмена», выберите нужный план и на закладке «Основные» нажмите кнопку «Состав». Там перечислены все объекты метаданных, для которых включён обмен, и для каждого задан режим авторегистрации — «Разрешить» или «Запретить».

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

Физически состав плана — часть метаданных конфигурации, а не данных. Это значит, что изменить его программно в пользовательском режиме нельзя: состав задаётся только в конфигураторе. Программно доступно чтение состава и управление регистрацией изменений в рамках этого состава.

Получение состава через метаданные

Основной способ — обращение к коллекции Состав объекта метаданных плана обмена. Каждый элемент коллекции имеет свойство Метаданные (ссылка на объект метаданных) и АвтоРегистрация. Типичный код перебора выглядит так:

Функция ПолучитьСоставПланаОбмена(ИмяПлана) Экспорт

Результат = Новый Массив;

ПланМетаданные = Метаданные.ПланыОбмена.Найти(ИмяПлана);

Если ПланМетаданные = Неопределено Тогда

ВызватьИсключение "План обмена не найден: " + ИмяПлана;

КонецЕсли;

Для Каждого Элемент Из ПланМетаданные.Состав Цикл

Описание = Новый Структура;

Описание.Вставить("ИмяОбъекта", Элемент.Метаданные.Имя);

Описание.Вставить("ПолноеИмя", Элемент.Метаданные.ПолноеИмя());

Описание.Вставить("АвтоРегистрация", Элемент.АвтоРегистрация);

Результат.Добавить(Описание);

КонецЦикла;

Возврат Результат;

КонецФункции

Обратите внимание на предварительную проверку через Метаданные.ПланыОбмена.Найти(). Прямое обращение Метаданные.ПланыОбмена.МойПлан вызовет ошибку, если план с таким именем отсутствует в конфигурации — а в универсальных обработках, работающих с разными конфигурациями, это типовая ситуация.

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

Если Метаданные.ПланыОбмена.ОбменССайтом.Состав.Содержит(Метаданные.Справочники.Номенклатура) Тогда

// Номенклатура участвует в обмене

КонецЕсли;

Такая проверка выполняется быстро и безопасно, её удобно ставить перед регистрацией изменений: попытка зарегистрировать объект, не входящий в состав плана, приведёт к ошибке времени выполнения.

Проверка конкретного объекта и узла

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

Проверка одного объекта делается так:

Узел = ПланыОбмена.ОбменССайтом.НайтиПоКоду("001");

СсылкаНаТовар = Справочники.Номенклатура.НайтиПоКоду("00-000123");

Зарегистрирован = ПланыОбмена.ИзменениеЗарегистрировано(Узел, СсылкаНаТовар);

Метод вернёт Истина, если для пары «узел — объект» есть запись в таблице регистрации изменений. Это полезно при отладке: вы видите, дошёл ли объект до очереди выгрузки после записи.

Выборка всех зарегистрированных изменений по узлу выполняется через ВыбратьИзменения. Ей нужен номер сообщения — его берут из реквизита узла НомерОтправленного, увеличенный на единицу:

УзелОбъект = Узел.ПолучитьОбъект();

НомерСообщения = УзелОбъект.НомерОтправленного + 1;

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

Пока Выборка.Следующий() Цикл

Данные = Выборка.Получить();

// работа с данными

КонецЦикла;

Регистрация объектов в составе обмена программно

Обратная задача — добавить объект в очередь выгрузки. Перед регистрацией всегда проверяйте, что тип объекта входит в состав плана, иначе получите исключение:

Функция ЗарегистрироватьОбъектКВыгрузке(Узел, Ссылка) Экспорт

МетаданныеОбъекта = Ссылка.Метаданные();

Если Не Метаданные.ПланыОбмена.ОбменССайтом.Состав.Содержит(МетаданныеОбъекта) Тогда

Возврат Ложь; // тип не участвует в обмене

КонецЕсли;

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

Возврат Истина;

КонецФункции

Для массовой регистрации — например, первичной выгрузки всей номенклатуры на новый узел — удобно передавать в ЗарегистрироватьИзменения не ссылку, а объект метаданных. Тогда платформа зарегистрирует все существующие данные этого типа:

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

На больших таблицах такая операция может занять заметное время и создать миллионы записей регистрации. Выполняйте её вне пиковой нагрузки и желательно в транзакции с контролем результата.

Порядок действий для первичной выгрузки
  1. 1
    Получите состав плана через Метаданные.ПланыОбмена.ИмяПлана.Состав
  2. 2
    Отберите только нужные типы объектов, исключив служебные
  3. 3
    Для каждого типа вызовите ПланыОбмена.ЗарегистрироватьИзменения(Узел, МетаданныеОбъекта)
  4. 4
    Проверьте результат через ПланыОбмена.ВыбратьИзменения на тестовом узле
  5. 5
    Только после проверки запускайте процедуру на рабочем узле

Получение списка узлов плана обмена

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Обмен.Ссылка КАК Узел,

| Обмен.Код КАК Код,

| Обмен.Наименование КАК Наименование

|ИЗ

| ПланОбмена.ОбменССайтом КАК Обмен

|ГДЕ

| НЕ Обмен.ЭтотУзел

| И НЕ Обмен.ПометкаУдаления";

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

// обработка узла

КонецЦикла;

Отбор по ЭтотУзел = Ложь и по пометке удаления — обязательная гигиена любого кода, работающего с узлами. Помеченный на удаление узел может ещё физически существовать, но регистрировать на него изменения уже не нужно: это мусор в таблицах регистрации и лишняя нагрузка на выгрузку.

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

Контрольные точки

Как проверить результат

Состав плана в конфигураторе
Норма

Нужный тип объекта присутствует и авторегистрация настроена осознанно

Тревожный признак

Типа нет в составе — регистрация из кода вызовет ошибку

Регистрация изменений
Норма

ИзменениеЗарегистрировано(Узел, Ссылка) возвращает Истина после записи

Тревожный признак

Возвращает Ложь — проверьте авторегистрацию и отборы в подписках

Выборка изменений
Норма

ВыбратьИзменения возвращает ожидаемые объекты

Тревожный признак

Пустая выборка — изменения не регистрируются или уже выгружены

Типичные ошибки и ограничения

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

Вторая частая проблема — регистрация на предопределённом узле «этой базы». Изменения, зарегистрированные на самого себя, никуда не выгружаются, но занимают место в таблицах регистрации. При массовых операциях это приводит к заметному разрастанию базы.

Третий источник ошибок — непонимание разницы между составом метаданных и фактической регистрацией. Состав отвечает на вопрос «может ли тип обмениваться», регистрация — «какие объекты ждут выгрузки». Код, который читает состав и делает выводы о реальных данных очереди, работает неправильно.

Наконец, помните про ограничения контекста: обращение к метаданным и методам планов обмена требует серверного вызова в управляемом приложении. Клиентский код, пытающийся обратиться к Метаданные.ПланыОбмена напрямую, не скомпилируется.

Типичные ошибки
01
Регистрация объекта без проверки Состав.Содержит — исключение или молчаливый пропуск данных
02
Отсутствие фильтра ЭтотУзел при переборе узлов — регистрация изменений на собственную базу и разрастание таблиц
03
Использование ВыбратьИзменения с реальным номером сообщения в отладке — потеря очереди выгрузки на рабочем узле
04
Обращение к метаданным плана обмена из клиентского кода управляемой формы — ошибка компиляции

Частые вопросы

Можно ли изменить состав плана обмена программно?

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

Как узнать, какие объекты реально ждут выгрузки на узел?

Используйте ПланыОбмена.ВыбратьИзменения(Узел, НомерСообщения) с номером, равным НомерОтправленного узла плюс один. Для точечной проверки одного объекта подойдёт ПланыОбмена.ИзменениеЗарегистрировано(Узел, Ссылка).

Почему объект записывается, но не регистрируется к обмену?

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

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

Переберите коллекцию Метаданные.ПланыОбмена и для каждого плана читайте его Состав. Так строят универсальные обработки, работающие с любой конфигурацией без жёсткой привязки к именам.

Можно ли получить состав плана обмена через запрос?

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

Что делать, если таблицы регистрации изменений разрослись?

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

Итог

Что важно запомнить

Состав плана обмена читается через Метаданные.ПланыОбмена.ИмяПлана.Состав, принадлежность типа проверяется методом Содержит, а реальная очередь выгрузки — через ВыбратьИзменения и ИзменениеЗарегистрировано. Перед регистрацией всегда проверяйте состав и исключайте собственный узел из обработки.