Как в СКД получить нарастающий итог и значение предыдущей строки без падения сеанса?

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

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

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

Анализ проблемы: почему падает сеанс?

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


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

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

Решение №1: Использование правильных границ в функции ВычислитьВыражение

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

Рассмотрим синтаксис: ВычислитьВыражение(Выражение, Группировка, Область, Начало, Конец). Чтобы получить сумму от самой первой строки до той, что предшествует текущей, мы просто меняем параметр «Конец».

Правильный вариант написания:

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

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

Решение №2: Использование числовых смещений

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

  1. 0 — соответствует текущей строке.
  2. -1 — соответствует предыдущей строке.
  3. 1 — соответствует следующей строке.

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

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

Этот метод абсолютно идентичен использованию слова "Предыдущая", но позволяет более гибко управлять смещением, если вам, например, нужно получить данные через одну строку назад (индекс -2).

Решение №3: Математический метод (через разность)

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

Проанализируем формулу:


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

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

Обработка пустых значений (Первая строка)

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

Рассмотрим пример с обработкой:


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

Теперь, если данных нет (в первой строке), система вернет 0, и отчет будет выглядеть корректно.

Особенности работы в группировках

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

Разберем пример:

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

Если же вы хотите получить сквозной нарастающий итог по всему отчету, невзирая на границы группировок, в качестве второго параметра следует передать строку "ОбщийИтог":


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

Резюме

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

Для эффективного решения задачи рекомендуется:

Эти методы позволяют избежать критических ошибок платформы и строить сложные аналитические отчеты средствами СКД без написания лишнего кода на языке 1С.

← На главную