В отличие от справочников, у документов в платформе 1С отсутствует встроенная (стандартная) иерархия. Однако на практике очень часто возникает необходимость вывести документы в виде древовидной структуры. Типичный пример — цепочки документов, когда один документ создается на основании другого (например, первоначальный «Проект договора» и подчиненные ему дополнительные соглашения, у которых заполнен реквизит Основание).
Если попытаться решить эту задачу простым добавлением группировки по полю Основание, мы неизбежно столкнемся с серьезными проблемами: нарушится структура детальных записей, а числовые показатели (суммы) в ресурсах начнут двоиться или выводиться в некорректных колонках. В этой статье мы подробно разберем, как правильно реализовать собственную иерархию документов в системе компоновки данных (СКД), настроить связи наборов данных и обеспечить корректный расчет итоговых сумм.
Это самый элегантный и правильный способ создания иерархии для объектов, которые изначально ее не поддерживают. Метод заключается в том, что мы связываем единственный набор данных (наш запрос) сам с собой.
Рассмотрим по шагам процесс настройки этого механизма:
НаборДанных1). В запросе выберем ссылку на сам документ, реквизит его основания, а также все необходимые аналитические и числовые поля.
Посмотрим на пример такого запроса:
ВЫБРАТЬ
ПроектДоговора.Ссылка КАК Ссылка,
ПроектДоговора.Основание КАК ДокументОснование,
ПроектДоговора.Контрагент КАК Контрагент,
ПроектДоговора.Сумма КАК Сумма
ИЗ
Документ.ПроектДоговора КАК ПроектДоговора
НаборДанных1НаборДанных1СсылкаДокументОснованиеЗначение(Документ.ПроектДоговора.ПустаяСсылка) (это важнейшая настройка, указывающая СКД, что построение дерева нужно начинать с документов, у которых нет вышестоящего основания).Ссылка. В свойствах этой группировки (тип группировки) выберем значение «Иерархия». В выбранные поля добавим Ссылка, Контрагент и Сумма.
При такой настройке СКД автоматически построит дерево подчиненности. Документы, не имеющие основания, станут корневыми узлами, а документы-наследники расположатся на соответствующих подуровнях.
Часто разработчики пытаются обойтись без связей наборов данных, создавая искусственные группировки и вытягивая реквизиты документов «через точку». Это приводит к тому, что при добавлении поля Сумма в ресурсы итоги рассчитываются неверно, либо колонка суммы дублируется и отчет «разваливается».
Выясним причину этого поведения. Когда мы используем связь наборов данных для построения иерархии, СКД берет на себя управление агрегацией. Платформа понимает, что подчиненные записи физически присутствуют в результате запроса, и при подсчете итогов по группировкам применяет особый алгоритм расчета.
Чтобы ресурсы считались правильно, настроим их следующим образом:
Сумма в список ресурсов.Сумма(Сумма).Ссылка Иерархия. Это гарантирует, что сумма по родителю будет складываться из его собственной суммы и сумм подчиненных ему документов, при этом каждая исходная запись будет учтена в общих итогах ровно один раз.При построении собственной иерархии часто возникает визуальный дефект: документ-родитель сначала отображается как папка (узел дерева), а затем этот же самый документ дублируется внутри своей же ветки как подчиненный элемент (детальная запись).
Проанализируем ситуацию и применим один из способов решения этой проблемы:
Способ А: Наложение отбора на уровне группировки
В настройках структуры отчета выберем нашу иерархическую группировку Ссылка. Перейдем во вкладку «Отбор» этой группировки и добавим системное поле:
СистемныеПоля.УровеньВГруппеРавно1Этот отбор скроет дублирование элементов на более глубоких уровнях отображения детальных записей, оставив только чистую древовидную структуру.
Способ Б: Фильтрация через вычисляемое поле
Мы можем создать вычисляемое поле с использованием функции СКД ВычислитьВыражение:
ВычислитьВыражение("Ссылка", "", "Иерархия")
Затем в настройках отчета мы накладываем условие, отсекающее строки, у которых значение самого документа совпадает с вычисленным значением родителя на уровне детальных записей.
Если в базе данных содержатся сотни тысяч документов «Проект договора», построение динамической рекурсивной связи наборов данных в СКД может привести к просадке производительности. В таких случаях эффективнее подготовить иерархический индекс прямо в тексте запроса СУБД.
Для этого мы можем выполнить следующие шаги:
"000001/000005/000012"), которое будет содержать коды или уникальные идентификаторы всех родительских документов по цепочке.
СтрокаПовторить(" ", УровеньВложенности) + Представление(Ссылка)
Такой подход работает значительно быстрее на больших объемах данных, так как СУБД выполняет линейную сортировку по проиндексированному полю пути быстрее, чем СКД осуществляет рекурсивную сборку дерева на клиенте или сервере приложений.