Как программно определить, добавлен ли объект метаданных в расширение

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

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

В этой статье мы подробно разберем, какими инструментами обладает платформа «1С:Предприятие 8.3» для решения этой задачи, проанализируем различия между методами и научимся писать универсальный код для работы с метаданными расширений.

Постановка задачи и варианты реализации

Представим ситуацию: вы создаете обработку для выгрузки справочников во внешнюю систему. Чтобы не прописывать каждый справочник в коде вручную, вы хотите реализовать алгоритм, который автоматически определяет: «Если справочник добавлен в мое расширение, значит, его нужно выгружать». Для этого нам нужно программно отличить объект, который существует только в основной конфигурации, от того, который был заимствован или создан в расширении. Для точечного переноса информации между базами с отличающейся структурой или несовпадающими ссылками применяется специальная обработка для переноса данных между похожими конфигурациями 1С.

Существует два основных способа решения этой задачи, в зависимости от версии платформы и режима совместимости:

  1. Использование метода РасширениеКонфигурации() у конкретного объекта метаданных.
  2. Анализ коллекции метаданных через глобальный менеджер РасширенияКонфигурации.

Метод 1: Использование РасширениеКонфигурации()

Начиная с версии платформы 8.3.13, у объектов метаданных появился специализированный метод РасширениеКонфигурации(). Проанализируем, как он работает на практике.

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

Рассмотрим пример кода, который проверяет конкретный справочник:


МетаданныеСправочника = Метаданные.Справочники.Номенклатура;
ОбъектРасширения = МетаданныеСправочника.РасширениеКонфигурации();

Если ОбъектРасширения <> Неопределено Тогда
    Сообщить("Справочник " + МетаданныеСправочника.Имя + " включен в расширение: " + ОбъектРасширения.Имя);
Иначе
    Сообщить("Справочник " + МетаданныеСправочника.Имя + " отсутствует в расширениях.");
КонецЕсли;

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

Метод 2: Обход метаданных через менеджер расширений

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

Разберем алгоритм по шагам:

  1. Получаем массив всех установленных в системе расширений.
  2. Находим среди них наше целевое расширение по имени.
  3. Обращаемся к свойству Метаданные этого расширения.

Проанализируем пример кода, который выводит список всех справочников, заимствованных в конкретное расширение с именем "МоеРасширениеДляВыгрузки":


ИмяНужногоРасширения = "МоеРасширениеДляВыгрузки";
МассивРасширений = РасширенияКонфигурации.Получить();

Для Каждого ТекущееРасширение Из МассивРасширений Цикл
    Если ТекущееРасширение.Имя = ИмяНужногоРасширения Тогда
        
        // Получаем метаданные именно этого расширения
        МетаданныеРасширения = ТекущееРасширение.Метаданные;
        
        // Перебираем справочники в составе расширения
        Для Каждого СправочникИзРасширения Из МетаданныеРасширения.Справочники Цикл
            Сообщить("Справочник к выгрузке: " + СправочникИзРасширения.Имя);
        КонецЦикла;
        
    КонецЕсли;
КонецЦикла;

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

Различия между собственными и заимствованными объектами

При работе с метаданными расширения важно различать два типа объектов:

Если вы используете второй метод (через РасширенияКонфигурации.Получить()), то в коллекции Метаданные расширения вы увидите оба типа. Если же вам нужно отделить только заимствованные, потребуется дополнительная проверка на наличие объекта с таким же именем в Метаданные основной конфигурации.

Ограничения режима совместимости

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

Рекомендация: Всегда проверяйте режим совместимости вашей конфигурации перед использованием метода РасширениеКонфигурации().

Практический пример: Универсальная функция проверки

Рассмотрим создание универсальной функции, которую можно разместить в общем модуле для использования во всей системе. Эта функция будет отвечать на вопрос: «Относится ли данный объект к конкретному расширению?»


// Функция проверяет принадлежность объекта метаданных расширению
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных (например, Метаданные.Справочники.Склады)
//  ИмяРасширения    - Строка, имя искомого расширения
// Возвращаемое значение: Булево
Функция ОбъектВходитВРасширение(ОбъектМетаданных, ИмяРасширения) Экспорт
    
    // Проверка для современных платформ (8.3.13+)
    Попытка
        СсылкаНаРасширение = ОбъектМетаданных.РасширениеКонфигурации();
        Если СсылкаНаРасширение <> Неопределено Тогда
            Возврат (СсылкаНаРасширение.Имя = ИмяРасширения);
        КонецЕсли;
    Исключение
        // Метод не поддерживается платформой, используем обходной путь через менеджер
    КонецПопытки;
    
    // Альтернативный метод для совместимости
    МассивРасширений = РасширенияКонфигурации.Получить();
    Для Каждого ТекРасширение Из МассивРасширений Цикл
        Если ТекРасширение.Имя = ИмяРасширения Тогда
            // Ищем объект в коллекции метаданных расширения по полному имени
            Возврат (ТекРасширение.Метаданные.НайтиПоПолномуИмени(ОбъектМетаданных.ПолноеИмя()) <> Неопределено);
        КонецЕсли;
    КонецЦикла;
    
    Возврат Ложь;
    
КонецФункции

Используя этот подход, мы обеспечиваем стабильную работу кода независимо от того, насколько свежая версия платформы используется на сервере клиента.

Резюме

Подведем итоги нашего анализа. Для определения того, добавлен ли объект в расширение, наиболее современным и быстрым способом является метод РасширениеКонфигурации(). Однако для задач массовой обработки объектов (как в случае с универсальной выгрузкой справочников) лучше всего подходит прямое обращение к коллекции Метаданные конкретного расширения через менеджер РасширенияКонфигурации. Это позволяет динамически формировать списки объектов, не привязываясь к жестко заданному составу основной конфигурации.

← На главную