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

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

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

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

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

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

Формула для ресурса:


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

Проанализируем параметры, которые мы использовали в этой функции:

  1. Первый параметр (Выражение): "Сумма(Цена)" — это то агрегатное значение, которое мы хотим получить из другой строки.
  2. Второй параметр (Группировка): Мы оставляем его пустым, чтобы расчет производился в контексте текущей группировки.
  3. Третий параметр (Область вычисления): Также оставляем пустым по умолчанию.
  4. Четвертый и пятый параметры (Начало и Конец): Мы указываем "Предыдущая" для обоих значений. Это критически важный момент — именно так мы сообщаем системе, что хотим взять значение ровно из одной предыдущей строки относительно текущей.

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

Способ 2: Программный расчет при ручном выводе макета

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

Разберем алгоритм на примере обработки ТаблицыЗначений. Основная идея заключается в использовании временной переменной-буфера, которая будет хранить значение текущей строки для использования в следующей итерации цикла.

Проанализируем пример кода:


// Инициализируем переменные перед началом цикла
ПеременнаяПредыдущегоЗначения = 0;
ИтоговаяРазность = 0;

Для Каждого СтрокаДанных Из ТзДанные Цикл
    
    // Если это не первая итерация, мы можем вычислить разницу
    Если ПеременнаяПредыдущегоЗначения <> 0 Тогда
        ТекущееОтклонение = СтрокаДанных.Сумма - ПеременнаяПредыдущегоЗначения;
    Иначе
        ТекущееОтклонение = 0; // Для первой строки разница обычно не считается
    КонецЕсли;
    
    // Заполняем параметры макета
    ОбластьСтрока.Параметры.Заполнить(СтрокаДанных);
    ОбластьСтрока.Параметры.Отклонение = ТекущееОтклонение;
    
    // Выводим строку в результирующий документ
    ДокументРезультат.Вывести(ОбластьСтрока);
    
    // Сохраняем текущее значение как "предыдущее" для следующего шага цикла
    ПеременнаяПредыдущегоЗначения = СтрокаДанных.Сумма;
    
КонецЦикла;

Выясним причину, почему этот метод надежен: он позволяет полностью контролировать условия расчета. Например, вы можете обнулять «предыдущее значение» при смене определенной группировки (например, при переходе к новому контрагенту), чего иногда сложно добиться в простом запросе.

Способ 3: Расчет накопительного итога (сальдо)

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

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


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

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

Рекомендации по оптимизации

При работе с вычислениями между строками следует учитывать несколько профессиональных советов:

  1. Сортировка данных: Любые вычисления, завязанные на «предыдущую» или «следующую» строку, критично зависят от порядка строк. Убедитесь, что в вашем запросе или настройках СКД жестко задана сортировка (например, по Дата или Период). Без этого результат будет непредсказуемым.
  2. Использование ресурсов: Старайтесь выполнять такие расчеты именно на уровне ресурсов СКД, а не в самом тексте запроса. Это позволит системе корректно пересчитывать итоги при различных настройках группировок пользователем.
  3. Производительность: Функция ВычислитьВыражение работает достаточно быстро, но на экстремально больших объемах данных (сотни тысяч строк) может вызывать замедление. В таких случаях стоит рассмотреть возможность предварительного расчета разниц во временных таблицах запроса с использованием АВТОНОМЕРЗАПИСИ() и соединения таблицы самой с собой по условию Т1.Номер = Т2.Номер + 1.

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

← На главную