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

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

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

Анализ проблемы и выбор метода решения

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

Проанализируем основные способы реализации этой задачи в СКД.

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

Это наиболее правильный и гибкий метод. Функция ВычислитьВыражение позволяет обращаться к значениям других группировок. Однако важно помнить: чтобы расчет корректно работал "по горизонтали" (между колонками), выражение должно быть прописано не в "Вычисляемых полях", а на вкладке Ресурсы.

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


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

Разберем параметры функции подробнее:

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

Важный нюанс: Если в какой-то из дней данных не было, СКД вернет NULL. В математических операциях Число - NULL = NULL, что приведет к пустой колонке. Чтобы этого избежать, всегда используйте проверку:


ЕстьNULL(ВычислитьВыражение("Сумма(Себестоимость)", "Дата", , "Последняя", "Последняя"), 0) 
- 
ЕстьNULL(ВычислитьВыражение("Сумма(Себестоимость)", "Дата", , "Первая", "Первая"), 0)

Способ 2. Условное суммирование через ОбщийИтог

Если по каким-то причинам стандартная навигация "Первая/Последняя" не подходит, можно воспользоваться сравнением дат. Мы можем сказать системе: "Возьми сумму только для той даты, которая является минимальной в этом отчете, и вычти её из суммы для максимальной даты".

Рассмотрим пример такого выражения в ресурсах:


Сумма(ВЫБОР 
    КОГДА Дата = ВычислитьВыражение("Минимум(Дата)", "ОбщийИтог") ТОГДА -Себестоимость 
    КОГДА Дата = ВычислитьВыражение("Максимум(Дата)", "ОбщийИтог") ТОГДА Себестоимость 
    ИНАЧЕ 0 
КОНЕЦ)

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

Настройка группировок для вывода "Разницы"

Часто пользователи жалуются: "Я добавил ресурс, но он выводится в каждой колонке с датой, и там везде одно и то же число!". Это происходит из-за того, что ресурс по умолчанию рассчитывается для всех группировок.

Посмотрим, как это исправить по шагам:

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

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

Как пропустить первую колонку, если в ней нулевое значение?

Проанализируем более сложную ситуацию: отчет строится за месяц, но товар поступил только 5-го числа. Нам нужно вычесть значение 5-го числа из 30-го, проигнорировав пустые дни в начале. Стандартное ключевое слово "Первая" вернет 0 (или NULL) за 1-е число.

Для решения этой задачи нам нужно сначала найти дату первого ненулевого значения. Мы можем вычислить её следующим выражением:


ВычислитьВыражение("Минимум(Выбор Когда Себестоимость > 0 Тогда Дата Конец)", "Номенклатура")

Однако передать эту дату напрямую в ВычислитьВыражение как параметр границы нельзя. В таких случаях программисты 1С обычно прибегают к одному из двух приемов:

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

Пример использования массива в ресурсе:


МойОбщийМодуль.РассчитатьРазницуПервыйПоследний(
    ВычислитьВыражениеСГруппировкойМассив("Сумма(Себестоимость)", "Дата")
)

Подведение итогов

Мы выяснили, что для корректного вычитания первой колонки из последней в СКД необходимо:

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

← На главную