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