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

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

1С: как получить менеджер объекта через метаданные

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

Во встроенном языке 1С менеджер объекта — это программный объект, через который выполняются операции с конкретным видом метаданных: поиск, создание, выборка, получение пустой ссылки. Обычно менеджер доступен напрямую по имени, например Справочники.Номенклатура или Документы.РеализацияТоваровУслуг. Но в универсальных алгоритмах имя объекта заранее неизвестно — оно хранится в строке, приходит из параметров или вычисляется в цикле. В этом случае менеджер получают через коллекцию метаданных.

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

Что такое менеджер объекта и зачем он нужен

Менеджер объекта — это точка входа для работы с видом метаданных целиком, а не с конкретной записью. Через менеджер справочника вызывают НайтиПоКоду(), СоздатьЭлемент(), ПустаяСсылка(), Выбрать(). У документов менеджер дополнительно даёт ПолучитьФорму(), у регистров — СоздатьНаборЗаписей().

Когда имя объекта известно на этапе написания кода, менеджер доступен напрямую: Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка"). Проблема появляется, когда вид объекта становится известен только во время выполнения — например, пользователь выбрал в форме произвольный справочник, и обработка должна с ним работать. Тогда нужен способ получить менеджер динамически, по объекту описания метаданных.

Получение объекта метаданных по имени

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

МетаОбъект = Метаданные.НайтиПоПолномуИмени("Справочник.Номенклатура");

Если МетаОбъект = Неопределено Тогда

ВызватьИсключение "Объект метаданных не найден";

КонецЕсли;

Если известна ссылка на конкретный элемент, метаданные получают от неё: МетаданныеОбъекта = Ссылка.Метаданные(). Этот приём удобен в универсальных обработчиках, где тип входящей ссылки заранее не определён.

Обратите внимание на формат полного имени: для справочников и документов вид указывается в единственном числе — Справочник.Номенклатура, Документ.РеализацияТоваровУслуг, Перечисление.СтавкиНДС, РегистрСведений.КурсыВалют. Ошибка в числе (множественное вместо единственного) — частая причина, почему НайтиПоПолномуИмени возвращает Неопределено.

Основной способ: получение менеджера через имя коллекции

Универсальный рабочий приём — определить имя глобальной коллекции менеджеров по виду метаданных и обратиться к ней через Вычислить():

Функция ПолучитьМенеджерПоМетаданным(МетаОбъект)

ПолноеИмя = МетаОбъект.ПолноеИмя();

ВидОбъекта = СтрРазделить(ПолноеИмя, ".")[0];

СоответствиеКоллекций = Новый Соответствие;

СоответствиеКоллекций.Вставить("Справочник", "Справочники");

СоответствиеКоллекций.Вставить("Документ", "Документы");

СоответствиеКоллекций.Вставить("Перечисление", "Перечисления");

СоответствиеКоллекций.Вставить("ПланВидовХарактеристик", "ПланыВидовХарактеристик");

СоответствиеКоллекций.Вставить("ПланСчетов", "ПланыСчетов");

СоответствиеКоллекций.Вставить("ПланВидовРасчета", "ПланыВидовРасчета");

СоответствиеКоллекций.Вставить("РегистрСведений", "РегистрыСведений");

СоответствиеКоллекций.Вставить("РегистрНакопления", "РегистрыНакопления");

СоответствиеКоллекций.Вставить("РегистрБухгалтерии", "РегистрыБухгалтерии");

СоответствиеКоллекций.Вставить("РегистрРасчета", "РегистрыРасчета");

СоответствиеКоллекций.Вставить("БизнесПроцесс", "БизнесПроцессы");

СоответствиеКоллекций.Вставить("Задача", "Задачи");

ИмяКоллекции = СоответствиеКоллекций[ВидОбъекта];

Если ИмяКоллекции = Неопределено Тогда

ВызватьИсключение "Менеджер для вида " + ВидОбъекта + " не поддерживается";

КонецЕсли;

