Как в СКД вычислить разницу между колонками таблицы без изменения запроса?

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

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

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

Метод 1: Использование фиктивного поля в запросе

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

Рассмотрим по шагам реализацию этого подхода:

  1. Подготовка запроса: В тексте запроса или в наборе данных — объекте добавим дополнительное поле с нулевым значением. Назовем его, например, Разница.
    
    ВЫБРАТЬ
        Данные.Новичок КАК Новичок,
        Данные.Показатель КАК Значение,
        0 КАК Разница
    ИЗ
        ВТ_Данные КАК Данные
    
  2. Настройка ресурсов: Перейдем на закладку "Ресурсы" в СКД. Для поля Разница в поле "Выражение" укажем формулу, которая будет обращаться к значениям других колонок. Если мы знаем, что колонки формируются по определенному измерению, мы можем использовать функции агрегации с условием или обратиться к конкретным значениям.
  3. Особенности вычисления: Однако, если колонки динамические (например, фамилии "Навальный" и "Скрипаль"), простое вычитание в ресурсах может не сработать напрямую. В этом случае мы используем следующий лайфхак: добавляем поле Разница в выбранные поля горизонтальной группировки.

Метод 2: Мощные возможности функции ВычислитьВыражение

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

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

Для работы с горизонтальными группировками (колонками) крайне важны параметры "Начало" и "Конец". Рассмотрим ситуацию, когда нам нужно в текущей колонке получить значение из предыдущей и вычислить разницу:

ВычислитьВыражение("Сумма(СуммаОборот)", , , "Предыдущая", "Предыдущая")

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

Чтобы вычислить разницу между "сейчас" и "было", выражение в ресурсе будет выглядеть так:


Сумма(СуммаОборот) - ВычислитьВыражение("Сумма(СуммаОборот)", , , "Предыдущая", "Предыдущая")

Метод 3: Работа с массивами через ВычислитьВыражениеСГруппировкойМассив

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

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


Максимум(ВычислитьВыражениеСГруппировкойМассив("Сумма(Продажи)", "ИмяВашейГоризонтальнойГруппировки"))

Затем это значение можно использовать в знаменателе для расчета доли каждой колонки в максимальном значении или для вычисления отклонения от среднего по горизонтали.

Важные технические нюансы при расчетах по горизонтали

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

1. Обработка пустых значений (NULL)

В горизонтальных таблицах очень часто бывает так, что в одной колонке данные есть, а в другой — нет. В 1С операция 10 - NULL даст в результате NULL (пусто). Поэтому всегда оборачивайте ваши выражения в функцию ЕстьNull.

ЕстьNull(Сумма(Показатель), 0) - ЕстьNull(ВычислитьВыражение(...), 0)

2. Настройка "Рассчитывать по..."

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

3. Использование контекста "Группировка"

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

Практический пример: План-фактный анализ

Представим, что у нас есть измерение ТипДанных со значениями "План" и "Факт". Мы хотим вывести их в колонки и получить третью — "Отклонение".

Разберем алгоритм:

  1. Создаем вычисляемое поле Отклонение.
  2. В ресурсах для этого поля пишем выражение:
    
    Сумма(Выбор Когда ТипДанных = &Факт Тогда Значение Иначе 0 Конец) 
    - 
    Сумма(Выбор Когда ТипДанных = &План Тогда Значение Иначе 0 Конец)
    
  3. В настройках отчета добавляем ТипДанных в колонки таблицы.
  4. Добавляем в выбранные поля группировки наши ресурсы.

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

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

← На главную