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