В практике разработки отчетов на базе Системы компоновки данных (СКД) часто возникает задача агрегации данных, при которой несколько документов (например, заказов или доставок) должны отображаться в одной строке, если у них совпадают ключевые реквизиты: контрагент, адрес, дата или ответственный сотрудник. При этом критически важно сохранить возможность «кликабельности» ссылок, чтобы пользователь мог открыть любой из объединенных документов прямо из отчета.
Рассмотрим детально, как реализовать такой функционал, проанализируем настройки ресурсов и разберем механизмы расшифровки, которые позволяют превратить список ссылок в удобный интерактивный инструмент.
Прежде всего, проанализируем запрос, который служит источником данных. В нашей ситуации используется объединение нескольких таблиц (Доставка, Забор, Транзит) через оператор ОБЪЕДИНИТЬ ВСЕ. Это правильный подход для сбора разнородных документов в единый поток данных. Однако стандартная группировка в самом тексте запроса (SQL-группировка) не позволит нам «склеить» ссылки в строку — она либо выберет одну (первую попавшуюся) ссылку, либо потребует перечисления всех ссылок в блоке СГРУППИРОВАТЬ ПО, что снова приведет к размножению строк.
Посмотрим на пример структуры запроса, который мы будем использовать в качестве фундамента для СКД:
ВЫБРАТЬ
Доставка.Ссылка КАК СсылкаДокумент,
Доставка.Клиент КАК Клиент,
Доставка.АдресДоставки КАК Адрес,
Доставка.ДатаВыдачи КАК ДатаИсполнения,
Доставка.Курьер КАК Сотрудник,
1 КАК Количество
ИЗ
Документ.Доставка КАК Доставка
ГДЕ
Доставка.Проведен = ИСТИНА
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Забор.Ссылка,
Забор.Клиент,
Забор.АдресДоставки,
Забор.ДатаВыдачи,
Забор.Курьер,
1
ИЗ
Документ.Забор КАК Забор
ГДЕ
Забор.Проведен = ИСТИНА
Главная хитрость заключается в том, что объединение строк мы будем делать не в запросе, а на уровне выражений ресурсов СКД.
Для того чтобы в итоговом отчете документы «схлопнулись» в одну ячейку, нам необходимо превратить поле СсылкаДокумент в ресурс. Начиная с версии платформы 8.3.6, в СКД доступна мощная функция СоединитьСтроки().
Разберем шаги по настройке вкладки Ресурсы:
СсылкаДокумент (или то поле, где хранится ссылка на документ).СоединитьСтроки(Массив(СсылкаДокумент), ", ", "Нет дублей")Количество используем стандартное выражение:
Сумма(Количество) или Количество(Различные СсылкаДокумент).Проанализируем, почему мы используем именно такую конструкцию в выражении ресурса. Функция Массив() собирает все значения ссылок, попавших в текущую группировку, в коллекцию. Затем функция СоединитьСтроки() берет этот массив, извлекает представления объектов (названия документов) и объединяет их через указанный разделитель (в нашем случае — запятая с пробелом). Параметр "Нет дублей" гарантирует, что если один и тот же документ по какой-то причине попал в выборку дважды, он не будет дублироваться в строке.
Чтобы документы объединялись только тогда, когда совпадают клиент, адрес и дата, нам нужно правильно настроить иерархию группировок на вкладке Настройки. Выясним причину, по которой группировка может «не работать»: если в детальные записи попадает хотя бы одно уникальное поле (например, уникальный номер документа или время), система не сможет схлопнуть строки.
Рассмотрим правильный порядок настройки группировок:
КлиентАдресДатаИсполненияСотрудникСсылкаДокумент.Количество.Важно помнить: мы не используем детальные записи (пустую группировку) под этой основной группировкой, иначе мы снова получим по одной строке на каждый документ.
Один из самых частых вопросов: «Если я соединю ссылки в строку, они станут просто текстом. Как мне открыть документ?». В СКД реализован встроенный механизм обработки массивов в ресурсах.
Когда вы используете СоединитьСтроки(Массив(Ссылка), ...), платформа 1С сохраняет в поле расшифровки не просто текст, а массив ссылок. При двойном клике на такую ячейку в сформированном отчете система автоматически предложит стандартное меню расшифровки. В этом меню пользователь увидит список всех документов, которые вошли в эту строку, и сможет выбрать нужный для открытия.
Если же требуется более специфичное поведение (например, открыть сразу все документы или выполнить расчет), мы можем воспользоваться событием ОбработкаРасшифровки в модуле формы отчета. Рассмотрим пример программной обработки:
Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка)
ПеременнаяДанные = ПолучитьИзВременногоХранилища(ДанныеРасшифровки);
Поля = ПеременнаяДанные.Элементы[Расшифровка].ПолучитьПоля();
ПолеДокумент = Поля.Найти("СсылкаДокумент");
Если ПолеДокумент <> Неопределено Тогда
Если ТипЗнч(ПолеДокумент.Значение) = Тип("Массив") Тогда
СтандартнаяОбработка = Ложь;
Для Каждого Док Из ПолеДокумент.Значение Цикл
ОткрытьЗначение(Док);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Если объединение через запятую кажется неудобным для чтения, мы можем применить другой визуальный прием — горизонтальное расположение документов. Рассмотрим, как это сделать:
В настройках СКД для конкретной группировки или всего отчета перейдем на вкладку Другие настройки. Найдем параметр Расположение группировок и установим значение В одной строке. Это заставит систему выводить вложенные данные не вниз, а вправо, при этом каждая ссылка останется отдельным объектом в своей микро-ячейке, что полностью исключает проблемы с расшифровкой.
Поскольку мы работаем с большим количеством документов через UNION ALL, проанализируем ситуацию с производительностью. Чтобы отчет работал быстро даже при больших объемах данных, придерживайтесь следующих правил:
ДатаВыдачи, Курьер), проиндексированы в конфигурации.ЕСТЬNULL(Доставка.Курьер, ЗНАЧЕНИЕ(...)) <> ЗНАЧЕНИЕ(...). Это может замедлять запрос. Лучше использовать прямое условие Доставка.Курьер <> ЗНАЧЕНИЕ(Справочник.Сотрудники.ПустаяСсылка), так как поле Курьер обычно является индексируемым.Строка(СсылкаДокумент.Номер) + " от " + Формат(СсылкаДокумент.Дата, "ДФ=dd.MM.yyyy"), а затем в ресурсах используйте СоединитьСтроки(Массив(ВашеВычисляемоеПоле), "; ").Подводя итог, мы видим, что решение задачи объединения данных в СКД сводится к переносу логики группировки из текста запроса в настройки ресурсов и компоновки. Использование функции СоединитьСтроки в сочетании с Массив() является наиболее современным и эффективным способом, обеспечивающим как компактность отчета, так и его интерактивность.