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