При разработке отчетов в платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ситуацией, когда после изменения типа измерения регистра с конкретного справочника (например, Справочник.Контрагенты) на универсальный составной тип Справочник (неопределенного вида) встроенный объект Запрос перестает выводить иерархические итоги по группам. Запрос начинает возвращать данные так, как будто в секции группировки жестко указана опция Без Групп.
Проанализируем причины такого поведения платформы и разберем практические способы решения этой задачи.
Выясним причину, по которой платформа отключает иерархию:
PARENTEXT.Запрос рассчитан строго на типизированные объекты с однозначно известной структурой метаданных (например, Справочник.Номенклатура или Справочник.Контрагенты). Для составных типов группировка всегда принудительно функционирует в режиме без иерархии.Таким образом, получить встроенные итоги по группам стандартным текстом запроса при типе Справочник невозможно. Рассмотрим доступные пути обхода этого ограничения.
Наиболее распространенный и универсальный способ в штатной конфигурации — выгрузить плоский результат запроса в таблицу значений и программно рассчитать итоговые суммы по родительским группам, поднимаясь по цепочке родителей.
Разберем алгоритм по шагам:
ТаблицаЗначений с помощью метода Выгрузить().Родитель и накапливаем суммы на каждом уровне иерархии вплоть до корневого элемента.Посмотрим на пример кода обработки иерархии:
// Выполняем запрос
Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
ТабДанных = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТабДанных);
// Создаем таблицу для итогов по группам
ТабИтогов = СоздатьОбъект("ТаблицаЗначений");
ТабИтогов.НоваяКолонка("Объект");
ТабИтогов.НоваяКолонка("Уровень", "Число");
ТабИтогов.НоваяКолонка("Сумма", "Число", 15, 2);
// Обходим детальные записи и рассчитываем родителей
ТабДанных.ВыбратьСтроки();
Пока ТабДанных.ПолучитьСтроку() = 1 Цикл
ТекОбъект = ТабДанных.кли;
ТекСумма = ТабДанных.сппСумма;
// Поднимаемся вверх по иерархии
Родитель = ТекОбъект.Родитель;
Пока Родитель.Выбран() = 1 Цикл
// Накапливаем итоги по каждой найденной группе
ТабИтогов.НоваяСтрока();
ТабИтогов.Объект = Родитель;
ТабИтогов.Уровень = Родитель.Уровень();
ТабИтогов.Сумма = ТекСумма;
Родитель = Родитель.Родитель;
КонецЦикла;
КонецЦикла;
// Сворачиваем итоги по группам
ТабИтогов.Свернуть("Объект,Уровень", "Сумма");
КонецЕсли;
Если проект находится в стадии активной разработки, рекомендуется пересмотреть архитектуру хранения данных в регистрах:
Справочник.Контрагенты и Справочник.Склады), эффективнее завести два раздельных типизированных измерения в регистре. В этом случае стандартный механизм запросов 1С 7.7 сохранит возможность строить итоги по группам для каждого справочника.Для конфигураций, работающих под управлением Microsoft SQL Server с подключенными внешними компонентами прямого доступа к БД, задачу можно решить на уровне SQL:
LEFT JOIN с соответствующей таблицей SCxxx справочника.Этот подход обеспечивает максимальное быстродействие на больших массивах данных, исключая медленный обход объектов через OLE/COM в цикле 1С 7.7.