Разработка и Конфигурация · 13 мин
1С: как получить менеджер объекта через метаданные
Как в 1С получить менеджер объекта по метаданным: Справочники, Документы, Перечисления, метод НайтиПоПолномуИмени, примеры кода и типичные ошибки разработчиков.
Во встроенном языке 1С менеджер объекта — это программный объект, через который выполняются операции с конкретным видом метаданных: поиск, создание, выборка, получение пустой ссылки. Обычно менеджер доступен напрямую по имени, например Справочники.Номенклатура или Документы.РеализацияТоваровУслуг. Но в универсальных алгоритмах имя объекта заранее неизвестно — оно хранится в строке, приходит из параметров или вычисляется в цикле. В этом случае менеджер получают через коллекцию метаданных.
Задача «получить менеджер по метаданным» возникает при написании универсальных обработок: выгрузки данных, обменов, групповых перепроведений, отчётов по произвольным объектам. Вместо жёсткой привязки к конкретному справочнику код работает с любым объектом конфигурации, переданным параметром. Ниже разобраны рабочие способы получения менеджера, их ограничения и типичные ошибки.
Что такое менеджер объекта и зачем он нужен
Менеджер объекта — это точка входа для работы с видом метаданных целиком, а не с конкретной записью. Через менеджер справочника вызывают НайтиПоКоду(), СоздатьЭлемент(), ПустаяСсылка(), Выбрать(). У документов менеджер дополнительно даёт ПолучитьФорму(), у регистров — СоздатьНаборЗаписей().
Когда имя объекта известно на этапе написания кода, менеджер доступен напрямую: Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка"). Проблема появляется, когда вид объекта становится известен только во время выполнения — например, пользователь выбрал в форме произвольный справочник, и обработка должна с ним работать. Тогда нужен способ получить менеджер динамически, по объекту описания метаданных.
Получение объекта метаданных по имени
Первый шаг — получить сам объект описания метаданных. Если известно полное имя в формате «ВидОбъекта.Имя», используйте метод Метаданные.НайтиПоПолномуИмени():
МетаОбъект = Метаданные.НайтиПоПолномуИмени("Справочник.Номенклатура");
Если МетаОбъект = Неопределено Тогда
ВызватьИсключение "Объект метаданных не найден";
КонецЕсли;
Если известна ссылка на конкретный элемент, метаданные получают от неё: МетаданныеОбъекта = Ссылка.Метаданные(). Этот приём удобен в универсальных обработчиках, где тип входящей ссылки заранее не определён.
Обратите внимание на формат полного имени: для справочников и документов вид указывается в единственном числе — Справочник.Номенклатура, Документ.РеализацияТоваровУслуг, Перечисление.СтавкиНДС, РегистрСведений.КурсыВалют. Ошибка в числе (множественное вместо единственного) — частая причина, почему НайтиПоПолномуИмени возвращает Неопределено.
Основной способ: получение менеджера через имя коллекции
Универсальный рабочий приём — определить имя глобальной коллекции менеджеров по виду метаданных и обратиться к ней через Вычислить():
Функция ПолучитьМенеджерПоМетаданным(МетаОбъект)
ПолноеИмя = МетаОбъект.ПолноеИмя();
ВидОбъекта = СтрРазделить(ПолноеИмя, ".")[0];
СоответствиеКоллекций = Новый Соответствие;
СоответствиеКоллекций.Вставить("Справочник", "Справочники");
СоответствиеКоллекций.Вставить("Документ", "Документы");
СоответствиеКоллекций.Вставить("Перечисление", "Перечисления");
СоответствиеКоллекций.Вставить("ПланВидовХарактеристик", "ПланыВидовХарактеристик");
СоответствиеКоллекций.Вставить("ПланСчетов", "ПланыСчетов");
СоответствиеКоллекций.Вставить("ПланВидовРасчета", "ПланыВидовРасчета");
СоответствиеКоллекций.Вставить("РегистрСведений", "РегистрыСведений");
СоответствиеКоллекций.Вставить("РегистрНакопления", "РегистрыНакопления");
СоответствиеКоллекций.Вставить("РегистрБухгалтерии", "РегистрыБухгалтерии");
СоответствиеКоллекций.Вставить("РегистрРасчета", "РегистрыРасчета");
СоответствиеКоллекций.Вставить("БизнесПроцесс", "БизнесПроцессы");
СоответствиеКоллекций.Вставить("Задача", "Задачи");
ИмяКоллекции = СоответствиеКоллекций[ВидОбъекта];
Если ИмяКоллекции = Неопределено Тогда
ВызватьИсключение "Менеджер для вида " + ВидОбъекта + " не поддерживается";
КонецЕсли;
Возврат Вычислить(ИмяКоллекции + "[""" + МетаОбъект.Имя + """]");
КонецФункции
Приём Вычислить("Справочники[""Номенклатура""]") возвращает тот же менеджер, что и прямое обращение Справочники.Номенклатура. Индексация коллекции строкой работает для всех прикладных видов объектов.
Менеджер = Вычислить("Справочники[""" + МетаОбъект.Имя + """]");
НовыйЭлемент = Менеджер.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Тест";
НовыйЭлемент.Записать();Альтернатива без Вычислить
Метод Вычислить() выполняет произвольный код и потенциально небезопасен, если имя объекта приходит извне. Безопаснее строить ветвление через Если...ИначеЕсли по типу метаданных и обращаться к коллекциям напрямую:
Если Метаданные.Справочники.Содержит(МетаОбъект) Тогда
Менеджер = Справочники[МетаОбъект.Имя];
ИначеЕсли Метаданные.Документы.Содержит(МетаОбъект) Тогда
Менеджер = Документы[МетаОбъект.Имя];
ИначеЕсли Метаданные.Перечисления.Содержит(МетаОбъект) Тогда
Менеджер = Перечисления[МетаОбъект.Имя];
КонецЕсли;
Метод Содержит() коллекции метаданных проверяет принадлежность объекта конкретному виду — это надёжнее разбора строки полного имени и не зависит от локализации кода.
Готовая функция в Библиотеке стандартных подсистем
В конфигурациях на базе БСП (Управление торговлей, ERP, Бухгалтерия предприятия и другие типовые) есть готовый механизм. Общий модуль ОбщегоНазначения предоставляет функцию МенеджерОбъектаПоПолномуИмени(ПолноеИмя), а также МенеджерОбъектаПоСсылке(Ссылка).
Менеджер = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени("Справочник.Номенклатура");
Пустая = Менеджер.ПустаяСсылка();
Функция БСП сама определяет вид объекта, проверяет существование метаданных и вызывает понятное исключение при ошибке. Если конфигурация включает БСП, используйте её, а не собственный велосипед: код короче и протестирован.
Практический сценарий: универсальная обработка по произвольному объекту
Типовая задача — обработка, которая получает на вход полное имя объекта и выполняет над ним действие, например подсчёт количества элементов или поиск по наименованию:
Функция НайтиПоНаименованиюУниверсально(ПолноеИмя, СтрокаПоиска)
МетаОбъект = Метаданные.НайтиПоПолномуИмени(ПолноеИмя);
Если МетаОбъект = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если НЕ Метаданные.Справочники.Содержит(МетаОбъект)
И НЕ Метаданные.ПланыВидовХарактеристик.Содержит(МетаОбъект) Тогда
ВызватьИсключение "Поиск по наименованию поддерживается только для справочников и ПВХ";
КонецЕсли;
Менеджер = Справочники[МетаОбъект.Имя];
Если Метаданные.ПланыВидовХарактеристик.Содержит(МетаОбъект) Тогда
Менеджер = ПланыВидовХарактеристик[МетаОбъект.Имя];
КонецЕсли;
Возврат Менеджер.НайтиПоНаименованию(СтрокаПоиска, Истина);
КонецФункции
Здесь важна предварительная проверка вида объекта: метод НайтиПоНаименованию есть не у всех менеджеров. У документов вместо него используется НайтиПоНомеру, у регистров сведений поиск идёт по измерениям через набор записей или запрос. Универсальный код обязан учитывать эти различия, иначе получите ошибку «Метод объекта не обнаружен» в режиме выполнения.
- 1Получите объект метаданных через Метаданные.НайтиПоПолномуИмени() или Ссылка.Метаданные()
- 2Проверьте, что объект найден (не Неопределено)
- 3Определите вид объекта методом Содержит() соответствующей коллекции метаданных
- 4Получите менеджер обращением к коллекции по имени: Справочники[МетаОбъект.Имя]
- 5Проверьте наличие нужного метода у менеджера для данного вида объектов
- 6Выполните операцию и проверьте результат
Проверка результата и ограничения
После получения менеджера убедитесь, что он работает: вызовите безопасный метод, например ПустаяСсылка(). Если менеджер получен корректно, метод вернёт пустую ссылку соответствующего типа. Дополнительно можно сравнить тип: ТипЗнч(Менеджер) = Тип("СправочникМенеджер.Номенклатура").
Есть ограничения, о которых нужно помнить. Во-первых, обращение Справочники[Имя] с несуществующим именем вызовет исключение, поэтому проверка метаданных обязательна до получения менеджера. Во-вторых, в безопасном режиме (например, при выполнении внешних обработок с ограничениями) Вычислить() может быть недоступен — используйте прямое обращение к коллекциям. В-третьих, у внешних источников данных и констант структура менеджеров другая: у констант единый менеджер КонстантыМенеджер через набор Константы.СоздатьНабор().
Как проверить результат
ТипЗнч возвращает тип вида СправочникМенеджер.<Имя>
Переменная равна Неопределено или возникло исключение
НайтиПоПолномуИмени вернул объект
Возвращено Неопределено — проверьте формат полного имени
Вызов метода выполняется без ошибки
Ошибка «Метод объекта не обнаружен» — вид объекта не поддерживает метод
Типичные ошибки при получении менеджера
Самая распространённая ошибка — неправильный формат полного имени. Пишут Справочники.Номенклатура вместо Справочник.Номенклатура, и НайтиПоПолномуИмени возвращает Неопределено. Вторая по частоте — попытка вызвать у менеджера метод, которого у данного вида объектов нет: СоздатьЭлемент() у перечисления или НайтиПоНаименованию() у документа.
Третья ошибка — использование Вычислить() со строкой, собранной из пользовательского ввода, без проверки. Это открывает возможность выполнения произвольного кода. Всегда проверяйте, что имя объекта соответствует реальному объекту метаданных, прежде чем подставлять его в вычисляемое выражение.
Частые вопросы
Как получить менеджер, если известна только ссылка на объект?
Вызовите у ссылки метод Метаданные() — получите объект описания метаданных, затем определите вид через Метаданные.Справочники.Содержит() и аналогичные проверки, после чего обратитесь к нужной коллекции: Справочники[Ссылка.Метаданные().Имя]. В конфигурациях с БСП используйте ОбщегоНазначения.МенеджерОбъектаПоСсылке(Ссылка).
Чем Вычислить() отличается от Выполнить() при получении менеджера?
Вычислить() выполняет выражение и возвращает его результат — именно оно нужно для получения менеджера как значения. Выполнить() исполняет оператор и ничего не возвращает, поэтому для этой задачи не подходит. Оба метода потенциально опасны с непроверенными строками.
Можно ли получить менеджер регистра сведений через метаданные?
Да, схема та же: проверить Метаданные.РегистрыСведений.Содержит(МетаОбъект) и обратиться РегистрыСведений[МетаОбъект.Имя]. Через такой менеджер доступны СоздатьНаборЗаписей(), СоздатьМенеджерЗаписи(), Получить() и другие методы работы с записями регистра.
Почему НайтиПоПолномуИмени возвращает Неопределено, хотя объект есть в конфигурации?
Проверьте формат строки: вид объекта указывается в единственном числе и без пробелов — «Справочник.Имя», «Документ.Имя», «РегистрСведений.Имя». Также убедитесь, что объект не входит в состав подсистемы, скрытой функциональными опциями, — метаданные при этом существуют, но проверьте точность написания имени, включая регистр не влияет, а лишние символы — да.
Есть ли единый метод, который возвращает менеджер для любого вида объекта?
В чистой платформе универсального метода нет — нужно определять вид и обращаться к соответствующей коллекции. В конфигурациях на БСП эту роль выполняет ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(), которая внутри делает то же самое ветвление, но уже протестировано и поддерживает все прикладные виды объектов.
Работает ли получение менеджера через Вычислить в безопасном режиме?
В безопасном режиме использование Вычислить() и Выполнить() может быть запрещено настройками профиля безопасности или режимом исполнения. Надёжный вариант — обращение к коллекциям напрямую через Содержит() и индексацию по имени, этот способ в безопасном режиме работает.
Что важно запомнить
Менеджер объекта по метаданным получают в два шага: сначала объект метаданных через НайтиПоПолномуИмени() или Ссылка.Метаданные(), затем обращение к коллекции менеджеров по имени — Справочники[Имя], Документы[Имя] и т.д. Вид объекта определяйте методом Содержит(), избегайте Вычислить() с непроверенными строками, а в конфигурациях с БСП используйте готовую ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени().