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