Как правильно вычислить начальный и конечный остатки в СКД с помощью ВычислитьВыражение?

Программист Управленческий учет IT и автоматизация бизнеса
← На главную

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

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

Суть проблемы: неверный расчет итогов в группировках

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

Для начального остатка:

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

Для конечного остатка:

ВычислитьВыражение("Сумма(Количество)", , , "Первая", "Текущая")

Для детальных записей отчета такие выражения строят красивую колонку нарастающего итога. Однако при вычислении итогов по группировке Склад возникают искажения: сальдо первого склада становится входящим сальдо для второго склада, накапливаясь нарастающим итогом по всему отчету. Указание явных параметров группировки, таких как ВычислитьВыражение("Количество", "Склад", "Группировка", "Текущая"), возвращает только отдельные записи, но не дает правильного свертывания конечных итогов по всей иерархии.

Способ 1. Расчет остатков через условие в запросе и ресурсы СКД

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

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

  1. В запросе набора данных формируем выборку по полям Склад, Регистратор, Количество.
  2. Добавляем обработку даты начала периода отчета через условие в запросе:
    
    ВЫБРАТЬ
        ТвояТаблица.Склад КАК Склад,
        ТвояТаблица.Регистратор КАК Регистратор,
        ТвояТаблица.Период КАК Период,
        ВЫБОР
            КОГДА ТвояТаблица.Период < &ДатаНачала
                ТОГДА ТвояТаблица.Количество
            ИНАЧЕ 0
        КОНЕЦ КАК НачальныйОстатокКоличество,
        ВЫБОР
            КОГДА ТвояТаблица.Период >= &ДатаНачала
                ТОГДА ТвояТаблица.Количество
            ИНАЧЕ 0
        КОНЕЦ КАК ОборотКоличество
    ИЗ
        РегистрНакопления.Продажи КАК ТвояТаблица
    
  3. На вкладке Ресурсы задаем простые агрегатные функции для группировок:
    • Для СальдоНаНачалоКоличество указываем выражение: Сумма(НачальныйОстатокКоличество)
    • Для СальдоНаКонецКоровень вычисляем итоговый остаток как сумму входящего сальдо и всех оборотов: Сумма(НачальныйОстатокКоличество) + Сумма(ОборотКоличество)
  4. В настройках макета отчета скрываем детальные строки с периодом меньше даты начала, чтобы оставить в отчете только итоговые данные и актуальные движения за выбранный период.

Способ 2. Использование штатного механизма Ролей полей в СКД

Рассмотрим стандартный механизм платформы 1С, предназначенный для автоматического расчета остатков по произвольным группировкам. Если набору данных передаются поля периода и сальдо, можно настроить правила их свертки на вкладке Наборы данных в колонке Роль.

  1. Для поля начального остатка открываем настройки роли и устанавливаем тип НачальныйОстаток.
  2. Для поля конечного остатка выбираем тип КонечныйОстаток.
  3. В поле Имя дополнительного поля связываем остатки с соответствующим полем периода (например, ПериодSec).
  4. Указываем флаги заполнения остатков и оборотов.

При такой настройке платформа 1С автоматически корректно рассчитывает и сворачивает начальные и конечные остатки по любым произвольным группировкам отчета, включая реквизиты, не являющиеся измерениями регистра.

Способ 3. Явное задание сортировки в ВычислитьВыражение

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

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

ВычислитьВыражение("Сумма(Количество)", , "Период Возр", "Первая", "Текущая")

Для корректного подсчета итогов в родительских группировках по нарастающим итогам дочерних элементов применяется двухуровневое агрегирование с помощью функции ВычислитьВыражениеСГруппировкойМассив:

Сумма(ВычислитьВыражениеСГруппировкойМассив("ВычислитьВыражение('Сумма(Количество)', , , 'Первая', 'Текущая')", "Регистратор"))

Ограничения и особенности работы функции ВычислитьВыражение

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

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

← На главную