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