К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как получить значение дополнительного реквизита в запросе 1С

Как получить значение дополнительного реквизита в запросе 1С: соединение с табличной частью ДополнительныеРеквизиты, параметры свойств, примеры кода и типичные ошибки.

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

Механизм одинаков для справочников (номенклатура, контрагенты) и документов: у объекта есть табличная часть «ДополнительныеРеквизиты» с полями «Свойство» (ссылка на план видов характеристик «ДополнительныеРеквизитыИСведения») и «Значение» (характеристика произвольного типа). Зная это, запрос строится по стандартному шаблону.

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

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

Дополнительные реквизиты — часть подсистемы «Свойства» Библиотеки стандартных подсистем (БСП). Когда пользователь добавляет реквизит через «Администрирование — Общие настройки — Дополнительные реквизиты и сведения», конфигурация не изменяется: новое поле не появляется в структуре таблицы. Вместо этого создаётся элемент плана видов характеристик «ДополнительныеРеквизитыИСведения», а введённые значения записываются в табличную часть объекта.

Из этого следуют два практических вывода. Первый: в запросе к таблице справочника или документа дополнительный реквизит недоступен как обычное поле. Второй: у одного объекта может быть несколько строк в табличной части — по одной на каждый заполненный реквизит, поэтому без отбора по свойству соединение размножит строки результата.

Базовый запрос: значение одного дополнительного реквизита

Типовой шаблон выглядит так: левое соединение таблицы объекта с табличной частью «ДополнительныеРеквизиты» по ссылке, с условием на конкретное свойство. Свойство удобнее всего передавать параметром.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Номенклатура,

ДопРеквизиты.Значение КАК Цвет

ИЗ

Справочник.Номенклатура КАК Номенклатура

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты

ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка

И ДопРеквизиты.Свойство = &СвойствоЦвет

Левое соединение важно: оно сохранит в выборке объекты, у которых реквизит не заполнен — для них поле «Значение» будет NULL. Если использовать внутреннее соединение, такие объекты выпадут из результата, что часто становится причиной «пропавших» строк в отчётах.

Параметр «СвойствоЦвет» — это ссылка на элемент плана видов характеристик «ДополнительныеРеквизитыИСведения». Получить её можно поиском по имени или через предопределённое имя, если оно задано.

bsl
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура.Ссылка, ДопРеквизиты.Значение КАК Цвет ИЗ Справочник.Номенклатура КАК Номенклатура ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка И ДопРеквизиты.Свойство = &Свойство";
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Цвет");
Запрос.УстановитьПараметр("Свойство", Свойство);
Результат = Запрос.Выполнить().Выгрузить();

Как получить ссылку на свойство для параметра запроса

Самый хрупкий способ — поиск по наименованию: НайтиПоНаименованию("Цвет"). Он сломается, если пользователь переименует реквизит или в базе появятся два свойства с одинаковым именем для разных наборов объектов. Использовать его допустимо в разовых обработках, но не в прикладном коде.

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

Выборка нескольких дополнительных реквизитов одним запросом

Если нужно вывести несколько реквизитов, есть два подхода. Первый — несколько левых соединений с одной и той же табличной частью, каждое со своим псевдонимом и своим условием по свойству. Запрос получается «плоским»: одна строка на объект, каждый реквизит в своей колонке.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Номенклатура,

РеквизитЦвет.Значение КАК Цвет,

РеквизитВес.Значение КАК Вес

ИЗ

Справочник.Номенклатура КАК Номенклатура

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК РеквизитЦвет

ПО Номенклатура.Ссылка = РеквизитЦвет.Ссылка

И РеквизитЦвет.Свойство = &СвойствоЦвет

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК РеквизитВес

ПО Номенклатура.Ссылка = РеквизитВес.Ссылка

И РеквизитВес.Свойство = &СвойствоВес

Второй подход — одно соединение с отбором по списку свойств и последующая группировка или свёртка в СКД. Он удобен, когда набор реквизитов динамический, но результат будет «вертикальным»: строки вида «объект — свойство — значение».

Сравнение вариантов

Несколько соединений

Подходит для фиксированного небольшого набора реквизитов. Результат — плоская таблица, удобная для отчёта. Минус: текст запроса нужно править при добавлении реквизита.

Одно соединение со списком свойств

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

СКД с характеристиками

В отчётах на СКД дополнительные реквизиты можно подключать штатным механизмом характеристик без ручных соединений. Минус: требует настройки и понимания СКД.

Фильтрация объектов по значению дополнительного реквизита

Частая задача — отобрать не значение, а сами объекты, у которых реквизит равен нужному значению. Здесь условие на значение лучше выносить в секцию ГДЕ, а соединение делать внутренним, если незаполненные объекты не нужны.

ВЫБРАТЬ

