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