При разработке отчетов на базе Системы компоновки данных (СКД) часто возникает задача не просто просуммировать данные, а вычислить разницу между итогами по разным операциям. Классический пример: получение итогового сальдо между документами Оприходование товаров и Списание товаров. В данной статье мы подробно разберем, как реализовать подобную логику, используя различные подходы — от модификации текста запроса до тонкой настройки ресурсов и вычисляемых полей.
Рассмотрим самый простой и быстрый способ, который часто используют разработчики. Его суть заключается в том, чтобы «инвертировать» значения для расходных операций еще на уровне получения данных из базы. Если мы приравняем оприходование к положительному числу, а списание — к отрицательному, то обычная сумма в итогах (агрегатная функция Сумма) автоматически выдаст нам искомую разницу.
Проанализируем пример запроса, в котором применяется эта логика:
ВЫБРАТЬ
ПартииТоваровНаСкладах.Период,
ПартииТоваровНаСкладах.Регистратор,
ПартииТоваровНаСкладах.Номенклатура,
ВЫБОР
КОГДА ПартииТоваровНаСкладах.Регистратор ССЫЛКА Документ.СписаниеТоваров
ТОГДА -ПартииТоваровНаСкладах.Количество
ИНАЧЕ ПартииТоваровНаСкладах.Количество
КОНЕЦ КАК Количество,
ВЫБОР
КОГДА ПартииТоваровНаСкладах.Регистратор ССЫЛКА Документ.СписаниеТоваров
ТОГДА -ПартииТоваровНаСкладах.Стоимость
ИНАЧЕ ПартииТоваровНаСкладах.Стоимость
КОНЕЦ КАК Стоимость
ИЗ
РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
ГДЕ
(Регистратор ССЫЛКА Документ.СписаниеТоваров
ИЛИ Регистратор ССЫЛКА Документ.ОприходованиеТоваров)
В данном коде мы используем конструкцию ВЫБОР КОГДА... ТОГДА. Для документа СписаниеТоваров мы ставим знак «минус» перед ресурсом. Теперь, когда СКД будет рассчитывать итоги, она фактически выполнит математическую операцию: (Сумма Оприходований) + (- Сумма Списаний), что и является разницей.
Важный нюанс: если после изменения запроса итоги не отображаются, обязательно проверьте закладку Ресурсы в схеме компоновки данных. Поля Количество и Стоимость должны быть добавлены в список ресурсов с выражением Сумма(Количество) и Сумма(Стоимость) соответственно. Без этого система воспримет их как обычные группировочные поля и не будет выводить общий итог.
Иногда изменение знака в запросе неудобно, так как пользователь хочет видеть в детальных записях положительные числа для обоих видов документов. В этом случае мы оставим запрос «чистым», а всю логику вычитания перенесем в настройки ресурсов СКД.
Рассмотрим, как прописать выражение для ресурса. Вместо стандартного Сумма(Количество) мы можем использовать более сложное выражение:
Сумма(Выбор Когда Регистратор ССЫЛКА Документ.ОприходованиеТоваров Тогда Количество Иначе -Количество Конец)
Этот подход позволяет гибко управлять расчетами. Например, если в отчет попадут другие типы документов, которые не должны влиять на итог, мы можем расширить условие:
Сумма(Выбор
Когда Регистратор ССЫЛКА Документ.ОприходованиеТоваров Тогда Количество
Когда Регистратор ССЫЛКА Документ.СписаниеТоваров Тогда -Количество
Иначе 0
Конец)
Преимущество этого метода в том, что в самих строках отчета (детальных записях) числа останутся положительными (если вы выберете поле Количество напрямую), а в иерархических группировках и общих итогах будет выводиться разница.
Для более наглядного анализа часто требуется вывести три колонки: «Приход», «Расход» и «Разница (Сальдо)». Это наиболее профессиональный подход в разработке управленческой отчетности. Разберем по шагам, как это сделать:
ВЫБОР КОГДА Регистратор ССЫЛКА Документ.ОприходованиеТоваров ТОГДА Количество ИНАЧЕ 0 КОНЕЦ КАК ПриходКол,
ВЫБОР КОГДА Регистратор ССЫЛКА Документ.СписаниеТоваров ТОГДА Количество ИНАЧЕ 0 КОНЕЦ КАК РасходКол
РазницаКол с выражением ПриходКол - РасходКол.Сумма(ПриходКол)Сумма(РасходКол)Сумма(ПриходКол) - Сумма(РасходКол) (для поля РазницаКол)Проанализируем ситуацию: использование функции ЕСТЬNULL. При работе с вычисляемыми полями и итогами, особенно если данные соединяются из разных источников, крайне важно оборачивать числовые значения: ЕСТЬNULL(ПриходКол, 0) - ЕСТЬNULL(РасходКол, 0). Это предотвратит появление пустых значений в итогах, если по одному из документов не было оборотов за период.
Если документов в системе много, использование конструкции ССЫЛКА для каждого типа может сделать запрос громоздким. В СКД можно использовать более элегантный способ проверки типа документа через ТИПЗНАЧЕНИЯ. Это особенно полезно в вычисляемых полях или выражениях ресурсов:
Выбор Когда ТипЗначения(Регистратор) = Тип("Документ.СписаниеТоваров") Тогда ...
Это позволяет избежать жесткой привязки к конкретным ссылкам и делает схему более универсальной.
Если вы применили формулу со сменой знака, но в итоге видите подозрительный «ноль» или пустую ячейку, проверим следующие моменты:
Подводя итог, можно сказать, что выбор метода зависит от требований к визуализации. Если нужно просто «склеить» итог — меняйте знак в запросе. Если нужно сохранить читаемость детальных записей — используйте выражения в ресурсах или вычисляемые поля. Сочетание этих инструментов позволит вам создать мощный и гибкий аналитический отчет.