Как корректно использовать функцию ВычислитьВыражение в СКД для табличных отчетов, когда ресурс не вычисляется?

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

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

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

ВычислитьВыражение("Сумма(КоличествоПДЗ)", "ЛицевойСчет",)

Здесь КоличествоПДЗ – это вычисляемое поле, которое принимает значение 0 или 1, указывая на наличие ПДЗ за период. Мы ожидаем, что функция просуммирует эти значения в контексте каждого ЛицевогоСчета. И действительно, при выводе отчета в виде простого списка, где данные сгруппированы сначала по ЛицевомуСчету, а затем по Периоду, функция работает идеально, выдавая корректные суммы.

Но что происходит, когда мы пытаемся вывести тот же результат в виде таблицы (кросс-таблицы)? Внезапно ресурс перестает вычисляться или выводит неверные значения. Это распространенная проблема, и её причина кроется в различиях контекста группировки между списочным и табличным отчетами.

Разбираемся с функцией ВычислитьВыражение и контекстом СКД

Для того чтобы понять, почему возникают такие расхождения, мы должны глубже рассмотреть, как работает функция ВычислитьВыражение в СКД и какие параметры влияют на её поведение. Функция принимает несколько ключевых параметров:

  1. Первый параметр: строка с вычисляемым выражением. Это само выражение, которое мы хотим агрегировать, например, "Сумма(КоличествоПДЗ)", "Максимум(Сумма)" или "Среднее(Цена)".
  2. Второй параметр: имя группировки. Этот параметр определяет, в контексте какой группировки должно быть вычислено выражение. Если мы оставляем его пустым (как в нашем первоначальном примере), выражение вычисляется в контексте текущей группировки, что в случае списочных отчетов обычно интуитивно понятно.
  3. Третий параметр: тип расчета. Этот параметр является критически важным и позволяет более точно указать контекст группировки. Мы можем использовать значения, такие как "Группировка", "ОбщийИтог", "Иерархия", "ГруппировкаНеРесурса". Выбор этого параметра напрямую влияет на то, как СКД будет агрегировать данные.
  4. Дополнительные параметры: "Начало" и "Конец". Эти параметры позволяют указать диапазон записей (например, "Первая", "Текущая", "Предыдущая") для расчета, что особенно полезно для построения нарастающих итогов или сравнения значений с предыдущими периодами. В нашем случае они не играют решающей роли, но важно знать об их существовании.

Различия в поведении между списочным и табличным отчетом

Давайте подробно проанализируем, как структура отчета влияет на контекст вычисления:

В списочном отчете

Когда мы формируем списочный отчет, данные выводятся построчно, с четко выраженной иерархией группировок. Например, если у нас есть группировки ЛицевойСчет и Период, то для каждой строки отчета легко определить её "текущую группировку". Если мы используем ВычислитьВыражение("Сумма(КоличествоПДЗ)", "",) или ВычислитьВыражение("Сумма(КоличествоПДЗ)", "ЛицевойСчет",), СКД понимает, что нужно просуммировать значения КоличествоПДЗ в рамках текущего ЛицевогоСчета или текущего Периода, в зависимости от контекста, в котором размещен ресурс.

В этом случае, если наш ресурс расположен в группировке ЛицевойСчет, он корректно агрегирует данные по всем подчиненным элементам этой группировки. Если ресурс находится в детальных записях, но ссылается на группировку, он также сможет вычислить значение относительно этой группировки.

В табличном отчете (кросс-таблице)

Ситуация значительно усложняется, когда мы переходим к табличному отчету. Кросс-таблица по своей природе отображает данные на пересечении различных измерений (группировок строк и группировок колонок). Каждая ячейка в таблице представляет собой пересечение этих измерений. Например, одна строка может соответствовать ЛицевомуСчету, а колонки — Периодам. Тогда каждая ячейка на пересечении ЛицевогоСчета и Периода должна отображать агрегированное значение по этому конкретному сочетанию.

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

Это и является причиной того, почему наш ресурс с ВычислитьВыражение("Сумма(КоличествоПДЗ)", "ЛицевойСчет",) не давал ожидаемого результата в таблице. СКД не могла правильно интерпретировать контекст ЛицевогоСчета на пересечении с Периодом в условиях кросс-таблицы.

Решение проблемы: используем параметр "ОбщийИтог"

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

Давайте посмотрим на предложенное решение, которое оказалось рабочим:

ВычислитьВыражение("Сумма(КоличествоПДЗ)","Период", "ОбщийИтог")

Разберем это выражение по частям и выясним, почему именно оно помогает решить проблему:

  1. "Сумма(КоличествоПДЗ)": Это наше вычисляемое выражение, которое мы хотим агрегировать. Здесь ничего не меняется, мы по-прежнему хотим получить сумму значений КоличествоПДЗ.
  2. "Период" (второй параметр – имя группировки): Мы явно указываем СКД, что агрегацию нужно производить в контексте группировки Период. В табличном отчете Период, вероятно, является одной из группировок колонок. Указание этого параметра помогает СКД понять, по какому измерению мы хотим собирать данные в каждой ячейке.
  3. "ОбщийИтог" (третий параметр – тип расчета): Это самый важный элемент решения. Параметр "ОбщийИтог" указывает СКД, что выражение должно быть рассчитано по всем записям, относящимся к текущему набору группировок ячейки, игнорируя более детальные записи или непосредственную группировку, которая могла бы быть использована по умолчанию. Фактически, "ОбщийИтог" заставляет СКД рассматривать более широкий контекст для агрегации, собирая данные по всем элементам, соответствующим пересечению текущей строки и колонки, а не только по одной "точке".

Таким образом, когда мы указываем ВычислитьВыражение("Сумма(КоличествоПДЗ)","Период", "ОбщийИтог"), мы говорим СКД: "Для каждой ячейки кросс-таблицы, которая является пересечением, например, определенного ЛицевогоСчета и определенного Периода, просуммируй все значения КоличествоПДЗ, относящиеся к этому Периоду, в рамках более широкого контекста общего итога для данного пересечения". Это позволяет функции корректно агрегировать данные для каждой ячейки кросс-таблицы, собирая значения КоличествоПДЗ по Периоду и при этом учитывая более общий контекст, необходимый для построения кросс-отчета.

Практические рекомендации при работе с ВычислитьВыражение в СКД

Чтобы избежать подобных проблем в будущем, мы можем следовать нескольким рекомендациям:

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

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

← На главную