Возврат Вычислить(ИмяКоллекции + "[""" + МетаОбъект.Имя + """]");

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

Приём Вычислить("Справочники[""Номенклатура""]") возвращает тот же менеджер, что и прямое обращение Справочники.Номенклатура. Индексация коллекции строкой работает для всех прикладных видов объектов.

bsl
Менеджер = Вычислить("Справочники[""" + МетаОбъект.Имя + """]");
НовыйЭлемент = Менеджер.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Тест";
НовыйЭлемент.Записать();

Альтернатива без Вычислить

Метод Вычислить() выполняет произвольный код и потенциально небезопасен, если имя объекта приходит извне. Безопаснее строить ветвление через Если...ИначеЕсли по типу метаданных и обращаться к коллекциям напрямую:

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

Менеджер = Справочники[МетаОбъект.Имя];

ИначеЕсли Метаданные.Документы.Содержит(МетаОбъект) Тогда

Менеджер = Документы[МетаОбъект.Имя];

ИначеЕсли Метаданные.Перечисления.Содержит(МетаОбъект) Тогда

Менеджер = Перечисления[МетаОбъект.Имя];

КонецЕсли;

Метод Содержит() коллекции метаданных проверяет принадлежность объекта конкретному виду — это надёжнее разбора строки полного имени и не зависит от локализации кода.

Готовая функция в Библиотеке стандартных подсистем

В конфигурациях на базе БСП (Управление торговлей, ERP, Бухгалтерия предприятия и другие типовые) есть готовый механизм. Общий модуль ОбщегоНазначения предоставляет функцию МенеджерОбъектаПоПолномуИмени(ПолноеИмя), а также МенеджерОбъектаПоСсылке(Ссылка).

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

Пустая = Менеджер.ПустаяСсылка();

Функция БСП сама определяет вид объекта, проверяет существование метаданных и вызывает понятное исключение при ошибке. Если конфигурация включает БСП, используйте её, а не собственный велосипед: код короче и протестирован.

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

Типовая задача — обработка, которая получает на вход полное имя объекта и выполняет над ним действие, например подсчёт количества элементов или поиск по наименованию:

Функция НайтиПоНаименованиюУниверсально(ПолноеИмя, СтрокаПоиска)

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

Если МетаОбъект = Неопределено Тогда

Возврат Неопределено;

КонецЕсли;

Если НЕ Метаданные.Справочники.Содержит(МетаОбъект)

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

ВызватьИсключение "Поиск по наименованию поддерживается только для справочников и ПВХ";

КонецЕсли;

Менеджер = Справочники[МетаОбъект.Имя];

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

Менеджер = ПланыВидовХарактеристик[МетаОбъект.Имя];

КонецЕсли;

Возврат Менеджер.НайтиПоНаименованию(СтрокаПоиска, Истина);

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

Здесь важна предварительная проверка вида объекта: метод НайтиПоНаименованию есть не у всех менеджеров. У документов вместо него используется НайтиПоНомеру, у регистров сведений поиск идёт по измерениям через набор записей или запрос. Универсальный код обязан учитывать эти различия, иначе получите ошибку «Метод объекта не обнаружен» в режиме выполнения.

Порядок действий
  1. 1
    Получите объект метаданных через Метаданные.НайтиПоПолномуИмени() или Ссылка.Метаданные()
  2. 2
    Проверьте, что объект найден (не Неопределено)
  3. 3
    Определите вид объекта методом Содержит() соответствующей коллекции метаданных
  4. 4
    Получите менеджер обращением к коллекции по имени: Справочники[МетаОбъект.Имя]
  5. 5
    Проверьте наличие нужного метода у менеджера для данного вида объектов
  6. 6
    Выполните операцию и проверьте результат

Проверка результата и ограничения

После получения менеджера убедитесь, что он работает: вызовите безопасный метод, например ПустаяСсылка(). Если менеджер получен корректно, метод вернёт пустую ссылку соответствующего типа. Дополнительно можно сравнить тип: ТипЗнч(Менеджер) = Тип("СправочникМенеджер.Номенклатура").

Есть ограничения, о которых нужно помнить. Во-первых, обращение Справочники[Имя] с несуществующим именем вызовет исключение, поэтому проверка метаданных обязательна до получения менеджера. Во-вторых, в безопасном режиме (например, при выполнении внешних обработок с ограничениями) Вычислить() может быть недоступен — используйте прямое обращение к коллекциям. В-третьих, у внешних источников данных и констант структура менеджеров другая: у констант единый менеджер КонстантыМенеджер через набор Константы.СоздатьНабор().

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

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

Менеджер получен
Норма

ТипЗнч возвращает тип вида СправочникМенеджер.<Имя>

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

Переменная равна Неопределено или возникло исключение

Метаданные найдены
Норма

НайтиПоПолномуИмени вернул объект

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

Возвращено Неопределено — проверьте формат полного имени

Метод доступен
Норма

Вызов метода выполняется без ошибки

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

Ошибка «Метод объекта не обнаружен» — вид объекта не поддерживает метод

Типичные ошибки при получении менеджера

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

Третья ошибка — использование Вычислить() со строкой, собранной из пользовательского ввода, без проверки. Это открывает возможность выполнения произвольного кода. Всегда проверяйте, что имя объекта соответствует реальному объекту метаданных, прежде чем подставлять его в вычисляемое выражение.

Типичные ошибки
01
Множественное число в полном имени («Справочники.Номенклатура») — НайтиПоПолномуИмени возвращает Неопределено
02
Вызов СоздатьЭлемент() у менеджера перечисления — исключение, значения перечислений создаются только в конфигураторе
03
Вычислить() с непроверенной строкой извне — риск выполнения произвольного кода
04
Отсутствие проверки на Неопределено после поиска метаданных — ошибка при обращении к свойству Имя
05
Ожидание метода НайтиПоНаименованию у документов — у них есть только НайтиПоНомеру

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

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

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

Чем Вычислить() отличается от Выполнить() при получении менеджера?

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

Можно ли получить менеджер регистра сведений через метаданные?

Да, схема та же: проверить Метаданные.РегистрыСведений.Содержит(МетаОбъект) и обратиться РегистрыСведений[МетаОбъект.Имя]. Через такой менеджер доступны СоздатьНаборЗаписей(), СоздатьМенеджерЗаписи(), Получить() и другие методы работы с записями регистра.

Почему НайтиПоПолномуИмени возвращает Неопределено, хотя объект есть в конфигурации?

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

Есть ли единый метод, который возвращает менеджер для любого вида объекта?

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

Работает ли получение менеджера через Вычислить в безопасном режиме?

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

Итог

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

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