Как обратиться к глобальному контексту и динамически получить менеджер объекта в 1С без условий Если...ИначеЕсли

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

При разработке универсальных механизмов обмена данными, групповой обработки или импорта информации из внешних источников программисты часто сталкиваются с задачей динамического создания объектов. Например, когда тип создаваемого объекта (справочник, документ, план видов характеристик) и его имя заранее неизвестны и приходят в виде строковых переменных: ГруппаОбъектов = "Справочники" и ИмяОбъекта = "Номенклатура".

Попытка обратиться напрямую через воображаемый глобальный контекст наподобие ГлобальныйКонтекст[ГруппаОбъектов][ИмяОбъекта] вызывает ошибку компиляции, так как у платформы "1С:Предприятие" внутри текущего сеанса нет предопределенного системного имени для индексации самого глобального контекста. В этой статье мы подробно разберем, как решить эту задачу изящно и обойтись без громоздких конструкций Если...ИначеЕсли...КонецЕсли.

Метод 1. Использование Библиотеки стандартных подсистем (БСП)

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

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


// Передаем полное имя объекта метаданных в формате "Тип.Имя"
ПолноеИмяОбъекта = "Справочник.Номенклатура";

// Получаем менеджер объекта с помощью БСП
Менеджер = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПолноеИмяОбъекта);

// Теперь мы можем динамически создавать элементы и выполнять другие операции
НовыйЭлемент = Менеджер.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Новый тестовый товар";
НовыйЭлемент.Записать();

Если имя коллекции (например, "Справочник") и имя самого объекта ("Номенклатура") у вас хранятся в разных переменных, мы можем легко объединить их, приведя к стандартному виду метаданных. При этом важно помнить, что в именах метаданных используется единственное число (Справочник, Документ), а в обращении к коллекциям менеджеров — множественное (Справочники, Документы).

Давайте посмотрим на пример преобразования имен:


ГруппаОбъектов = "Справочники"; // Переменная содержит множественное число
ИмяОбъекта = "Номенклатура";

// Приводим имя группы к единственному числу для БСП
Если ГруппаОбъектов = "Справочники" Тогда
    ТипОбъекта = "Справочник";
ИначеЕсли ГруппаОбъектов = "Документы" Тогда
    ТипОбъекта = "Документ";
// Добавьте другие типы при необходимости
КонецЕсли;

ПолноеИмя = ТипОбъекта + "." + ИмяОбъекта;
Менеджер = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПолноеИмя);

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

Метод 2. Динамическое выполнение кода через Вычислить()

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

Рассмотрим, как это выглядит на практике:


ГруппаОбъектов = "Справочники"; 
ИмяОбъекта = "Номенклатура";

// Формируем строковое выражение: "Справочники[""Номенклатура""]"
СтрокаВызова = ГруппаОбъектов + "[""" + ИмяОбъекта + """]";

Попытка
    // Вычисляем строку и получаем готовый менеджер
    Менеджер = Вычислить(СтрокаВызова);
    
    // Выполняем создание объекта
    НовыйОбъект = Менеджер.СоздатьЭлемент();
Исключение
    Сообщить("Ошибка получения менеджера: " + ОписаниеОшибки());
КонецПопытки;

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

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

Метод 3. Собственная универсальная функция-обертка

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

Разберем пример реализации такой функции:


// Функция возвращает менеджер объекта по имени коллекции и имени объекта
Функция ПолучитьМенеджерОбъекта(Знач ИмяКоллекции, Знач ИмяОбъекта) Экспорт
    
    // Приводим имя коллекции к верхнему регистру для надежности сравнения
    ИмяКоллекцииВР = ВРег(СокрЛП(ИмяКоллекции));
    
    Если ИмяКоллекцииВР = "СПРАВОЧНИКИ" Или ИмяКоллекцииВР = "СПРАВОЧНИК" Тогда
        Возврат Справочники[ИмяОбъекта];
    ИначеЕсли ИмяКоллекцииВР = "ДОКУМЕНТЫ" Или ИмяКоллекцииВР = "ДОКУМЕНТ" Тогда
        Возврат Документы[ИмяОбъекта];
    ИначеЕсли ИмяКоллекцииВР = "ПЛАНЫВИДОВХАРАКТЕРИСТИК" Или ИмяКоллекцииВР = "ПВХ" Тогда
        Возврат ПланыВидовХарактеристик[ИмяОбъекта];
    ИначеЕсли ИмяКоллекцииВР = "ЗАДАЧИ" Тогда
        Возврат Задачи[ИмяОбъекта];
    ИначеЕсли ИмяКоллекцииВР = "БИЗНЕСПРОЦЕССЫ" Тогда
        Возврат БизнесПроцессы[ИмяОбъекта];
    КонецЕсли;
    
    ВызватьИсключение "Неподдерживаемая коллекция объектов метаданных: " + ИмяКоллекции;
    
КонецФункции

Этот код работает максимально быстро, так как использует прямое обращение к коллекциям платформы по индексу строки. Вы можете разместить эту функцию в общем модуле с признаком Клиент (сервер) и флагом Повторное использование, чтобы оптимизировать обращения.

Метод 4. Определение коллекции через метаданные

Иногда на входе у нас есть только имя объекта (например, "Номенклатура"), но мы не знаем, справочник это, документ или план видов характеристик. Чтобы не перебирать все варианты вручную, мы можем программно определить, к какой коллекции принадлежит этот объект, обратившись к структуре метаданных базы данных.

Посмотрим на пример поиска типа объекта через метаданные:


ИмяИскомогоОбъекта = "Номенклатура";
КлассОбъекта = ""; // Сюда запишем "Справочники", "Документы" и т.д.

// Проверяем принадлежность к справочникам
Если Метаданные.Справочники.Найти(ИмяИскомогоОбъекта) <> Неопределено Тогда
    КлассОбъекта = "Справочники";
// Проверяем принадлежность к документам
ИначеЕсли Метаданные.Документы. Найти(ИмяИскомогоОбъекта) <> Неопределено Тогда
    КлассОбъекта = "Документы";
// Проверяем принадлежность к планам видов характеристик
ИначеЕсли Метаданные.ПланыВидовХарактеристик.Найти(ИмяИскомогоОбъекта) <> Неопределено Тогда
    КлассОбъекта = "ПланыВидовХарактеристик";
КонецЕсли;

Если ЗначениеЗаполнено(КлассОбъекта) Тогда
    // Получаем менеджер, используя ранее написанную функцию
    Менеджер = ПолучитьМенеджерОбъекта(КлассОбъекта, ИмяИскомогоОбъекта);
Иначе
    Сообщить("Объект с именем " + ИмяИскомогоОбъекта + " не найден в метаданных конфигурации!");
КонецЕсли;

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

Резюме и рекомендации

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

  1. Встроенного "волшебного слова" нет. Платформа 1С внутри текущего сеанса не предоставляет глобального ассоциативного массива для прямого получения коллекций менеджеров по строковому представлению.
  2. Лучший выбор — функции БСП. Если проект использует БСП, всегда применяйте ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(). Это стандарт разработки, поддерживающий оптимизацию и кэширование данных.
  3. Ограничивайте применение Вычислить(). Метод Вычислить() удобен для быстрых разовых обработок, но неприменим в циклах с большим объемом данных и может быть заблокирован в безопасном режиме работы конфигурации.
  4. Создавайте собственные обертки. Если БСП отсутствует, напишите простую функцию-посредник в общем модуле с повторным использованием значений. Это сохранит ваш код чистым, понятным и быстродействующим.
← На главную