Номенклатура.Ссылка КАК Номенклатура

ИЗ

Справочник.Номенклатура КАК Номенклатура

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты

ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка

ГДЕ

ДопРеквизиты.Свойство = &Свойство

И ДопРеквизиты.Значение = &Значение

Учтите тип поля «Значение»: это характеристика составного типа. Сравнение строки со строкой или ссылки со ссылкой работает напрямую, но сравнение с несовместимым типом (например, строковое значение с параметром-числом) вернёт пустой результат без ошибки. При сомнениях проверьте фактический тип значения в базе через консоль запросов.

Дополнительные сведения: отличие от реквизитов

Не путайте дополнительные реквизиты с дополнительными сведениями. Сведения хранятся не в табличной части объекта, а в регистре сведений «ДополнительныеСведения» с измерением «Объект» и «Свойство». Запрос к ним строится иначе — соединение с регистром по ссылке на объект.

ВЫБРАТЬ

Контрагенты.Ссылка КАК Контрагент,

ДопСведения.Значение КАК Регион

ИЗ

Справочник.Контрагенты КАК Контрагенты

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДопСведения

ПО Контрагенты.Ссылка = ДопСведения.Объект

И ДопСведения.Свойство = &СвойствоРегион

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

Проверка результата и типичные ошибки

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

Контрольные точки

Как проверить результат

Число строк результата
Норма

Совпадает с числом отобранных объектов

Тревожный признак

Строк больше — соединение без условия по свойству размножило записи

Объекты без заполненного реквизита
Норма

Присутствуют со значением NULL при левом соединении

Тревожный признак

Пропали — вероятно, использовано внутреннее соединение

Значение реквизита
Норма

Совпадает с данными карточки объекта

Тревожный признак

Пусто при заполненной карточке — свойство найдено неверно или это сведение, а не реквизит

Типичные ошибки
01
Соединение с табличной частью без условия по свойству — строки результата перемножаются, итоги завышаются
02
Поиск свойства по наименованию — запрос ломается после переименования реквизита пользователем
03
Использование внутреннего соединения там, где нужны объекты с пустым реквизитом — часть данных теряется
04
Путаница между реквизитами и сведениями — запрос к табличной части вместо регистра сведений возвращает пустоту
05
Сравнение поля «Значение» с параметром несовместимого типа — фильтр молча не срабатывает

Альтернатива: получение значения без запроса

Если нужно значение для одного объекта в коде, запрос не обязателен. В типовых конфигурациях на БСП есть программный интерфейс модуля «УправлениеСвойствами» (в старых версиях — «СвойстваПереопределяемый» и связанные модули), а также можно обратиться к табличной части напрямую через объект: Объект.ДополнительныеРеквизиты.Найти(Свойство, "Свойство") и прочитать поле «Значение» найденной строки.

Запрос оправдан при массовой выборке — в отчётах, обработках заполнения, динамических списках. Для единичного чтения в форме или при записи объекта работа через объект проще и не требует текста запроса.

Итог

Что важно запомнить

Дополнительный реквизит выбирается соединением с табличной частью «ДополнительныеРеквизиты» по ссылке и свойству, значение — в поле «Значение». Свойство передавайте параметром и ищите по имени, а не по наименованию. Дополнительные сведения хранятся в регистре сведений и требуют другого запроса.

Частые вопросы

Почему запрос возвращает NULL, хотя реквизит в карточке заполнен?

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

Как вывести дополнительный реквизит в отчёте на СКД без ручного соединения?

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

Можно ли отфильтровать динамический список по дополнительному реквизиту?

Да, но основную таблицу динамического списка придётся дополнить соединением с табличной частью «ДополнительныеРеквизиты» через произвольный текст запроса списка. Учтите, что произвольный запрос в динамическом списке может ограничить стандартные возможности, например динамическое обновление.

Чем дополнительный реквизит отличается от дополнительного сведения?

Реквизит хранится в табличной части самого объекта и виден в его форме как поле; сведение хранится в отдельном регистре сведений «ДополнительныеСведения» и привязано к объекту через измерение «Объект». В запросах реквизит берут соединением с табличной частью, сведение — соединением с регистром.

Как получить значение реквизита для одного объекта без запроса?

Через объект: откройте объект методом ПолучитьОбъект() или используйте данные формы, найдите строку в табличной части «ДополнительныеРеквизиты» методом Найти(Свойство, "Свойство") и прочитайте её поле «Значение». Если строки нет — реквизит у объекта не заполнен.

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

Поле «Значение» имеет составной тип, и сравнение выполняется с учётом типа. Если параметр передан как строка, а в базе хранится ссылка или число, условие не выполнится. Приведите параметр к тому же типу, что указан в настройках реквизита, и проверьте отсутствие лишних пробелов в строковых значениях.