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

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

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

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

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

  1. Свойство — ссылка на план видов характеристик ДополнительныеРеквизитыИСведения.
  2. Значение — само значение реквизита, которое имеет составной тип данных.

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

Метод 1: Использование Левого Соединения в запросе

Это классический и самый гибкий способ получения данных. Мы используем ЛЕВОЕ СОЕДИНЕНИЕ, чтобы основная выборка (например, список договоров) не уменьшилась, если у какого-то договора реквизит не заполнен. Рассмотрим пример запроса, где мы выбираем договоры с видом «Прочее» и получаем значение доп. реквизита «Подразделение».


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

Обратите внимание на важный нюанс: условие по свойству ДопРеквизиты.Свойство = &Свойство должно находиться именно в блоке ПО (в условии соединения), а не в блоке ГДЕ. Если вы вынесете его в ГДЕ, левое соединение превратится во внутреннее, и вы потеряете из выборки все договоры, у которых этот реквизит не задан.

Метод 2: Обращение через внутреннее имя (Имя для разработчиков)

Часто в коде неудобно или невозможно передавать ссылку на свойство через параметр. В этом случае мы можем использовать «Имя для разработчиков», которое задается в настройках дополнительного реквизита. Это имя уникально и позволяет обращаться к свойству более надежно.

Выясним причину, почему это лучше: поиск по текстовому заголовку («Подразделение») опасен, так как пользователь может переименовать реквизит в интерфейсе. А внутреннее имя, например Подразделение_82f1..., обычно остается неизменным.


ВЫБРАТЬ
    Договоры.Ссылка КАК Ссылка,
    ЕСТЬNULL(ДопРеквизиты.Значение, ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)) КАК Подразделение
ИЗ
    Справочник.ДоговорыКонтрагентов КАК Договоры
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов.ДополнительныеРеквизиты КАК ДопРеквизиты
    ПО Договоры.Ссылка = ДопРеквизиты.Ссылка
    И (ДопРеквизиты.Свойство.Имя = "Подразделение_ВашУникальныйИдентификатор")

Применение оператора ВЫРАЗИТЬ для оптимизации

Поле Значение в таблице доп. реквизитов имеет составной тип. Если вы планируете в запросе обращаться к полям этого значения (например, получить код подразделения или его наименование), система может работать медленно, выполняя множество неявных соединений со всеми возможными таблицами. Чтобы этого избежать, используем ВЫРАЗИТЬ. Автоматически обнаружить неявные разыменования полей составного типа в запросах поможет обработка для проверки запросов на разыменование полей составного типа.

Рассмотрим подробнее пример с приведением типа:


ВЫБРАТЬ
    Договоры.Ссылка КАК Ссылка,
    ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК Справочник.ПодразделенияОрганизаций) КАК ПодразделениеОбъект
ИЗ
    Справочник.ДоговорыКонтрагентов КАК Договоры
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов.ДополнительныеРеквизиты КАК ДопРеквизиты
    ПО Договоры.Ссылка = ДопРеквизиты.Ссылка
    И (ДопРеквизиты.Свойство = &Свойство)

Важно: если тип в ВЫРАЗИТЬ не совпадет с фактическим типом значения, система вернет NULL. Поэтому всегда точно указывайте целевой справочник.

Программное получение значений через функции БСП

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

Разберем по шагам, как это сделать:

  1. Если вам нужно одно значение для одного объекта:

ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаДоговор, "ИмяВашегоРеквизита");
  1. Если вам нужно получить значения для целого списка объектов (например, для таблицы значений или массива ссылок), используйте более эффективный метод:

// МассивСсылок - массив договоров, для которых нужны данные
ТаблицаЗначенийСвойств = УправлениеСвойствами.ЗначенияСвойствОбъектов(МассивСсылок);
// На выходе получаем ТЗ со всеми доп. реквизитами этих объектов

Отличия дополнительных реквизитов от дополнительных сведений

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

Дополнительные реквизиты хранятся в самом объекте (в ТЧ ДополнительныеРеквизиты). Они видны прямо в карточке объекта. Дополнительные сведения хранятся в отдельном регистре сведений ДополнительныеСведения. Они обычно открываются по отдельной кнопке на панели.

Если ваше «Подразделение» — это сведение, запрос изменится:


ВЫБРАТЬ
    Сведения.Значение КАК Подразделение
ИЗ
    РегистрСведений.ДополнительныеСведения КАК Сведения
ГДЕ
    Сведения.Объект = &СсылкаНаДоговор
    И Сведения.Свойство = &Свойство

Рекомендации по производительности

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

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


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

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

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

Для Каждого Строка Из Результат Цикл
    Если ЗначениеЗаполнено(Строка.Подразделение) Тогда
        // Здесь можно подставлять значение в документ
        Сообщить("Для договора " + Строка.Договор + " найдено подразделение: " + Строка.Подразделение);
    КонецЕсли;
КонецЦикла;

Таким образом, мы рассмотрели все основные способы извлечения данных из дополнительных свойств 1С. Помните о разнице между реквизитами и сведениями, используйте ЛЕВОЕ СОЕДИНЕНИЕ и не забывайте про оптимизацию через ВЫРАЗИТЬ.

← На главную