Можно ли в 1С обращаться к предопределенным элементам справочника через иерархию групп в коде?

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

При проектировании структуры данных в 1С часто возникает желание сделать код максимально читаемым и логичным. Одна из распространенных идей — создать иерархический справочник (например, "Свойства"), создать в нем группы (например, "Цвета", "Положение"), а внутри групп разместить предопределенные элементы. Логичным продолжением этой идеи кажется возможность обращаться к этим элементам в программном коде, используя синтаксис, повторяющий структуру дерева: Справочники.Свойства.Цвета.Зеленый.

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

Архитектура предопределенных элементов: Метаданные против Данных

Для начала проанализируем, как платформа 1С воспринимает предопределенные элементы. Когда мы создаем элемент в конфигураторе, мы задаем ему свойство Имя. Это имя является идентификатором объекта метаданных. Ключевой момент здесь заключается в том, что Имя должно быть уникальным в пределах всего объекта метаданных (всего Справочника), а не в пределах конкретной группы.

Рассмотрим разницу между тем, как мы видим данные, и как их видит платформа:

  1. Визуальная иерархия (Данные): Для пользователя и программиста в режиме "Предприятие" справочник выглядит как дерево. У элемента "Зеленый" есть родитель "Цвета". Но "Родитель" — это просто ссылка в таблице базы данных.
  2. Программный доступ (Метаданные): Обращение через менеджер справочника Справочники.ИмяСправочника.ИмяПредопределенного работает напрямую с таблицей предопределенных имен. В этой таблице нет понятия иерархии. Группа "Цвета" — это один предопределенный элемент, а элемент "Зеленый" — это другой, совершенно независимый с точки зрения метаданных элемент.

Именно поэтому попытка написать Справочники.Свойства.Цвета.Зеленый приведет к синтаксической ошибке или ошибке исполнения. Платформа попытается найти у элемента "Цвета" (который является ссылкой) свойство "Зеленый", но такого свойства у ссылки нет.

Почему нельзя использовать "пространства имен" внутри справочника?

Давайте выясним техническую причину ограничения. Если бы платформа позволяла создавать элементы с одинаковым именем "Зеленый" в разных группах (например, в группе "Цвета" и в группе "Статусы"), то при обращении из кода возникла бы неопределенность. Уникальность идентификатора (Имени) гарантирует, что, написав Справочники.Свойства.Зеленый, мы получим конкретную ссылку.

Следовательно, иерархия в справочниках — это свойство данных (значение реквизита "Родитель"), а не свойство конфигурации (структура объектов).

Решение 1: Использование плоской структуры имен (Штатный метод)

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

Вместо желаемой структуры .Цвета.Зеленый, мы создаем предопределенные элементы со следующими именами:

Тогда в коде обращение будет выглядеть следующим образом:


// Обращение к элементу
ТекущийЦвет = Справочники.Свойства.Цвета_Зеленый;

// Обращение к группе (если она тоже предопределенная)
РодительскаяГруппа = Справочники.Свойства.Цвета;

Это полностью решает задачу уникальности и позволяет сохранить некоторую логическую группировку за счет префиксов в именах. Да, это не дает "точечной" нотации (dot syntax) для вложенности, но это стандартный подход в 1С.

Решение 2: Использование Перечислений

Если ваша задача — хранить фиксированный список значений, которые никогда не будут меняться пользователем, давайте рассмотрим объект Перечисление. Это наиболее близкий аналог для хранения списка опций.

Обращение к перечислению выглядит так:

ТекущийЦвет = Перечисления.Цвета.Зеленый;

Однако, проанализируем ограничения этого подхода, которые были выявлены в обсуждении:

  1. Отсутствие дополнительных полей. У перечисления есть только Имя и Синоним. Вы не можете добавить пользовательский реквизит (например, строковый код цвета "green" для веб-интеграции) напрямую в перечисление.
  2. Невозможность редактирования. Пользователь не может добавить новый цвет в режиме "Предприятие".

