Разработка и Конфигурация · 12 мин
Как получить значение дополнительного реквизита в запросе 1С
Как получить значение дополнительного реквизита в запросе 1С: соединение с табличной частью ДополнительныеРеквизиты, параметры свойств, примеры кода и типичные ошибки.
Дополнительные реквизиты в типовых конфигурациях 1С хранятся не в основной таблице объекта, а в отдельной табличной части «ДополнительныеРеквизиты». Поэтому простое обращение к полю через точку в запросе не сработает — такого поля в таблице справочника или документа физически нет. Чтобы получить значение, нужно соединить основную таблицу с табличной частью по ссылке и отобрать строку по конкретному свойству.
Механизм одинаков для справочников (номенклатура, контрагенты) и документов: у объекта есть табличная часть «ДополнительныеРеквизиты» с полями «Свойство» (ссылка на план видов характеристик «ДополнительныеРеквизитыИСведения») и «Значение» (характеристика произвольного типа). Зная это, запрос строится по стандартному шаблону.
Ниже разобраны готовые варианты запросов: выборка значения одного реквизита, нескольких реквизитов одновременно, фильтрация по значению и получение значения через параметр свойства, чтобы не привязываться к имени в коде.
Где хранятся дополнительные реквизиты и почему нужен отдельный запрос
Дополнительные реквизиты — часть подсистемы «Свойства» Библиотеки стандартных подсистем (БСП). Когда пользователь добавляет реквизит через «Администрирование — Общие настройки — Дополнительные реквизиты и сведения», конфигурация не изменяется: новое поле не появляется в структуре таблицы. Вместо этого создаётся элемент плана видов характеристик «ДополнительныеРеквизитыИСведения», а введённые значения записываются в табличную часть объекта.
Из этого следуют два практических вывода. Первый: в запросе к таблице справочника или документа дополнительный реквизит недоступен как обычное поле. Второй: у одного объекта может быть несколько строк в табличной части — по одной на каждый заполненный реквизит, поэтому без отбора по свойству соединение размножит строки результата.
Базовый запрос: значение одного дополнительного реквизита
Типовой шаблон выглядит так: левое соединение таблицы объекта с табличной частью «ДополнительныеРеквизиты» по ссылке, с условием на конкретное свойство. Свойство удобнее всего передавать параметром.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
ДопРеквизиты.Значение КАК Цвет
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка
И ДопРеквизиты.Свойство = &СвойствоЦвет
Левое соединение важно: оно сохранит в выборке объекты, у которых реквизит не заполнен — для них поле «Значение» будет NULL. Если использовать внутреннее соединение, такие объекты выпадут из результата, что часто становится причиной «пропавших» строк в отчётах.
Параметр «СвойствоЦвет» — это ссылка на элемент плана видов характеристик «ДополнительныеРеквизитыИСведения». Получить её можно поиском по имени или через предопределённое имя, если оно задано.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура.Ссылка, ДопРеквизиты.Значение КАК Цвет ИЗ Справочник.Номенклатура КАК Номенклатура ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка И ДопРеквизиты.Свойство = &Свойство";
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Цвет");
Запрос.УстановитьПараметр("Свойство", Свойство);
Результат = Запрос.Выполнить().Выгрузить();Как получить ссылку на свойство для параметра запроса
Самый хрупкий способ — поиск по наименованию: НайтиПоНаименованию("Цвет"). Он сломается, если пользователь переименует реквизит или в базе появятся два свойства с одинаковым именем для разных наборов объектов. Использовать его допустимо в разовых обработках, но не в прикладном коде.
Надёжнее задать свойству имя в режиме предприятия (в карточке дополнительного реквизита есть поле «Имя» для использования в программах) и обращаться через метод, предоставляемый БСП, либо хранить ссылку в константе или параметре сеанса. В типовых конфигурациях часто применяют функционал управления свойствами, где имя реквизита формируется автоматически вида «Номенклатура_Цвет».
Выборка нескольких дополнительных реквизитов одним запросом
Если нужно вывести несколько реквизитов, есть два подхода. Первый — несколько левых соединений с одной и той же табличной частью, каждое со своим псевдонимом и своим условием по свойству. Запрос получается «плоским»: одна строка на объект, каждый реквизит в своей колонке.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
РеквизитЦвет.Значение КАК Цвет,
РеквизитВес.Значение КАК Вес
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК РеквизитЦвет
ПО Номенклатура.Ссылка = РеквизитЦвет.Ссылка
И РеквизитЦвет.Свойство = &СвойствоЦвет
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК РеквизитВес
ПО Номенклатура.Ссылка = РеквизитВес.Ссылка
И РеквизитВес.Свойство = &СвойствоВес
Второй подход — одно соединение с отбором по списку свойств и последующая группировка или свёртка в СКД. Он удобен, когда набор реквизитов динамический, но результат будет «вертикальным»: строки вида «объект — свойство — значение».
Сравнение вариантов
Подходит для фиксированного небольшого набора реквизитов. Результат — плоская таблица, удобная для отчёта. Минус: текст запроса нужно править при добавлении реквизита.
Подходит для динамического набора: свойства передаются списком в параметр. Минус: результат вертикальный, для плоской таблицы нужна свёртка в СКД или коде.
В отчётах на СКД дополнительные реквизиты можно подключать штатным механизмом характеристик без ручных соединений. Минус: требует настройки и понимания СКД.
Фильтрация объектов по значению дополнительного реквизита
Частая задача — отобрать не значение, а сами объекты, у которых реквизит равен нужному значению. Здесь условие на значение лучше выносить в секцию ГДЕ, а соединение делать внутренним, если незаполненные объекты не нужны.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура
ИЗ
Справочник.Номенклатура КАК Номенклатура
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка
ГДЕ
ДопРеквизиты.Свойство = &Свойство
И ДопРеквизиты.Значение = &Значение
Учтите тип поля «Значение»: это характеристика составного типа. Сравнение строки со строкой или ссылки со ссылкой работает напрямую, но сравнение с несовместимым типом (например, строковое значение с параметром-числом) вернёт пустой результат без ошибки. При сомнениях проверьте фактический тип значения в базе через консоль запросов.
Дополнительные сведения: отличие от реквизитов
Не путайте дополнительные реквизиты с дополнительными сведениями. Сведения хранятся не в табличной части объекта, а в регистре сведений «ДополнительныеСведения» с измерением «Объект» и «Свойство». Запрос к ним строится иначе — соединение с регистром по ссылке на объект.
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
ДопСведения.Значение КАК Регион
ИЗ
Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДопСведения
ПО Контрагенты.Ссылка = ДопСведения.Объект
И ДопСведения.Свойство = &СвойствоРегион
Признак того, что перед вами сведение, а не реквизит: в карточке объекта оно отображается на закладке «Дополнительно» в группе «Дополнительные сведения» и не видно в табличной части «Дополнительные реквизиты». При настройке в разделе дополнительных реквизитов и сведений эти два списка разделены.
Проверка результата и типичные ошибки
После написания запроса проверьте три вещи: количество строк (не должно размножаться при левом соединении с одним свойством), наличие объектов с незаполненным реквизитом (при левом соединении они должны присутствовать с NULL) и тип возвращаемого значения (должен совпадать с типом, заданным в настройках реквизита).
Как проверить результат
Совпадает с числом отобранных объектов
Строк больше — соединение без условия по свойству размножило записи
Присутствуют со значением NULL при левом соединении
Пропали — вероятно, использовано внутреннее соединение
Совпадает с данными карточки объекта
Пусто при заполненной карточке — свойство найдено неверно или это сведение, а не реквизит
Альтернатива: получение значения без запроса
Если нужно значение для одного объекта в коде, запрос не обязателен. В типовых конфигурациях на БСП есть программный интерфейс модуля «УправлениеСвойствами» (в старых версиях — «СвойстваПереопределяемый» и связанные модули), а также можно обратиться к табличной части напрямую через объект: Объект.ДополнительныеРеквизиты.Найти(Свойство, "Свойство") и прочитать поле «Значение» найденной строки.
Запрос оправдан при массовой выборке — в отчётах, обработках заполнения, динамических списках. Для единичного чтения в форме или при записи объекта работа через объект проще и не требует текста запроса.
Что важно запомнить
Дополнительный реквизит выбирается соединением с табличной частью «ДополнительныеРеквизиты» по ссылке и свойству, значение — в поле «Значение». Свойство передавайте параметром и ищите по имени, а не по наименованию. Дополнительные сведения хранятся в регистре сведений и требуют другого запроса.
Частые вопросы
Почему запрос возвращает NULL, хотя реквизит в карточке заполнен?
Чаще всего параметр свойства не совпадает с фактическим свойством строки: например, найдено свойство с похожим наименованием для другого набора объектов. Проверьте ссылку свойства в табличной части объекта через консоль запросов. Вторая причина — значение введено как дополнительное сведение, которое хранится в регистре сведений, а не в табличной части.
Как вывести дополнительный реквизит в отчёте на СКД без ручного соединения?
В схеме компоновки данных дополнительные реквизиты можно подключить через механизм характеристик: в настройках набора данных указывается тип объекта, а реквизиты становятся доступны как характеристики. В типовых отчётах многие дополнительные реквизиты уже подключены и доступны в настройках полей отчёта.
Можно ли отфильтровать динамический список по дополнительному реквизиту?
Да, но основную таблицу динамического списка придётся дополнить соединением с табличной частью «ДополнительныеРеквизиты» через произвольный текст запроса списка. Учтите, что произвольный запрос в динамическом списке может ограничить стандартные возможности, например динамическое обновление.
Чем дополнительный реквизит отличается от дополнительного сведения?
Реквизит хранится в табличной части самого объекта и виден в его форме как поле; сведение хранится в отдельном регистре сведений «ДополнительныеСведения» и привязано к объекту через измерение «Объект». В запросах реквизит берут соединением с табличной частью, сведение — соединением с регистром.
Как получить значение реквизита для одного объекта без запроса?
Через объект: откройте объект методом ПолучитьОбъект() или используйте данные формы, найдите строку в табличной части «ДополнительныеРеквизиты» методом Найти(Свойство, "Свойство") и прочитайте её поле «Значение». Если строки нет — реквизит у объекта не заполнен.
Почему фильтр по значению реквизита не срабатывает, хотя значение совпадает?
Поле «Значение» имеет составной тип, и сравнение выполняется с учётом типа. Если параметр передан как строка, а в базе хранится ссылка или число, условие не выполнится. Приведите параметр к тому же типу, что указан в настройках реквизита, и проверьте отсутствие лишних пробелов в строковых значениях.