В современных конфигурациях 1С, построенных на базе Библиотеки стандартных подсистем (БСП), таких как УТ 11, ERP 2.5 или КА 2, механизм дополнительных реквизитов и сведений является крайне гибким. Однако при попытке вывести эти данные в отчет или программную выборку разработчики часто сталкиваются с проблемой: запрос возвращает только те реквизиты, которые уже заполнены у объекта. Если реквизит в системе заведен, но значение в карточке товара или партнера не указано, он просто исчезает из результата выборки.
В этой статье мы подробно разберем, как построить запрос так, чтобы получить полный список всех назначенных объекту реквизитов, независимо от того, заполнены они или нет. Мы рассмотрим логику работы с планами видов характеристик, наборами свойств и табличными частями объектов.
Давайте проанализируем стандартную ошибку. Дополнительные реквизиты хранятся в табличной части справочника (например, Справочник.Партнеры.ДополнительныеРеквизиты). Если мы просто обратимся к этой таблице, система вернет только существующие записи. Если пользователь не заполнил реквизит "Цвет", записи в табличной части просто не будет.
Чтобы увидеть "пустые" строки, нам нужно сначала получить список всех теоретически возможных реквизитов для данного объекта, а затем "приклеить" к ним реальные значения там, где они есть. Для этого используется справочник НаборыДополнительныхРеквизитовИСведений.
Первым делом нам необходимо определить, какие именно реквизиты назначены нашему справочнику. Рассмотрим ситуацию на примере справочника Партнеры. Сначала создадим временную таблицу, куда поместим все свойства, входящие в нужный нам набор.
Важный нюанс: условие на ПометкаУдаления крайне важно, чтобы не выводить "мусорные" или удаленные администратором поля.
ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
НаборыДопРеквизитов.Свойство КАК Свойство,
НаборыДопРеквизитов.НомерСтроки КАК ПорядокСвойства
ПОМЕСТИТЬ ВТ_СвойстваНабора
ИЗ
Справочник.НаборыДополнительныхРеквизитовИСведений.ДополнительныеРеквизиты КАК НаборыДопРеквизитов
ГДЕ
НаборыДопРеквизитов.Ссылка = &НаборСвойств
И НЕ НаборыДопРеквизитов.ПометкаУдаления
;
Здесь параметр &НаборСвойств — это ссылка на элемент справочника НаборыДополнительныхРеквизитовИСведений, соответствующий вашему справочнику (например, "Справочник_Партнеры").
Теперь выберем те данные, которые реально заполнены у нашего объекта (Партнера). Мы также поместим их во временную таблицу для удобства последующего соединения.
ВЫБРАТЬ
ПартнерыДопРеквизиты.Свойство КАК Свойство,
ПартнерыДопРеквизиты.Значение КАК Значение,
ПартнерыДопРеквизиты.ТекстоваяСтрока КАК ТекстоваяСтрока
ПОМЕСТИТЬ ВТ_ДанныеОбъекта
ИЗ
Справочник.Партнеры.ДополнительныеРеквизиты КАК ПартнерыДопРеквизиты
ГДЕ
ПартнерыДопРеквизиты.Ссылка = &Партнер
;
Теперь самое главное — соединение. Мы должны использовать ЛЕВОЕ СОЕДИНЕНИЕ от таблицы ВТ_СвойстваНабора к таблице ВТ_ДанныеОбъекта. В этом случае все свойства из набора останутся в выборке, а там, где данных нет, мы получим NULL.
Рассмотрим итоговый текст запроса, который объединяет все шаги:
ВЫБРАТЬ
СвойстваНабора.Свойство КАК Свойство,
СвойстваНабора.Свойство.Наименование КАК НаименованиеСвойства,
ЕСТЬNULL(ДанныеОбъекта.Значение, ЗНАЧЕНИЕ(Справочник.ЗначенияСвойствОбъектов.ПустаяСсылка)) КАК Значение,
ДанныеОбъекта.ТекстоваяСтрока КАК ТекстоваяСтрока
ИЗ
ВТ_СвойстваНабора КАК СвойстваНабора
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДанныеОбъекта КАК ДанныеОбъекта
ПО СвойстваНабора.Свойство = ДанныеОбъекта.Свойство
УПОРЯДОЧИТЬ ПО
СвойстваНабора.ПорядокСвойства
Разберем, почему у многих разработчиков этот запрос всё равно выдает только заполненные реквизиты. Основная причина — неправильное использование секции ГДЕ.
Ошибка "WHERE превращает LEFT JOIN в INNER JOIN":
Если вы напишете в конце запроса ГДЕ ДанныеОбъекта.Ссылка = &Партнер, то СУБД сначала выполнит соединение (получит NULL для пустых полей), а затем отфильтрует все строки, где Ссылка равна &Партнер. Поскольку в пустых строках ссылка будет NULL, условие NULL = &Партнер не выполнится, и пустые строки исчезнут.
Как правильно: фильтрацию по конкретному объекту нужно делать либо во вложенном запросе (как мы сделали в Шаге 2), либо непосредственно в условии связи ПО.
Проанализируем ситуацию, когда нам не обязательно использовать чистый SQL-запрос. Если задача выполняется программно в модуле, гораздо надежнее и проще использовать встроенные функции Библиотеки стандартных подсистем. Это избавит вас от необходимости знать внутреннюю структуру хранения наборов.
Метод УправлениеСвойствами.ПолучитьЗначенияДополнительныхРеквизитов возвращает таблицу значений, которая уже содержит все необходимые поля. Пример использования:
// Подготовим массив ссылок (можно для одного объекта)
Объекты = Новый Массив;
Объекты.Добавить(СсылкаНаПартнера);
// Получим таблицу значений
ТаблицаСвойств = УправлениеСвойствами.ПолучитьЗначенияДополнительныхРеквизитов(Объекты);
// В ТаблицаСвойств будут колонки: Свойство, Значение, ТекстоваяСтрока и др.
Этот способ предпочтительнее, так как БСП автоматически учитывает:
Для получения всех дополнительных реквизитов через запрос необходимо:
ЛЕВОЕ СОЕДИНЕНИЕ.NULL-значения незаполненных реквизитов.УправлениеСвойствами), так как они учитывают сложную логику динамических наборов свойств.