При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с жесткими требованиями к макету печатной формы. Одно из классических требований — отчет должен оставаться абсолютно плоским, то есть представлять собой линейную таблицу без древовидной структуры, раскрывающихся групп и визуальных сдвигов строк. При этом внутри строк такой таблицы необходимо выводить сложные расчетные данные, например, сумму ресурса в разрезе определенного аналитического разреза (например, «Должность» или «Подразделение») для каждой детальной записи.
Проанализируем ситуацию на конкретном примере. Представим отчет по штатному расписанию. В нем выводятся детальные записи сотрудников и вакансий. Нам необходимо рассчитать и вывести в каждой строке детальных записей общее количество незамещенных ставок по соответствующей должности. Если мы просто добавим группировку по должности, структура отчета станет иерархической. Изменение текста запроса также невозможно, так как он формируется динамически в общем модуле типовой конфигурации (например, 1С:ЗУП) и нам важно сохранить полную совместимость с обновлениями.
Выясним причину, почему стандартные средства СКД кажутся неподходящими на первый взгляд, и разберем по шагам три эффективных способа решения этой задачи: от стандартных виртуальных настроек компоновки до программных методов обхода ограничений.
Это самый элегантный, производительный и рекомендуемый методистами фирмы 1С способ. Он позволяет выполнить расчеты в контексте группировки, которая физически создается в структуре компоновки данных, но полностью скрывается при выводе пользователю. Таким образом, СКД рассчитывает итоги в памяти, а на экран выводится плоская таблица детальных записей.
Рассмотрим подробнее процесс настройки этого механизма:
Должность. Внутрь этой созданной группировки добавьте подчиненную группировку Детальные записи. На данном этапе структура выглядит как стандартное дерево.Должность. Перейдите на вкладку «Другие настройки» (в нижней части окна настроек СКД). Найдите системный параметр Расположение группировок и принудительно установите для него значение Нет.НеЗамещенныхВсегоВДолжности) в колонке «Выражение» укажите стандартную функцию вычисления выражений в контексте группировки:
ВычислитьВыражение("Сумма(НеЗамещенных)", "Должность")
При такой настройке СКД выполнит группировку данных по полю Должность в оперативной памяти, посчитает сумму ресурса НеЗамещенных для каждого значения должности, а затем подставит полученное значение в каждую строку подчиненных детальных записей. Благодаря параметру Расположение группировок = Нет, строки самой группировки «Должность» не будут выведены в печатную форму, и макет останется строго линейным.
Если поле Должность обязательно должно присутствовать в строках отчета в виде отдельной колонки, но вы категорически хотите избежать иерархических сдвигов и «плюсиков» сворачивания групп, можно настроить плоское отображение группировок.
Разберем по шагам этот вариант настройки:
Должность, а внутри нее — подчиненные Детальные записи.Расположение полей группировок и выберите для него значение Отдельно (в некоторых случаях отлично подойдет значение Отдельно и только в итогах).Расположение группировок оставьте значение Конец или Нет в зависимости от того, нужны ли вам итоговые строки по группировке. Если они не нужны — установите Нет.Посмотрим на пример работы данного механизма: СКД выведет значение должности в отдельной колонке для каждой строки детальных записей. При этом строка не будет дублироваться визуальными заголовками группировок, и таблица будет выглядеть как обычный плоский список, полученный простым запросом, но с корректно рассчитанными итогами в рамках каждой строки.
Если ваш отчет имеет настолько сложную структуру, что виртуальные группировки СКД начинают конфликтовать с другими объединениями или вычисляемыми полями, можно использовать альтернативный программно-настройки метод. Этот способ основан на передаче агрегированных данных во внешний или общий модуль конфигурации для последующего поиска.
Суть метода заключается в том, что мы используем функцию ВычислитьВыражениеСГруппировкойТаблицаЗначений для формирования временной таблицы итогов прямо внутри СКД, а затем с помощью вызова функции общего модуля получаем нужное значение по ключу связи.
Рассмотрим пример реализации вычисляемого поля:
НеЗамещенныхВсегоВДолжности.РабочийОтчетсПереопределяемый), передав туда таблицу значений и текущую должность:
РабочийОтчетсПереопределяемый.ПолучитьСуммуПоДолжности(
ВычислитьВыражениеСГруппировкойТаблицаЗначений("Сумма(НеЗамещенных)", "Должность"),
Должность
)
В общем модуле конфигурации (который обязательно должен иметь свойства «Сервер», «Вызов сервера» или «Внешнее соединение») необходимо разместить экспортируемую функцию поиска значения. Посмотрим на пример кода такой функции:
Функция ПолучитьСуммуПоДолжности(ТаблицаИтогов, ТекущаяДолжность) Экспорт
Если ТаблицаИтогов = Неопределено Или ТаблицаИтогов.Количество() = 0 Тогда
Возврат 0;
КонецЕсли;
СтрокаПоиска = ТаблицаИтогов.Найти(ТекущаяДолжность, "Должность");
Если СтрокаПоиска <> Неопределено Тогда
Возврат СтрокаПоиска.НеЗамещенных;
КонецЕсли;
Возврат 0;
КонецФункции
Хотя этот способ полностью решает задачу и оставляет структуру отчета абсолютно нетронутой (вам действительно понадобятся только «Детальные записи»), у него есть критические недостатки, которые необходимо учитывать при проектировании:
ВычислитьВыражениеСГруппировкойТаблицаЗначений генерирует таблицу значений при обработке каждой строки, что создает серьезную нагрузку на сервер приложений 1С.Для решения задачи суммирования ресурсов без визуального отображения группировок всегда в первую очередь используйте Способ 1 (Виртуальная группировка со скрытием). Это стандартное, быстрое и максимально производительное решение, заложенное в архитектуру Системы компоновки данных. Оно работает на уровне платформы без привлечения кода общего модуля и не снижает скорость формирования отчетов даже на больших базах данных.