Как в СКД рассчитать ресурс по данным другой группировки?

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

При разработке отчетов на системе компоновки данных (СКД) в 1С часто возникает задача, когда показатели в отчете выводятся в виде строк (вертикальная структура), и один из этих показателей должен рассчитываться на основе значений других показателей. Например, у нас есть три показателя: п1, п2 и п3. Значения п1 и п2 берутся напрямую из базы данных, а п3 должен рассчитываться как п1 / п2 для каждого конкретного подразделения.

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

Выясняем причину: почему стандартные формулы не работают

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

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

Рассмотрим по шагам решения, которые позволяют обойти это ограничение.

Решение 1. Использование функции ВычислитьВыражение с отбором

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

Перейдем на вкладку Ресурсы в схеме компоновки данных. Для поля Значение напишем следующую формулу ресурса:


Выбор 
    Когда Показатель = "п3" Тогда 
        ВычислитьВыражение("Сумма(Значение)", "Подразделение", , "Первая", "Последняя", "Показатель = ""п1""") / 
        Выбор 
            Когда ВычислитьВыражение("Сумма(Значение)", "Подразделение", , "Первая", "Последняя", "Показатель = ""п2""") = 0 Тогда 1 
            Иначе ВычислитьВыражение("Сумма(Значение)", "Подразделение", , "Первая", "Последняя", "Показатель = ""п2""") 
        Конец
    Иначе Сумма(Значение) 
Конец

Разберем подробнее, как работает эта конструкция:

  1. Первый параметр функции "Сумма(Значение)" указывает, какое именно выражение мы хотим рассчитать.
  2. Второй параметр "Подразделение" задает группировку, в рамках которой производится расчет. Это гарантирует, что мы не смешаем данные разных подразделений.
  3. Параметры "Первая" и "Последняя" определяют границы поиска записей внутри этой группировки.
  4. Шестой параметр "Показатель = ""п1""" выполняет отбор. Система находит строки текущего подразделения, где показатель равен п1, и суммирует их значения, игнорируя то, что текущая строка отчета строится для п3.
  5. Вторая часть формулы выполняет аналогичный расчет для п2 с проверкой на деление на ноль, чтобы избежать критических ошибок при выводе отчета.

Решение 2. Транспонирование таблицы (Метод разворота в запросе)

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

Проанализируем, как должен выглядеть запрос. Нам нужно преобразовать строки в колонки, чтобы каждая запись содержала все показатели одновременно:


ВЫБРАТЬ
    ИсходныеДанные.Подразделение КАК Подразделение,
    ВЫРАЗИТЬ(ВЫБОР КОГДА ИсходныеДанные.Показатель = "п1" ТОГДА ИсходныеДанные.Значение ИНАЧЕ 0 КОНЕЦ КАК ЧИСЛО(15,2)) КАК Значение_п1,
    ВЫРАЗИТЬ(ВЫБОР КОГДА ИсходныеДанные.Показатель = "п2" ТОГДА ИсходныеДанные.Значение ИНАЧЕ 0 КОНЕЦ КАК ЧИСЛО(15,2)) КАК Значение_п2
ПОМЕСТИТЬ ВТ_Свернутая
ИЗ
    &ТаблицаИсточника КАК ИсходныеДанные
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Свернутая.Подразделение КАК Подразделение,
    СУММА(ВТ_Свернутая.Значение_п1) КАК Значение_п1,
    СУММА(ВТ_Свернутая.Значение_п2) КАК Значение_п2
ИЗ
    ВТ_Свернутая КАК ВТ_Свернутая
ГРУППИРОВАТЬ ПО
    ВТ_Свернутая.Подразделение

После получения такой таблицы в СКД мы можем пойти двумя путями:

Решение 3. Использование общего модуля для сложных расчетов

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

Создадим в конфигураторе неглобальный общий модуль (например, ОтчетыСервер) и напишем в нем функцию:


Функция РассчитатьПоказательЭффективности(Значение1, Значение2) Экспорт
    
    Если Значение2 = 0 Тогда
        Возврат 0;
    КонецЕсли;
    
    // Здесь может быть любая сложная математическая логика
    Результат = Значение1 / Значение2;
    
    Возврат Окр(Результат, 2);
    
КонецФункции

Теперь в схеме компоновки данных на вкладке Ресурсы мы можем вызвать эту функцию напрямую, передав в нее результаты вычислений функции ВычислитьВыражение:


Выбор 
    Когда Показатель = "п3" Тогда 
        ОтчетыСервер.РассчитатьПоказательЭффективности(
            ВычислитьВыражение("Сумма(Значение)", "Подразделение", , "Первая", "Последняя", "Показатель = ""п1"""),
            ВычислитьВыражение("Сумма(Значение)", "Подразделение", , "Первая", "Последняя", "Показатель = ""п2""")
        )
    Иначе Сумма(Значение) 
Конец

Этот подход значительно упрощает отладку кода и позволяет использовать все возможности встроенного языка 1С для вычисления сложных бизнес-показателей в отчетах.

← На главную