Как получить дополнительные реквизиты номенклатуры в 1С 8.3 без обращения к форме

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

В этой статье мы подробно разберем, как устроена подсистема «Свойства» Библиотеки стандартных подсистем (БСП), почему на форме появляются странные идентификаторы и как правильно извлекать эти данные программно на сервере с помощью запросов и встроенных механизмов БСП.

Архитектура хранения свойств в БСП: реквизиты против сведений

Прежде чем перейти к написанию кода, давайте проанализируем внутреннее устройство подсистемы «Свойства». БСП разделяет все дополнительные свойства на две категории, которые хранятся принципиально в разных местах базы данных:

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

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

Почему на форме генерируются странные имена реквизитов?

Когда мы открываем форму номенклатуры в конфигураторе, мы не видим там полей вроде «Цвет», «Размер» или «Производитель». Эти элементы управления создаются платформой динамически в момент открытия формы. БСП выполняет следующие действия:

  1. Считывает настройки из плана видов характеристик ДополнительныеРеквизитыИСведения.
  2. Для каждого активного свойства берет его уникальный идентификатор (UUID).
  3. Поскольку правила встроенного языка 1С запрещают использовать дефисы в именах переменных и реквизитов формы, БСП заменяет их на специальные символы (например, символ x) и добавляет префикс. Получается строка вида ДополнительныйРеквизитЗначение_8A949A3Cx9FBD....
  4. Программно добавляет реквизит с таким именем на форму и связывает его с элементом управления.

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

Рассмотрим три правильных и надежных способа получения значений дополнительных реквизитов.

Способ 1. Прямой запрос к табличной части (Идеально для отчетов и циклов)

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

Разберем пример запроса, который выбирает значение конкретного свойства для заданной номенклатуры:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	НоменклатураДополнительныеРеквизиты.Ссылка КАК Номенклатура,
    |	НоменклатураДополнительныеРеквизиты.Значение КАК ЗначениеРеквизита
    |ИЗ
    |	Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
    |ГДЕ
    |	НоменклатураДополнительныеРеквизиты.Ссылка В(&МассивНоменклатуры)
    |	И НоменклатураДополнительныеРеквизиты.Свойство = &НужноеСвойство";

// В качестве параметра Свойство передается ссылка на элемент ПВХ ДополнительныеРеквизитыИСведения
Запрос.УстановитьПараметр("НужноеСвойство", ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Цвет (Номенклатура)"));
Запрос.УстановитьПараметр("МассивНоменклатуры", МассивСсылок);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обрабатываем полученные данные
    Сообщить("Для номенклатуры " + Выборка.Номенклатура + " установлено значение: " + Выборка.ЗначениеРеквизита);
КонецЦикла;

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

Способ 2. Использование программного интерфейса БСП (Рекомендуется для бизнес-логики)

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

Для этого используется функция ЗначениеСвойства(). Посмотрим на практический пример:


// 1. Находим целевое свойство (элемент ПВХ)
СвойствоЦвет = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("ИмяДляРазработчиков", "Цвет_8A9499FB");

Если ЗначениеЗаполнено(СвойствоЦвет) Тогда
    // 2. Получаем значение свойства для конкретной ссылки номенклатуры
    ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаНоменклатуру, СвойствоЦвет);
    
    // 3. Используем полученное значение в коде
    Если ЗначениеРеквизита = Справочники.ЗначенияСвойствОбъектов.НайтиПоНаименованию("Красный") Тогда
        // Выполняем необходимое действие...
    КонецЕсли;
КонецЕсли;

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

Способ 3. Работа со свойствами в контексте формы

Бывают ситуации, когда вам действительно необходимо получить значение дополнительного реквизита прямо на форме элемента в процессе интерактивной работы пользователя (например, при изменении другого поля на клиенте, когда объект еще не записан в базу данных). Как мы выяснили, обращаться напрямую к имени с UUID нельзя.

Для решения этой задачи разработчики БСП предусмотрели специальную служебную коллекцию на форме — таблицу Свойства_ОписаниеДополнительныхРеквизитов. В ней хранится карта соответствия между реальными свойствами (ссылками ПВХ) и динамическими именами элементов формы.

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


&НаКлиенте
Процедура ПолучитьЗначениеРеквизитаНаФорме()
    
    // Определяем свойство, значение которого нам нужно прочитать
    НужноеСвойство = ПолучитьСвойствоНа Сервере(); 
    
    // Отыскиваем строку описания этого свойства в служебной коллекции формы
    ПараметрыОтбора = Новый Структура("Свойство", НужноеСвойство);
    НайденныеСтроки = Свойства_ОписаниеДополнительныхРеквизитов.НайтиСтроки(ПараметрыОтбора);
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        СтрокаОписания = НайденныеСтроки[0];
        
        // Получаем то самое динамическое имя реквизита формы с UUID
        ИмяРеквизитаФормы = СтрокаОписания.ИмяРеквизитаЗначение; 
        
        // Обращаемся к реквизиту формы по его динамическому имени
        ТекущееЗначениеНаФорме = ЭтотОбъект[ИмяРеквизитаФормы];
        
        ПоказатьПредупреждение(, "Текущее значение на форме: " + ТекущееЗначениеНаФорме);
    КонецЕсли;
    
КонецПроцедуры

Подведем итоги

Для эффективной работы с дополнительными реквизитами в конфигурациях на базе БСП (таких как «1С:Управление торговлей 11», «1С:ERP», «1С:Комплексная автоматизация») всегда придерживайтесь следующих правил:

← На главную