Планы обмена в 1С:Предприятие — это основа для организации синхронизации данных между базами, внешними системами или распределёнными узлами. Однако часто разработчикам требуется не просто использовать готовый план, а программно анализировать его структуру: список объектов, их реквизиты, правила обмена или даже динамически формировать запросы на основе метаданных. Без этого невозможно создать универсальные обработки для миграции данных, аудита обменов или автоматизации интеграций.
В этой статье мы разберём 5 проверенных способов получения состава плана обмена — от стандартных методов встроенного языка до низкоуровневых приёмов через COM и REST. Вы узнаете, как извлечь не только список объектов, но и их свойства (например, ПометкаУдаления или ЭтоГруппа), как работать с версиями планов обмена, и какие подводные камни ждут при динамическом чтении метаданных. Все примеры кода адаптированы для актуальных версий платформы 1С:Предприятие 8.3 (включая 8.3.23+).
1. Стандартный метод: Чтение состава через МенеджерОбмена
Самый очевидный способ — использовать объекты ПланОбмена и МенеджерОбмена, которые предоставляет платформа. Этот метод подходит для большинства типовых задач, когда нужно получить список объектов, участвующих в обмене, или их свойства.
Основные объекты для работы:
- 📌 ПланОбмена — сам объект конфигурации (например,
ПланОбмена.ОсновнойОбмен). Через него можно получитьМенеджерОбмена. - 🔄 МенеджерОбмена — предоставляет методы для работы с узлами и данными обмена, включая
ПолучитьОбъектыДляОбмена(). - 📋 ОбъектОбмена — описывает конкретный объект (справочник, документ и т.д.) с его реквизитами и свойствами.
Пример кода для получения списка объектов плана обмена:
ПланОбмена = ПланыОбмена.ОсновнойОбмен;
МенеджерОбмена = ПланОбмена.ПолучитьМенеджерОбмена();
// Получаем все объекты, участвующие в обмене
ОбъектыОбмена = МенеджерОбмена.ПолучитьОбъектыДляОбмена();
// Выводим список в отладочную консоль
Для Каждого ОбъектОбмена Из ОбъектыОбмена Цикл
Сообщить(ОбъектОбмена.ИмяТипа + " (" + ОбъектОбмена.Имя + ")");
КонецЦикла;
⚠️ Внимание: Метод ПолучитьОбъектыДляОбмена() возвращает только те объекты, которые фактически участвуют в обмене на текущий момент (с учётом фильтров и настроек плана). Если вам нужны все возможные объекты, включая те, что временно исключены, используйте альтернативные подходы (см. раздел 3).
Если вам нужно получить не только имена объектов, но и их реквизиты, используйте метод ОбъектОбмена.ПолучитьРеквизитыДляОбмена(). Это позволит динамически формировать структуры данных для внешних систем.
2. Работа с метаданными плана обмена через встроенный язык
Если стандартный МенеджерОбмена не предоставляет нужных данных (например, требуется информация о версиях объектов или правилах преобразования), можно обратиться напрямую к метаданным плана обмена. Этот метод более гибкий, но требует знания структуры метаданных.
Ключевые свойства плана обмена в метаданных:
- 🔹
ОбъектыОбмена— коллекция всех объектов, которые могут участвовать в обмене (включая отключённые). - 🔹
ВерсияПланаОбмена— текущая версия структуры плана (важна для контроля изменений). - 🔹
Префикс— префикс, используемый для идентификации объектов в распределённой базе. - 🔹
ИспользоватьВерсионность— флаг, указывающий, ведётся ли контроль версий объектов.
Пример кода для чтения метаданных:
МetaДанныеПлана = Метаданные.ПланыОбмена.ОсновнойОбмен;
// Получаем все объекты обмена (включая отключённые)
ОбъектыМетаданных = МetaДанныеПлана.ОбъектыОбмена;
// Выводим детальную информацию по каждому объекту
Для Каждого ОбъектМетаданных Из ОбъектыМетаданных Цикл
Сообщить("Тип: " + ОбъектМетаданных.Тип.Имя);
Сообщить("Имя: " + ОбъектМетаданных.Имя);
Сообщить("Включен в обмен: " + ?(ОбъектМетаданных.Включен, "Да", "Нет"));
// Получаем реквизиты объекта
Реквизиты = ОбъектМетаданных.Реквизиты;
Для Каждого Реквизит Из Реквизиты Цикл
Сообщить(" - Реквизит: " + Реквизит.Имя + " (" + Реквизит.Тип.ОписаниеТипа() + ")");
КонецЦикла;
КонецЦикла;
| Свойство метаданных | Описание | Пример использования |
|---|---|---|
ОбъектыОбмена |
Коллекция всех объектов, задействованных в плане (включая отключённые). | Аудит структуры обмена, поиск "лишних" объектов. |
ВерсияПланаОбмена |
Текущая версия структуры (инкрементируется при изменении состава). | Контроль совместимости между узлами распределённой базы. |
ИспользоватьСжатие |
Флаг, указывающий, сжимаются ли данные при передаче. | Оптимизация сетевого трафика. |
Префикс |
Префикс для идентификации объектов в распределённой базе. | Разрешение конфликтов при слиянии данных. |
3. Динамическое чтение через COM-соединение (внешние системы)
Если вам нужно получить состав плана обмена из внешней системы (например, C#, Python или PHP), можно использовать COM-соединение с 1С:Предприятие. Этот метод универсален, но требует настройки прав доступа и учёта особенностей работы с COM.
Основные шаги:
- Создать COM-соединение с базой 1С.
- Получить объект
ПланОбменачерез метаданные. - Извлечь данные с помощью методов встроенного языка.
Пример на C#:
// Подключаем COM-библиотеку 1С
dynamic comConnector = Activator.CreateInstance(Type.GetTypeFromProgID("V83.ComConnector"));
dynamic app = comConnector.Connect("File=\"C:\\Bases\\MyBase\";Usr=\"Администратор\";Pwd=\"\";");
// Получаем план обмена
dynamic планОбмена = app.ПланыОбмена.ОсновнойОбмен;
dynamic менеджерОбмена = планОбмена.ПолучитьМенеджерОбмена();
// Получаем объекты обмена
dynamic объектыОбмена = менеджерОбмена.ПолучитьОбъектыДляОбмена();
// Обрабатываем результат (пример для вывода в консоль)
foreach (dynamic объект in объектыОбмена)
{
Console.WriteLine(объект.ИмяТипа + ": " + объект.Имя);
}
⚠️ Внимание: При работе через COM учитывайте:
- 🔐 Права доступа: Пользователь 1С должен иметь права на чтение метаданных плана обмена.
- 🕒 Производительность: COM-соединение медленнее прямого вызова в 1С. Для больших баз используйте пакетную обработку.
- 🛠 Ошибки подключения: Убедитесь, что на сервере разрешён доступ по COM (настройки
ragentилиrmngr).
Установить библиотеку V83.ComConnector|Настроить права пользователя в 1С|Проверить доступность порта 1540/1541|Создать резервную копию базы перед тестами|Подготовить обработку ошибок в коде-->
4. Использование REST API (для облачных и веб-решений)
С версии 1С:Предприятие 8.3.18+ появилась возможность работать с базой через REST API, включая чтение метаданных планов обмена. Этот метод актуален для облачных решений или интеграций с веб-сервисами.
Преимущества REST:
- 🌐 Кросс-платформенность (работает из любого языка, поддерживающего HTTP).
- 🔒 Безопасность (используются стандартные механизмы аутентификации).
- 📡 Удобство для распределённых систем.
Пример запроса для получения состава плана обмена (на базе 1С:Fresh или локального веб-сервера):
// URL для запроса (пример для локального веб-сервера)
string url = "http://localhost/ws/ПланОбмена.ОсновнойОбмен?format=json";
// Заголовки аутентификации (Basic Auth)
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", Convert.ToBase64String(
Encoding.ASCII.GetBytes("Администратор:")));
// Выполняем запрос
var response = await client.GetAsync(url);
string jsonResponse = await response.Content.ReadAsStringAsync();
// Обрабатываем ответ (пример для C#)
dynamic data = JsonConvert.DeserializeObject(jsonResponse);
foreach (var объект in data.ОбъектыОбмена)
{
Console.WriteLine(объект.ИмяТипа + ": " + объект.Имя);
}
Для работы с REST в 1С необходимо:
- Настроить публикацию базы на веб-сервере (Apache, IIS или встроенный сервер 1С).
- Включить OData-сервис или настроить собственные HTTP-сервисы.
- Сконфигурировать права доступа для REST-пользователей.
Как включить REST в 1С
Предприятие 8.3:
1. Откройте конфигуратор и перейдите в Администрирование → Публикация на веб-сервере.
2. Укажите каталог публикации и порт (например, 80 или 443 для HTTPS).
3. В настройках веб-сервисов включите опцию Использовать OData.
4. Перезапустите службу ragent или веб-сервер.
5. Проверьте доступность по адресу http://[адрес_сервера]/[имя_базы]/odata/standard.odata
5. Низкоуровневое чтение через запросы к СУБД (для опытных)
В редких случаях (например, при восстановлении данных или анализе повреждённых баз) может потребоваться прямое чтение таблиц СУБД, где хранятся метаданные планов обмена. Этот метод рискованный и требует глубокого понимания структуры базы 1С, но иногда он единственно возможный.
Ключевые таблицы в SQL-базе 1С (для PostgreSQL/MSSQL):
- 🗃
Config— хранит метаданные конфигурации, включая планы обмена. - 🗃
ConfigSave— архивные версии конфигурации (полезно для отката изменений). - 🗃
ExchangePlan— данные о узлах и объектах обмена (для распределённых баз).
Пример SQL-запроса для получения объектов плана обмена (для PostgreSQL):
SELECT
ep."PlanName" AS "ИмяПлана",
ep."ObjectType" AS "ТипОбъекта",
ep."ObjectName" AS "ИмяОбъекта",
ep."IsEnabled" AS "Включен"
FROM
"ExchangePlan" ep
WHERE
ep."PlanName" = 'ОсновнойОбмен'
ORDER BY
ep."ObjectType", ep."ObjectName";
⚠️ Внимание: Прямое обращение к таблицам СУБД может:
- 🚨 Нарушить целостность данных при некорректных запросах (особенно в транзакционных базах).
- 🔄 Дать неактуальные данные, если конфигурация была изменена, но не обновлена в базе.
- 🛡 Требовать прав администратора СУБД, что не всегда безопасно.
Используйте этот метод только в крайних случаях и обязательно делайте резервную копию перед экспериментами.
Низкоуровневое чтение через SQL следует использовать ТОЛЬКО для диагностики или восстановления данных. Для регулярных задач предпочтительны стандартные методы встроенного языка или REST API.
6. Автоматизация: Генерация отчётов и документирование плана обмена
Часто состав плана обмена требуется не только для программной обработки, но и для документирования (например, при передаче системы заказчику или аудите интеграций). В этом случае полезно автоматизировать генерацию отчётов в удобном формате (Excel, JSON, Markdown).
Пример кода для экспорта состава плана обмена в JSON:
Функция ЭкспортироватьПланОбменаВJSON(ИмяПлана)
ПланОбмена = ПланыОбмена[ИмяПлана];
МенеджерОбмена = ПланОбмена.ПолучитьМенеджерОбмена();
ОбъектыОбмена = МенеджерОбмена.ПолучитьОбъектыДляОбмена();
JSONОбъект = Новый Структура();
JSONОбъект.Вставить("ИмяПлана", ИмяПлана);
JSONОбъект.Вставить("Версия", ПланОбмена.ВерсияПланаОбмена);
СписокОбъектов = Новый Массив();
Для Каждого ОбъектОбмена Из ОбъектыОбмена Цикл
ОбъектJSON = Новый Структура();
ОбъектJSON.Вставить("Тип", ОбъектОбмена.ИмяТипа);
ОбъектJSON.Вставить("Имя", ОбъектОбмена.Имя);
ОбъектJSON.Вставить("Реквизиты", ПолучитьРеквизитыОбъекта(ОбъектОбмена));
СписокОбъектов.Добавить(ОбъектJSON);
КонецЦикла;
JSONОбъект.Вставить("Объекты", СписокОбъектов);
Возврат JSONЗапись(JSONОбъект);
КонецФункции
Функция ПолучитьРеквизитыОбъекта(ОбъектОбмена)
Реквизиты = Новый Массив();
Для Каждого Реквизит Из ОбъектОбмена.Реквизиты Цикл
Реквизиты.Добавить(Реквизит.Имя);
КонецЦикла;
Возврат Реквизиты;
КонецФункции
Для генерации отчётов в Excel можно использовать библиотеку OneScript.Xlsx или встроенные механизмы 1С:
// Пример создания Excel-отчёта
Таблица = Новый ТаблицаЗначений();
Таблица.Колонки.Добавить("Тип");
Таблица.Колонки.Добавить("Имя");
Таблица.Колонки.Добавить("Реквизиты");
Для Каждого ОбъектОбмена Из ОбъектыОбмена Цикл
НоваяСтрока = Таблица.Добавить();
НоваяСтрока.Тип = ОбъектОбмена.ИмяТипа;
НоваяСтрока.Имя = ОбъектОбмена.Имя;
НоваяСтрока.Реквизиты = СтрСоединить(ПолучитьРеквизитыОбъекта(ОбъектОбмена), ", ");
КонецЦикла;
// Сохраняем в Excel
Таблица.Записать("C:\Отчеты\СоставПланаОбмена.xlsx", ТипФайлаExcel.Excel2007);
FAQ: Частые вопросы по работе с планами обмена
Как получить список объектов, которые были изменены с последнего обмена?
Используйте метод МенеджерОбмена.ПолучитьИзменённыеОбъекты(). Он возвращает коллекцию объектов с флагом изменений. Пример:
ИзменённыеОбъекты = МенеджерОбмена.ПолучитьИзменённыеОбъекты(ТекущаяДата() - 86400); // За последние сутки
Для Каждого Объект Из ИзменённыеОбъекты Цикл
Сообщить("Изменён: " + Объект.Имя);
КонецЦикла;
Для распределённых баз можно также использовать ПланОбмена.ПолучитьИзмененияДляОтправки().
Можно ли программно добавить новый объект в план обмена?
Да, но это требует редактирования конфигурации. Пример:
// Получаем объект метаданных плана обмена
МетаданныеПлана = Метаданные.ПланыОбмена.ОсновнойОбмен;
// Добавляем новый объект (например, справочник "Контрагенты")
НовыйОбъект = МетаданныеПлана.ОбъектыОбмена.Добавить();
НовыйОбъект.Тип = Метаданные.Справочники.Контрагенты;
НовыйОбъект.Включен = Истина;
⚠️ После изменения конфигурации требуется обновление базы данных.
Как узнать, какие реквизиты объекта участвуют в обмене?
Используйте метод ОбъектОбмена.ПолучитьРеквизитыДляОбмена(). Он возвращает коллекцию реквизитов, которые фактически передаются в обмене. Пример:
Реквизиты = ОбъектОбмена.ПолучитьРеквизитыДляОбмена();
Для Каждого Реквизит Из Реквизиты Цикл
Сообщить(Реквизит.Имя + " (" + Реквизит.Тип.ОписаниеТипа() + ")");
КонецЦикла;
Если нужно получить все возможные реквизиты (включая те, что не передаются), обращайтесь к метаданным объекта:
ВсеРеквизиты = ОбъектОбмена.Тип.Реквизиты;
Почему метод ПолучитьОбъектыДляОбмена() возвращает пустой список?
Возможные причины:
- Фильтры плана обмена: В настройках плана могут быть установлены фильтры по узлам или типам объектов.
- Отсутствие прав: Пользователь не имеет прав на чтение метаданных или объектов.
- Повреждение метаданных: Проверьте целостность конфигурации (
Тестирование и исправление → Тестировать и исправлять). - Несоответствие версий: Если план обмена был изменён, но база не обновлена.
Для диагностики используйте:
Сообщить(МенеджерОбмена.ПроверкаДоступностиОбмена());
Как сравнить состав двух планов обмена?
Создайте функцию, которая экспортирует состав каждого плана в структуру, а затем сравнивает их. Пример:
Функция СравнитьПланыОбмена(ИмяПлана1, ИмяПлана2)
Состав1 = ПолучитьСоставПлана(ИмяПлана1);
Состав2 = ПолучитьСоставПлана(ИмяПлана2);
Результат = Новый Структура();
Результат.Вставить("ТолькоВПервом", СравнитьСписки(Состав1.Объекты, Состав2.Объекты, "Левое"));
Результат.Вставить("ТолькоВоВтором", СравнитьСписки(Состав1.Объекты, Состав2.Объекты, "Правое"));
Результат.Вставить("Общие", СравнитьСписки(Состав1.Объекты, Состав2.Объекты, "Пересечение"));
Возврат Результат;
КонецФункции
Функция СравнитьСписки(Список1, Список2, Режим)
// Реализация сравнения (упросщённо)
Результат = Новый Массив();
Для Каждого Элемент Из Список1 Цикл
Если Режим = "Левое" И НЕ Список2.Найти(Элемент) Тогда
Результат.Добавить(Элемент);
ИначеЕсли Режим = "Пересечение" И Список2.Найти(Элемент) Тогда
Результат.Добавить(Элемент);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции