Как настроить расчет итогов по вычисляемому полю в СКД 1С, если сумма двоится

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

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

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

Причины некорректного расчета итогов в СКД

Проанализируем механику работы платформы 1С при обработке наборов данных и ресурсов:

  1. Дублирование строк в первичном наборе данных: Если в запросе набора данных используются левые соединения (ЛЕВОЕ СОЕДИНЕНИЕ) с соединенными таблицами "один ко многим", в результирующую выборку попадает больше физических строк, чем отображается при группировке в отчете. Вычисляемое поле рассчитывается для каждой исходной строки. Когда на вкладке «Ресурсы» указывается формула Сумма(ПробегТС), платформа суммирует значения по всем физическим строкам набора данных, из-за чего итоговая сумма умножается на количество дублей.
  2. Порядковая агрегация вычисляемых полей: Вычисление значений происходит на этапе формирования детальных записей. Если ресурс использует стандартное суммирование поверх вызовов экспортных функций, агрегация происходит по сырым не группированным данным.

Способ 1. Вызов функции общего модуля в выражении ресурса

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

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

МойОбщийМодуль.РассчитатьПробег(Сумма(НачальныйПробег), Сумма(КонечныйПробег))

Также в колонке «Рассчитывать по» можно гибко разграничить формулы расчета:

  1. Для детальных записей оставить прямое выражение или значение ресурса.
  2. Для уровней группировок и поля «Общий итог» указать вызов функции общего модуля с передачей агрегированных параметров Сумма() или Максимум().

Способ 2. Агрегация через массив сгруппированных значений

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

Перейдем на вкладку «Ресурсы» и в поле выражения для ресурса укажем одну из функций языка выражений СКД:


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

Или используем более простую конструкцию получения массива значений:

Сумма(ВычислитьВыражениеМассив("ПробегТС"))

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

Способ 3. Устранение дублирования на уровне запроса

Посмотрим на проблему с точки зрения оптимизации базы данных. Наличие дублирующих строк в наборе данных негативно влияет на производительность отчета. Для решения задачи на уровне запроса выполним следующие действия:

  1. Проанализируем связи таблиц в наборе данных запроса.
  2. Избавимся от размножения строк с помощью инструкций СГРУППИРОВАТЬ ПО или временных таблиц.
  3. Перенесем первичные расчеты показателей непосредственно в текст запроса, избегая лишних вызовов внешних функций кода 1С.

Отладка и особенности работы с внешними функциями в СКД

При вызове процедур и функций из внешних модулей учтем важные ограничения платформы 1С:

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