Как рассчитать сложные итоги в СКД с помощью ВычислитьВыражениеСГруппировкойМассив и не запутаться в кавычках?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Разработчики отчетов в системе компоновки данных (СКД) часто сталкиваются с задачами, когда стандартных агрегатных функций (Сумма, Максимум, Среднее) на вкладке «Ресурсы» оказывается недостаточно. Типичный пример: на уровне детальных записей или месяцев нам нужно получить максимум показателя, на уровне номенклатуры — суммировать эти полученные максимумы, а в общем итоге — вывести максимум из всех рассчитанных сумм по номенклатуре.

В этой статье мы подробно разберем, как решать подобные задачи с помощью вложенных функций СКД ВычислитьВыражение и ВычислитьВыражениеСГруппировкойМассив, разберемся в логике работы этих «монструозных» выражений, а также изучим правила удвоения кавычек в языке выражений СКД, чтобы вы могли уверенно писать и читать такие формулы.

Постановка задачи на практическом примере

Представим, что мы разрабатываем отчет для анализа среднесуточных продаж. Период отчета разбит по месяцам. Нам необходимо решить следующую цепочку вычислений:

  1. В разрезе каждого месяца для каждой номенклатуры нужно определить максимальное количество дней работы (например, поле КоличествоДней).
  2. В итогах по номенклатуре нам нужно сложить эти максимальные значения по месяцам (то есть получить сумму максимумов).
  3. В общем итоге по отчету нам нужно отобразить максимальное значение среди итогов всех номенклатур, чтобы найти пиковый показатель по всей базе.

Если мы просто укажем в ресурсах формулу Сумма(КоличествоДней) или Максимум(КоличествоДней), СКД применит эту операцию ко всем исходным строкам без учета иерархии группировок, и результат окажется неверным. Нам нужен тонко настраиваемый расчет на каждом уровне группировки отчета.

Решение с помощью вложенных функций СКД

Для реализации такой сложной логики в СКД используется связка функций ВычислитьВыражениеСГруппировкойМассив и ВычислитьВыражение. Рассмотрим итоговое работающее выражение для ресурса:


ВычислитьВыражение(
    "Максимум(ВычислитьВыражениеСГруппировкойМассив(""Сумма(ВычислитьВыражениеСГруппировкойМассив(""""Максимум(КоличествоДней)"""", """"МесяцДокумента""""))"", ""Номенклатура""))",
    "Номенклатура",
    "ОбщийИтог"
)

Выглядит пугающе, не правда ли? Давайте разберем эту конструкцию «изнутри наружу» по шагам, чтобы понять, как именно СКД обрабатывает этот код.

Пошаговый разбор логики вычислений

Шаг 1. Расчет на самом нижнем уровне (Месяц)

Самое внутреннее выражение выполняет расчет для каждого месяца:

Максимум(КоличествоДней)

Здесь все просто — для конкретной номенклатуры в конкретном месяце берется максимальное значение показателя.

Шаг 2. Агрегирование помесячных данных по Номенклатуре

Поднимаемся на один уровень выше:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(КоличествоДней)", "МесяцДокумента"))

Функция ВычислитьВыражениеСГруппировкойМассив обходит все группировки МесяцДокумента внутри текущей номенклатуры, рассчитывает для каждого месяца Максимум(КоличествоДней) и возвращает массив этих значений. Функция Сумма складывает элементы полученного массива. Таким образом, для каждой номенклатуры мы получаем сумму месячных максимумов.

Шаг 3. Сбор данных по всем номенклатурам в массив

Двигаемся еще выше:

ВычислитьВыражениеСГруппировкойМассив("Сумма(...)", "Номенклатура")

Теперь мы собираем рассчитанные на Шаге 2 суммы по всем номенклатурам отчета в один общий массив. Каждый элемент этого массива — это готовый итог по конкретной номенклатуре.

Шаг 4. Нахождение максимума для Общего итога

