При разработке отчетов, обработок или печатных форм в среде «1С:Предприятие» программисты часто сталкиваются с задачей вывода данных, которые были созданы пользователями самостоятельно. Типичный пример — создание дополнительного реквизита для справочника Номенклатура средствами Библиотеки стандартных подсистем (БСП) в пользовательском режиме. Попытка найти этот реквизит напрямую в дереве метаданных конфигуратора (в свойствах или табличных частях справочника) оборачивается неудачей. Выясним причину этой особенности и разберем по шагам, как правильно извлекать такие данные программным путем.
Прежде всего, проанализируем архитектуру хранения данных в платформе «1С:Предприятие». Конфигуратор отображает только статическую структуру метаданных, которая жестко зафиксирована разработчиком информационной базы. Все дополнительные реквизиты и сведения, которые пользователи добавляют через интерфейс программы, создаются динамически.
Они не меняют физическую структуру таблиц СУБД для конкретного справочника. Вместо этого БСП использует универсальный механизм свойств, основанный на использовании специального Плана видов характеристик (ПВХ) ДополнительныеРеквизитыИСведения и универсальных коллекций хранения.
Для того чтобы успешно решить задачу получения таких данных в коде или запросе конфигуратора (например, для макета печатной формы), нам необходимо разобраться в двух ключевых аспектах:
---
В БСП предусмотрено два разных механизма для расширения свойств объектов. Очень важно их различать, так как от этого зависит способ написания запроса:
ДополнительныеРеквизиты.ДополнительныеСведения.Поскольку автор вопроса указал, что ему требуется получить реквизит справочника Номенклатура, мы имеем дело именно с табличной частью объекта.
---
Чтобы гарантировать стабильную работу нашего программного кода в будущем, мы не должны обращаться к реквизиту по его синониму (заголовку), видимому пользователю. Пользователь может легко переименовать «Срок поставки» в «Срок доставки (дни)», и тогда наш запрос перестанет работать.
Для решения этой проблемы разработчики БСП предусмотрели специальный идентификатор:
СрокДоставки или ЧисловойКодВыгрузки.Имя соответствующего элемента Плана видов характеристик ДополнительныеРеквизитыИСведения. Именно его мы и будем искать из конфигуратора.---
Рассмотрим подробнее три основных практических сценария извлечения значения дополнительного реквизита для печатной формы или отчета.
Этот способ удобен, когда весь код печатной формы строится на одном большом запросе и вы не хотите выполнять предварительный поиск элементов ПВХ в коде на встроенном языке. Мы можем обратиться к реквизиту Имя свойства через точку прямо в тексте запроса.
Рассмотрим пример построения такого запроса:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование,
ЕСТЬNULL(НоменклатураДопРеквизиты.Значение, 0) КАК ЧисловоеЗначениеРеквизита
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДопРеквизиты
ПО НоменклатураДопРеквизиты.Ссылка = Номенклатура.Ссылка
И НоменклатураДопРеквизиты.Свойство.Имя = "СрокДоставки"
Важное примечание: Использование конструкции ЕСТЬNULL позволяет нам подставить дефолтное значение (например, 0 для числового типа), если у конкретной позиции номенклатуры данный дополнительный реквизит не был заполнен в пользовательском режиме.
С точки зрения оптимизации СУБД, обращение через точку к реквизитам связанных таблиц (Свойство.Имя) в условиях соединения может замедлять выполнение запроса на больших базах данных. Более профессиональным подходом считается предварительное получение ссылки на само свойство и передача его в качестве параметра запроса.
Разберем этот метод по шагам:
1. В программном коде формирования печатной формы (модуль менеджера или объект обработки) перед выполнением запроса находим наше свойство:
// Находим элемент ПВХ по уникальному имени разработчика
СвойствоДопРеквизита = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "СрокДоставки");
Если СвойствоДопРеквизита.Пустая() Тогда
ВызватьИсключение "В системе не найден дополнительный реквизит с именем для разработчика 'СрокДоставки'!";
КонецЕсли;
2. Передаем найденную ссылку в параметры запроса и выполняем соединение по индексированному полю ссылки:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование,
| ЕСТЬNULL(НоменклатураДопРеквизиты.Значение, 0) КАК ЧисловоеЗначениеРеквизита
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДопРеквизиты
| ПО НоменклатураДопРеквизиты.Ссылка = Номенклатура.Ссылка
| И НоменклатураДопРеквизиты.Свойство = &ПараметрСвойство";
Запрос.УстановитьПараметр("ПараметрСвойство", СвойствоДопРеквизита);
РезультатЗапроса = Запрос.Выполнить();
Если вам не нужно собирать сложную таблицу данных запросом, а требуется лишь получить значение этого реквизита для конкретного объекта в процессе выполнения алгоритма на встроенном языке, наилучшим решением будет использование штатных функций БСП.
В составе библиотеки есть общий модуль УправлениеСвойствами, который содержит готовую функцию ЗначениеСвойства(). Она самостоятельно определяет тип свойства, место его хранения (ТЧ или регистр) и возвращает готовое значение.
Посмотрим на пример вызова этой функции:
// СсылкаНаНоменклатуру - ссылка на элемент справочника Номенклатура
ИмяСвойства = "СрокДоставки";
ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаНоменклатуру, ИмяСвойства);
Если ЗначениеРеквизита <> Неопределено Тогда
// Выполняем логику с полученным числовым значением
ИтоговыйСрок = ЗначениеРеквизита + 5;
КонецЕсли;
---
Мы выяснили, что отсутствие созданных в пользовательском режиме дополнительных реквизитов в конфигураторе — это естественное поведение платформы. Благодаря архитектуре БСП, разработчик может легко обходить это ограничение, используя План видов характеристик ДополнительныеРеквизитыИСведения и обращаясь к табличной части объекта по уникальному «Имени для разработчика». Использование рассмотренных методов гарантирует стабильность работы программного кода при любых интерфейсных изменениях, выполняемых пользователями.