При работе с системой компоновки данных (СКД) в 1С, особенно когда используется Пользовательская СКД для расширения возможностей отчетов на стороне клиента, часто возникает задача вывести в отчете не просто абсолютные значения, но и относительные, например, долю конкретной строки в общем итоге (для удобной визуализации таких данных есть панель инструментов для создания интерфейсов на основе СКД). Классический пример — показать, какой процент от общей суммы продаж составляет продажа по конкретной номенклатуре. Сложность заключается в том, что на момент вывода детальной записи (строки отчета) общий итог по всему отчету еще не рассчитан. Из-за этого простое деление значения в строке на итоговую сумму невозможно. Разберемся, как обойти это ограничение с помощью встроенных механизмов СКД.
Давайте проанализируем ситуацию. СКД обрабатывает данные последовательно. Сначала выполняется запрос, который получает плоский набор данных. Для быстрой отладки таких запросов и проверки данных на лету часто применяется Консоль запросов УФ с поддержкой СКД и временных таблиц — для этого подойдёт набор инструментов для отладки запросов и СКД. Затем система обрабатывает этот набор, группирует записи и вычисляет итоги. Когда формируется строка для конкретной номенклатуры, СКД "знает" только данные этой строки. Общий итог по колонке "Сумма" будет известен только после того, как все строки будут обработаны.
Если в вычисляемом поле мы напишем выражение вроде Сумма / Сумма(Сумма), это не сработает, так как функция Сумма() в этом контексте будет относиться только к текущей записи, а не ко всему набору данных. Нам нужен инструмент, который может "заглянуть вперед" и получить итоговое значение, которое будет рассчитано позже.
Для решения подобных задач в языке выражений СКД существует специальная функция — Вычислить(). Она позволяет получить значение выражения, рассчитанное для определенной группировки отчета, например, для родительской группы или для общего итога. Это именно то, что нам нужно. При разработке сложных выражений и схем полезно иметь под рукой такие инструменты, как Консоль запросов для управляемых форм, которая позволяет детально разбирать структуру запроса и схемы.
Синтаксис функции:
Вычислить(Выражение, Группировка, ТипРасчета)
Рассмотрим ее параметры подробнее:
Выражение — это строка, содержащая вычисляемое выражение. Как правило, здесь используются агрегатные функции, такие как Сумма(), Количество(), Среднее() и т.д. Например, "Сумма(Выручка)".Группировка — строка с именем группировки, для которой нужно рассчитать выражение. Это может быть имя конкретной группировки из настроек отчета (например, "Контрагент") или одно из системных значений. Для нашей задачи ключевое значение — "ОбщийИтог". Оно указывает, что нужно взять итог по всему отчету.ТипРасчета — необязательный параметр, который уточняет, как рассчитывать итоги относительно указанной группировки. В большинстве случаев при использовании "ОбщийИтог" его можно опустить.Разберем по шагам, как применить эту функцию на практике для расчета доли каждой строки в общей сумме.
Переходим к настройке СКД. Откройте схему компоновки данных вашего отчета. Нам нужна вкладка "Вычисляемые поля".
Создаем новое поле. Нажмите "Добавить" и создайте новое вычисляемое поле. Зададим ему путь данных (имя), например, ПроцентОтИтога, и заголовок, который увидит пользователь, — "Процент от итога". В ситуациях, когда стандартных настроек недостаточно, может потребоваться программное изменение заголовка группировки отчета, но для нашей задачи хватит штатных средств.
Пишем выражение для расчета. В поле "Выражение" необходимо написать формулу, которая будет использовать нашу сумму по строке и общий итог, полученный с помощью функции Вычислить(). Важно также предусмотреть защиту от деления на ноль: если общий итог равен нулю, то и процент должен быть равен нулю.
Для этого идеально подходит конструкция Выбор ... КонецВыбора.
Выбор
Когда Вычислить("Сумма(Сумма)", "ОбщийИтог") > 0
Тогда Сумма / Вычислить("Сумма(Сумма)", "ОбщийИтог") * 100
Иначе 0
КонецВыбора
Давайте детально разберем этот код:
Выбор Когда ... — это аналог оператора If...Then...Else. Мы проверяем условие.Вычислить("Сумма(Сумма)", "ОбщийИтог") > 0 — это наше условие. Здесь мы получаем общий итог по полю "Сумма" для всего отчета и проверяем, больше ли он нуля. Это и есть защита от ошибки деления на ноль.Тогда Сумма / Вычислить("Сумма(Сумма)", "ОбщийИтог") * 100 — эта часть выполняется, если условие истинно. Мы берем значение поля Сумма для текущей детальной записи и делим его на общий итог, который мы получили с помощью Вычислить(). Умножаем на 100 для получения процентного значения.Иначе 0 — если общий итог равен нулю, то результатом выражения будет 0.КонецВыбора — завершение конструкции.После создания этого поля его необходимо добавить в "Выбранные поля" на вкладке "Настройки", чтобы оно появилось в отчете. Также не забудьте настроить для него формат, чтобы значение отображалось с нужным количеством знаков после запятой и символом "%".
Функцию Вычислить() можно использовать не только в вычисляемых полях, но и непосредственно при настройке ресурсов. Этот способ полезен, если вы проводите оптимизацию отчетов с набором данных - объект или используете сложные схемы компоновки, где процент должен корректно рассчитываться на разных уровнях итогов.
Порядок действий:
Перейдите на вкладка "Ресурсы" в схеме компоновки данных.
Добавьте новый ресурс. Назовем его, например, ДоляВПродажах.
В поле "Выражение" укажите формулу. Формула будет очень похожа, но с одним отличием: так как мы находимся в контексте ресурса, нам нужно использовать агрегатную функцию для значения текущей группировки.
Выбор
Когда Вычислить(Сумма(Сумма), "ОбщийИтог") > 0
Тогда Сумма(Сумма) * 100 / Вычислить(Сумма(Сумма), "ОбщийИтог")
Иначе 0
КонецВыбора
Обратите внимание, что здесь мы используем Сумма(Сумма) как для числителя, так и внутри функции Вычислить(). Это позволяет корректно рассчитывать долю не только для детальных записей, но и для промежуточных итогов (например, долю продаж по группе номенклатуры в общем объеме).
Сравнение подходов:
Функция Вычислить() еще более универсальна. Вместо `"ОбщийИтог"` вы можете указать имя конкретной группировки. Это позволяет рассчитывать процент не от общего итога, а от итога по родительской группе. В некоторых архитектурных решениях для этого могут даже использоваться две разных схемы в отчете СКД, чтобы разделить логику подготовки данных и их визуализации.
Предположим, у вас есть отчет с группировками "Контрагент" -> "Номенклатура". И вы хотите для каждой номенклатуры посчитать ее долю в продажах по текущему контрагенту — для автоматизации таких расчетов подойдёт отчет для анализа ассортимента с расчетом долей на СКД.
Для этого в выражении нужно будет указать имя родительской группировки:
Выбор
Когда Вычислить("Сумма(Сумма)", "Контрагент") > 0
Тогда Сумма / Вычислить("Сумма(Сумма)", "Контрагент") * 100
Иначе 0
КонецВыбора
Таким образом, функция Вычислить() является мощным и гибким инструментом, который позволяет решать широкий круг задач по расчету относительных показателей в системе компоновки данных, эффективно обходя ограничения последовательной обработки данных.