Разработка и Конфигурация · 11 мин
Как получить состав плана обмена 1С программно
Как программно получить состав плана обмена в 1С: методы ПолучитьСостав, метаданные, выборка узлов, регистрация изменений. Примеры кода и типичные ошибки.
Состав плана обмена в 1С — это перечень объектов метаданных (справочников, документов, регистров), которые участвуют в синхронизации между узлами распределённой базы или с внешними системами. Программный доступ к составу нужен, когда вы пишете универсальные обработчики обмена, проверяете корректность настройки плана, формируете отчёты о том, какие данные реально синхронизируются, или динамически регистрируете изменения для выгрузки.
Получить состав можно двумя принципиально разными способами: через метаданные конфигурации (объект Метаданные.ПланыОбмена.ИмяПлана.Состав) и через механизм регистрации изменений на конкретном узле. Первый способ отвечает на вопрос «какие типы объектов вообще могут обмениваться», второй — «какие конкретные объекты зарегистрированы к выгрузке на данный узел». Путать эти задачи — одна из самых частых ошибок начинающих разработчиков.
Ниже разобраны оба подхода с рабочими примерами кода, способы проверить результат через конфигуратор и типовые сценарии: выборка узлов, проверка принадлежности объекта плану, массовая регистрация данных. Все примеры написаны для управляемого приложения, но работают и в обычном, поскольку используют серверный контекст.
Что такое состав плана обмена и где он хранится
Состав плана обмена определяется на этапе разработки конфигурации: в конфигураторе откройте ветку «Планы обмена», выберите нужный план и на закладке «Основные» нажмите кнопку «Состав». Там перечислены все объекты метаданных, для которых включён обмен, и для каждого задан режим авторегистрации — «Разрешить» или «Запретить».
Режим авторегистрации критически важен для понимания поведения системы. Если авторегистрация разрешена, платформа автоматически регистрирует изменения объекта на всех подходящих узлах при записи. Если запрещена — регистрировать изменения нужно вручную через ПланыОбмена.ЗарегистрироватьИзменения(), иначе объект никогда не уйдёт в выгрузку. Программно вы можете прочитать этот режим через свойство АвтоРегистрация элемента состава.
Физически состав плана — часть метаданных конфигурации, а не данных. Это значит, что изменить его программно в пользовательском режиме нельзя: состав задаётся только в конфигураторе. Программно доступно чтение состава и управление регистрацией изменений в рамках этого состава.
Получение состава через метаданные
Основной способ — обращение к коллекции Состав объекта метаданных плана обмена. Каждый элемент коллекции имеет свойство Метаданные (ссылка на объект метаданных) и АвтоРегистрация. Типичный код перебора выглядит так:
Функция ПолучитьСоставПланаОбмена(ИмяПлана) Экспорт
Результат = Новый Массив;
ПланМетаданные = Метаданные.ПланыОбмена.Найти(ИмяПлана);
Если ПланМетаданные = Неопределено Тогда
ВызватьИсключение "План обмена не найден: " + ИмяПлана;
КонецЕсли;
Для Каждого Элемент Из ПланМетаданные.Состав Цикл
Описание = Новый Структура;
Описание.Вставить("ИмяОбъекта", Элемент.Метаданные.Имя);
Описание.Вставить("ПолноеИмя", Элемент.Метаданные.ПолноеИмя());
Описание.Вставить("АвтоРегистрация", Элемент.АвтоРегистрация);
Результат.Добавить(Описание);
КонецЦикла;
Возврат Результат;
КонецФункции
Обратите внимание на предварительную проверку через Метаданные.ПланыОбмена.Найти(). Прямое обращение Метаданные.ПланыОбмена.МойПлан вызовет ошибку, если план с таким именем отсутствует в конфигурации — а в универсальных обработках, работающих с разными конфигурациями, это типовая ситуация.
Если нужно просто проверить, входит ли конкретный тип объекта в состав плана, используйте метод Содержит():
Если Метаданные.ПланыОбмена.ОбменССайтом.Состав.Содержит(Метаданные.Справочники.Номенклатура) Тогда
// Номенклатура участвует в обмене
КонецЕсли;
Такая проверка выполняется быстро и безопасно, её удобно ставить перед регистрацией изменений: попытка зарегистрировать объект, не входящий в состав плана, приведёт к ошибке времени выполнения.
Проверка конкретного объекта и узла
На практике чаще нужно не перебрать весь состав, а ответить на вопрос: «зарегистрирован ли этот конкретный объект к выгрузке на этот узел». Для этого существуют методы ПланыОбмена.ИзменениеЗарегистрировано() и ПланыОбмена.ВыбратьИзменения().
Проверка одного объекта делается так:
Узел = ПланыОбмена.ОбменССайтом.НайтиПоКоду("001");
СсылкаНаТовар = Справочники.Номенклатура.НайтиПоКоду("00-000123");
Зарегистрирован = ПланыОбмена.ИзменениеЗарегистрировано(Узел, СсылкаНаТовар);
Метод вернёт Истина, если для пары «узел — объект» есть запись в таблице регистрации изменений. Это полезно при отладке: вы видите, дошёл ли объект до очереди выгрузки после записи.
Выборка всех зарегистрированных изменений по узлу выполняется через ВыбратьИзменения. Ей нужен номер сообщения — его берут из реквизита узла НомерОтправленного, увеличенный на единицу:
УзелОбъект = Узел.ПолучитьОбъект();
НомерСообщения = УзелОбъект.НомерОтправленного + 1;
Выборка = ПланыОбмена.ВыбратьИзменения(Узел, НомерСообщения);
Пока Выборка.Следующий() Цикл
Данные = Выборка.Получить();
// работа с данными
КонецЦикла;
Регистрация объектов в составе обмена программно
Обратная задача — добавить объект в очередь выгрузки. Перед регистрацией всегда проверяйте, что тип объекта входит в состав плана, иначе получите исключение:
Функция ЗарегистрироватьОбъектКВыгрузке(Узел, Ссылка) Экспорт
МетаданныеОбъекта = Ссылка.Метаданные();
Если Не Метаданные.ПланыОбмена.ОбменССайтом.Состав.Содержит(МетаданныеОбъекта) Тогда
Возврат Ложь; // тип не участвует в обмене
КонецЕсли;
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Ссылка);
Возврат Истина;
КонецФункции
Для массовой регистрации — например, первичной выгрузки всей номенклатуры на новый узел — удобно передавать в ЗарегистрироватьИзменения не ссылку, а объект метаданных. Тогда платформа зарегистрирует все существующие данные этого типа:
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Метаданные.Справочники.Номенклатура);
На больших таблицах такая операция может занять заметное время и создать миллионы записей регистрации. Выполняйте её вне пиковой нагрузки и желательно в транзакции с контролем результата.
- 1Получите состав плана через Метаданные.ПланыОбмена.ИмяПлана.Состав
- 2Отберите только нужные типы объектов, исключив служебные
- 3Для каждого типа вызовите ПланыОбмена.ЗарегистрироватьИзменения(Узел, МетаданныеОбъекта)
- 4Проверьте результат через ПланыОбмена.ВыбратьИзменения на тестовом узле
- 5Только после проверки запускайте процедуру на рабочем узле
Получение списка узлов плана обмена
Состав плана бессмысленен без узлов — конечных точек обмена. Список узлов получают запросом к таблице плана обмена. Важно исключить предопределённый узел «этой базы», иначе зарегистрируете изменения сами для себя:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Обмен.Ссылка КАК Узел,
| Обмен.Код КАК Код,
| Обмен.Наименование КАК Наименование
|ИЗ
| ПланОбмена.ОбменССайтом КАК Обмен
|ГДЕ
| НЕ Обмен.ЭтотУзел
| И НЕ Обмен.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// обработка узла
КонецЦикла;
Отбор по ЭтотУзел = Ложь и по пометке удаления — обязательная гигиена любого кода, работающего с узлами. Помеченный на удаление узел может ещё физически существовать, но регистрировать на него изменения уже не нужно: это мусор в таблицах регистрации и лишняя нагрузка на выгрузку.
Если узлов много, полезно дополнительно фильтровать по функциональной опции или реквизиту активности, если такой предусмотрен в конфигурации. В типовых решениях часто есть признак использования обмена, который стоит учитывать.
Как проверить результат
Нужный тип объекта присутствует и авторегистрация настроена осознанно
Типа нет в составе — регистрация из кода вызовет ошибку
ИзменениеЗарегистрировано(Узел, Ссылка) возвращает Истина после записи
Возвращает Ложь — проверьте авторегистрацию и отборы в подписках
ВыбратьИзменения возвращает ожидаемые объекты
Пустая выборка — изменения не регистрируются или уже выгружены
Типичные ошибки и ограничения
Самая распространённая ошибка — попытка зарегистрировать объект, не входящий в состав плана. Платформа в этом случае либо выбрасывает исключение, либо молча игнорирует вызов в зависимости от контекста. Всегда проверяйте Состав.Содержит() перед регистрацией, особенно в универсальном коде.
Вторая частая проблема — регистрация на предопределённом узле «этой базы». Изменения, зарегистрированные на самого себя, никуда не выгружаются, но занимают место в таблицах регистрации. При массовых операциях это приводит к заметному разрастанию базы.
Третий источник ошибок — непонимание разницы между составом метаданных и фактической регистрацией. Состав отвечает на вопрос «может ли тип обмениваться», регистрация — «какие объекты ждут выгрузки». Код, который читает состав и делает выводы о реальных данных очереди, работает неправильно.
Наконец, помните про ограничения контекста: обращение к метаданным и методам планов обмена требует серверного вызова в управляемом приложении. Клиентский код, пытающийся обратиться к Метаданные.ПланыОбмена напрямую, не скомпилируется.
Частые вопросы
Можно ли изменить состав плана обмена программно?
Нет. Состав — часть метаданных конфигурации и меняется только в конфигураторе с последующим обновлением конфигурации базы данных. Программно доступно только чтение состава и управление регистрацией изменений в его рамках.
Как узнать, какие объекты реально ждут выгрузки на узел?
Используйте ПланыОбмена.ВыбратьИзменения(Узел, НомерСообщения) с номером, равным НомерОтправленного узла плюс один. Для точечной проверки одного объекта подойдёт ПланыОбмена.ИзменениеЗарегистрировано(Узел, Ссылка).
Почему объект записывается, но не регистрируется к обмену?
Чаще всего в составе плана для этого типа отключена авторегистрация, либо в подписках на события или правилах регистрации заданы отборы, которые объект не проходит. Проверьте свойство АвтоРегистрация элемента состава и логику правил регистрации.
Как получить состав плана обмена, если имя плана неизвестно заранее?
Переберите коллекцию Метаданные.ПланыОбмена и для каждого плана читайте его Состав. Так строят универсальные обработки, работающие с любой конфигурацией без жёсткой привязки к именам.
Можно ли получить состав плана обмена через запрос?
Нет, состав — это метаданные, а не данные таблиц. Запросом можно получить только узлы плана (таблица ПланОбмена.ИмяПлана) и данные самих объектов. Состав читается исключительно через объект Метаданные.
Что делать, если таблицы регистрации изменений разрослись?
Удалите устаревшую регистрацию через ПланыОбмена.УдалитьРегистрациюИзменений(Узел, МетаданныеОбъекта) для неиспользуемых узлов и проверьте, не регистрируются ли изменения на помеченные или собственный узел. Перед массовой очисткой сделайте резервную копию.
Что важно запомнить
Состав плана обмена читается через Метаданные.ПланыОбмена.ИмяПлана.Состав, принадлежность типа проверяется методом Содержит, а реальная очередь выгрузки — через ВыбратьИзменения и ИзменениеЗарегистрировано. Перед регистрацией всегда проверяйте состав и исключайте собственный узел из обработки.