Если вам нужно получить строковое представление значения перечисления (синоним), используем функцию Строка():


// Вернет "Зеленый" (если это задано в синониме)
НазваниеЦвета = Строка(Перечисления.Цвета.Зеленый);

Если же требуется хранить соответствие "Зеленый" -> "green", для перечислений придется писать отдельную функцию, которая через Если...ИначеЕсли или Соответствие будет возвращать нужные данные, что усложняет поддержку кода.

Решение 3: Эмуляция иерархии через Общий Модуль (Паттерн "Кэш свойств")

Если для вас критически важен именно синтаксис Свойства.Группа.Элемент, и вы хотите объединить гибкость справочников (наличие реквизитов) с красотой кода, мы можем реализовать программную обертку. Давайте создадим механизм, который будет собирать нужную структуру.

Алгоритм реализации:

  1. Создаем справочник "Свойства" с нужной иерархией и реквизитами (например, "КодДляAPI").
  2. Создаем Общий модуль, например, УправлениеСвойствами.
  3. В модуле пишем функцию, которая возвращает фиксированную структуру данных.

Пример кода в общем модуле:


Функция ПолучитьДеревоСвойств() Экспорт
    
    // 1. Подготавливаем структуру для Цветов
    Цвета = Новый Структура;
    // Здесь мы обращаемся к предопределенным элементам, названным плоско (см. Решение 1)
    Цвета.Вставить("Зеленый", Справочники.Свойства.Цвета_Зеленый);
    Цвета.Вставить("Красный", Справочники.Свойства.Цвета_Красный);
    
    // 2. Подготавливаем структуру для Положения
    Положение = Новый Структура;
    Положение.Вставить("Верх", Справочники.Свойства.Положение_Верх);
    Положение.Вставить("Низ",  Справочники.Свойства.Положение_Низ);
    
    // 3. Собираем общую структуру
    ОбщиеСвойства = Новый Структура;
    ОбщиеСвойства.Вставить("Цвета", Цвета);
    ОбщиеСвойства.Вставить("Положение", Положение);
    
    Возврат ОбщиеСвойства;

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

Теперь в любом месте конфигурации мы можем использовать желанный синтаксис:


Свойства = УправлениеСвойствами.ПолучитьДеревоСвойств();

// Красивое обращение через точку
МойЦвет = Свойства.Цвета.Зеленый;

// Доступ к дополнительным реквизитам справочника
КодДляСайта = МойЦвет.КодДляAPI; // Вернет "green"

Плюсы и минусы этого подхода:

Преимущество очевидно: вы получаете идеальный автокомплит (если модуль возвращает фиксированную структуру и платформа сможет её проанализировать, либо если вы знаете структуру) и читаемый код.

Недостатком является необходимость поддерживать этот код. Если вы добавите новый предопределенный элемент в конфигураторе, вам придется руками добавить строчку в общий модуль. Если элементов сотни, этот метод становится трудоемким.

Итоги и рекомендации

Давайте подытожим, какой подход лучше выбрать в зависимости от ваших целей:

  1. Если значений мало, они никогда не меняются, и им не нужны сложные дополнительные атрибуты — выбирайте Перечисления.
  2. Если нужны дополнительные реквизиты (например, английское название, код для интеграции), и вы хотите стандартное решение 1С — используйте Справочник с предопределенными элементами и плоским именованием (Цвета_Зеленый).
  3. Если вам жизненно необходим синтаксис с точками для повышения читаемости кода в больших проектах — используйте Общий модуль, который возвращает структуру ссылок, но будьте готовы обновлять его при добавлении новых свойств.

Платформа 1С жестко разграничивает пространство имен метаданных и иерархию данных в базе. Понимание этого принципа позволит вам избегать ошибок при проектировании архитектуры решения.

← На главную