И, наконец, внешняя оболочка выражения:

ВычислитьВыражение("Максимум(...)", "Номенклатура", "ОбщийИтог")

Мы берем массив итогов по всем номенклатурам (полученный на Шаге 3), находим из него максимальное значение с помощью функции Максимум и выводим этот результат в качестве ОбщегоИтога.

Тайное знание: Почему удваиваются кавычки?

Один из самых частых вопросов разработчиков при виде таких формул: «Зачем здесь столько кавычек по краям параметров — то по две, то по четыре штуки?». Выясним причину этого явления.

Дело в том, что функции ВычислитьВыражение и ВычислитьВыражениеСГруппировкойМассив в качестве своего первого параметра принимают строку, содержащую код выражения, которое нужно выполнить. Когда мы вкладываем одну такую функцию в другую, нам приходится передавать строку внутри строки. По правилам встроенного языка 1С, чтобы внутри строкового литерала написать символ кавычки, его необходимо удвоить.

Проанализируем геометрическую прогрессию кавычек при росте вложенности выражений:

Для наглядности схематично это можно представить следующим образом:

Функция("Уровень1_Начало ""Уровень2_Начало """"Уровень3_Значение"""" Уровень2_Конец"" Уровень1_Конец")

Альтернативный элегантный подход без «монструозных» формул

Хотя вложенные формулы отлично работают, их крайне тяжело читать, отлаживать и поддерживать — для этого подойдёт консоль СКД для отладки сложных выражений компоновки данных. Любая пропущенная кавычка или скобка приводит к синтаксической ошибке, которую трудно локализовать.

К счастью, в СКД есть встроенный механизм, позволяющий разделить расчет по разным уровням группировок без написания гигантских формул. Мы можем добавить одно и то же поле на вкладку «Ресурсы» несколько раз, но указать для каждого из них свое выражение и область расчета в колонке «Рассчитывать по...». При необходимости можно изучить практическое руководство по различным методам настройки расчета итогов для разных группировок в СКД.

Рассмотрим, как настроить этот подход по шагам:

  1. Строка ресурса 1 (для самого детального уровня — Месяц):
    • Поле: КоличествоДней
    • Выражение: Максимум(КоличествоДней)
    • Рассчитывать по: МесяцДокумента
  2. Строка ресурса 2 (для уровня Номенклатуры):
    • Поле: КоличествоДней
    • Выражение: Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(КоличествоДней)", "МесяцДокумента"))
    • Рассчитывать по: Номенклатура

    Обратите внимание: глубина вложенности уменьшилась, кавычек стало гораздо меньше и читать формулу стало намного проще!

  3. Строка ресурса 3 (для Общего итога):
    • Поле: КоличествоДней
    • Выражение: Максимум(ВычислитьВыражениеСГруппировкойМассив("Сумма(ВычислитьВыражениеСГруппировкойМассив(""Максимум(КоличествоДней)"", ""МесяцДокумента""))", "Номенклатура"))
    • Рассчитывать по: ОбщийИтог (или оставить колонку пустой, тогда формула применится ко всем уровням, для которых не заданы индивидуальные настройки).

При таком подходе СКД сама определяет, на каком уровне группировки отчета находится рассчитываемая ячейка, и применяет соответствующее простое выражение. Это значительно упрощает отладку отчета.

Важное предупреждение о производительности отчетов

Использование функций семейства ВычислитьВыражение и ВычислитьВыражениеСГруппировкойМассив накладывает определенные ограничения на скорость работы отчета. Проанализируем, почему это происходит:

Рекомендация: При работе с большими объемами данных старайтесь переносить подобные сложные перекрестные расчеты (максимумы по месяцам и их последующее суммирование) непосредственно в текст запроса СКД, используя временные таблицы и группировки SQL. В СКД в таком случае должны передаваться уже готовые предсчитанные показатели, которые останется лишь просто просуммировать стандартным образом.

← На главную