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

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

В современных конфигурациях 1С, построенных на базе Библиотеки стандартных подсистем (БСП), таких как УТ 11, ERP 2.5 или КА 2, механизм дополнительных реквизитов и сведений является крайне гибким. Однако при попытке вывести эти данные в отчет или программную выборку разработчики часто сталкиваются с проблемой: запрос возвращает только те реквизиты, которые уже заполнены у объекта. Если реквизит в системе заведен, но значение в карточке товара или партнера не указано, он просто исчезает из результата выборки.

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

Почему обычное соединение не работает?

Давайте проанализируем стандартную ошибку. Дополнительные реквизиты хранятся в табличной части справочника (например, Справочник.Партнеры.ДополнительныеРеквизиты). Если мы просто обратимся к этой таблице, система вернет только существующие записи. Если пользователь не заполнил реквизит "Цвет", записи в табличной части просто не будет.

Чтобы увидеть "пустые" строки, нам нужно сначала получить список всех теоретически возможных реквизитов для данного объекта, а затем "приклеить" к ним реальные значения там, где они есть. Для этого используется справочник НаборыДополнительныхРеквизитовИСведений.

Шаг 1: Получаем список доступных свойств для набора

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

Важный нюанс: условие на ПометкаУдаления крайне важно, чтобы не выводить "мусорные" или удаленные администратором поля.


ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
    НаборыДопРеквизитов.Свойство КАК Свойство,
    НаборыДопРеквизитов.НомерСтроки КАК ПорядокСвойства
ПОМЕСТИТЬ ВТ_СвойстваНабора
ИЗ
    Справочник.НаборыДополнительныхРеквизитовИСведений.ДополнительныеРеквизиты КАК НаборыДопРеквизитов
ГДЕ
    НаборыДопРеквизитов.Ссылка = &НаборСвойств
    И НЕ НаборыДопРеквизитов.ПометкаУдаления
;

Здесь параметр &НаборСвойств — это ссылка на элемент справочника НаборыДополнительныхРеквизитовИСведений, соответствующий вашему справочнику (например, "Справочник_Партнеры").

Шаг 2: Получаем заполненные значения конкретного объекта

Теперь выберем те данные, которые реально заполнены у нашего объекта (Партнера). Мы также поместим их во временную таблицу для удобства последующего соединения.


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

Шаг 3: Объединяем данные (Левое или Полное соединение)

Теперь самое главное — соединение. Мы должны использовать ЛЕВОЕ СОЕДИНЕНИЕ от таблицы ВТ_СвойстваНабора к таблице ВТ_ДанныеОбъекта. В этом случае все свойства из набора останутся в выборке, а там, где данных нет, мы получим NULL.

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


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

Разбор типичных ошибок при написании такого запроса

Разберем, почему у многих разработчиков этот запрос всё равно выдает только заполненные реквизиты. Основная причина — неправильное использование секции ГДЕ.

Ошибка "WHERE превращает LEFT JOIN в INNER JOIN":
Если вы напишете в конце запроса ГДЕ ДанныеОбъекта.Ссылка = &Партнер, то СУБД сначала выполнит соединение (получит NULL для пустых полей), а затем отфильтрует все строки, где Ссылка равна &Партнер. Поскольку в пустых строках ссылка будет NULL, условие NULL = &Партнер не выполнится, и пустые строки исчезнут.

Как правильно: фильтрацию по конкретному объекту нужно делать либо во вложенном запросе (как мы сделали в Шаге 2), либо непосредственно в условии связи ПО.

Альтернативный способ: Использование БСП

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

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


// Подготовим массив ссылок (можно для одного объекта)
Объекты = Новый Массив;
Объекты.Добавить(СсылкаНаПартнера);

// Получим таблицу значений
ТаблицаСвойств = УправлениеСвойствами.ПолучитьЗначенияДополнительныхРеквизитов(Объекты);

// В ТаблицаСвойств будут колонки: Свойство, Значение, ТекстоваяСтрока и др.

Этот способ предпочтительнее, так как БСП автоматически учитывает:

  1. Общие наборы (реквизиты, общие для всех партнеров).
  2. Индивидуальные наборы (реквизиты только для клиентов или только для поставщиков).
  3. Удаленные элементы и настройки видимости/доступности.

Итоги

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

← На главную