При разработке внешних обработок или универсальных механизмов в 1С часто возникает задача: имея на руках только ссылку на элемент (например, переданную в качестве параметра), необходимо программно узнать системное имя этого справочника. Это бывает нужно для динамического формирования пути к форме, чтобы затем открыть ее для добавления нового элемента или редактирования.
Рассмотрим классическую ситуацию, с которой сталкиваются многие разработчики: при попытке использовать свойство Метаданные система выдает ошибку, сообщая, что метод или переменная не обнаружены. Проанализируем, почему так происходит, и разберем по шагам все возможные способы получения имени справочника — от стандартных серверных методов до хитрых обходных путей на стороне клиента.
Если вы пытаетесь обратиться к метаданным через Ссылка.Метаданные().Имя и получаете ошибку, давайте выясним причину. Обычно проблема кроется в одном из двух факторов:
Метаданные() доступен исключительно на сервере, в толстом клиенте или во внешнем соединении. Если вы пытаетесь вызвать его в процедуре с директивой &НаКлиенте, платформа выдаст ошибку, так как на тонком клиенте структуры метаданных недоступны.Неопределено, Null или пустую ссылку, метод не отработает корректно.Если код выполняется на сервере, то получить имя справочника очень просто. Рассмотрим несколько надежных подходов.
Способ 1: Прямое обращение к метаданным ссылки
Самый очевидный и быстрый вариант, если переменная гарантированно содержит ссылку на объект:
ИмяСправочника = СсылкаНаОбъект.Метаданные().Имя;
Способ 2: Поиск по типу значения
Если вы работаете с составными типами или извлекаете данные из массивов/выборок, бывает удобнее получить имя объекта через глобальный контекст метаданных, используя тип значения:
ТипОбъекта = ТипЗнч(СсылкаНаОбъект);
ИмяСправочника = Метаданные.НайтиПоТипу(ТипОбъекта).Имя;
Способ 3: Использование готовых функций БСП
В большинстве современных типовых конфигураций 1С встроена Библиотека стандартных подсистем (БСП). Посмотрим на пример использования готовой функции, которая сразу вернет строку в формате "Справочник.ИмяСправочника":
ИмяОбъекта = ОбщегоНазначения.ИмяТаблицыПоСсылке(СсылкаНаОбъект);
// Результат: "Справочник.Номенклатура"
Иногда обращаться к серверу ради получения одной строки нецелесообразно. Рассмотрим хитрый способ получить системное имя справочника прямо в контексте &НаКлиенте. Для этого мы задействуем функции работы с XML.
Каждый тип данных в 1С имеет свое внутреннее XML-представление. Извлечем его:
&НаКлиенте
Процедура ПолучитьИмяНаКлиенте(СсылкаНаОбъект)
// Получаем XML тип по типу значения ссылки
ИмяТипаXML = XMLТип(ТипЗнч(СсылкаНаОбъект)).ИмяТипа;
// Результатом будет строка вида "CatalogRef.ИмяСправочника"
// Отбрасываем префикс, чтобы получить чистое имя
ИмяСправочника = СтрЗаменить(ИмяТипаXML, "CatalogRef.", "");
Сообщить(ИмяСправочника);
КонецПроцедуры
Этот подход безопасен, быстр и не вызывает дополнительных накладных расходов на клиент-серверное взаимодействие.
Вернемся к первоначальной задаче — открытию формы для добавления нового элемента. Проанализируем типичную ошибку в формировании строки пути к форме.
Часто разработчики пытаются собрать строку вида "Справочник." + ИмяСправочника + ".Форма.ФормаЭлемента". Однако слово "Форма" и конкретное имя требуются только при вызове произвольных (нестандартных) форм. Для открытия основной формы объекта по умолчанию нужно использовать предопределенный идентификатор ФормаОбъекта.
Разберем правильный код для открытия формы нового элемента:
&НаКлиенте
Процедура ОткрытьФормуНовогоЭлемента(СсылкаНаОбъект)
ИмяТипаXML = XMLТип(ТипЗнч(СсылкаНаОбъект)).ИмяТипа;
ИмяСправочника = СтрЗаменить(ИмяТипаXML, "CatalogRef.", "");
// Формируем правильную строку пути к основной форме
СтрокаФормы = "Справочник." + ИмяСправочника + ".ФормаОбъекта";
Попытка
ОткрытьФорму(СтрокаФормы);
Исключение
Сообщить("Не удалось открыть форму объекта!");
КонецПопытки;
КонецПроцедуры
Если же стоит задача просто открыть существующий элемент по его ссылке, то собирать строку метаданных вообще не нужно. В управляемом приложении достаточно использовать глобальный метод:
ПоказатьЗначение(Неопределено, СсылкаНаОбъект);
Используйте эти методы в зависимости от вашей конкретной архитектурной задачи. Если код позволяет, обращайтесь к метаданным на сервере, а если требуется минимизировать контекстные вызовы — применяйте элегантный трюк с XMLТип на клиенте.