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