Часто при разработке сложных отчетов на базе Системы Компоновки Данных (СКД) в 1С мы сталкиваемся с двумя нетривиальными задачами. Первая — это необходимость настроить отбор через параметр таким образом, чтобы при его незаполнении отчет не выдавал ошибку, а просто игнорировал это условие. Вторая задача возникает, когда отчет строится на базе нескольких наборов данных, и нам требуется корректно сложить итоги из этих наборов. Разберем по шагам, как правильно обойти эти ситуации, проанализируем частые ошибки и рассмотрим оптимальные архитектурные решения.
Рассмотрим типичную ситуацию: в отчете есть несколько наборов данных. Мы добавляем параметр (например, МестоОплаты) и хотим, чтобы пользователь мог оставить его пустым. Как мы знаем, для того чтобы сделать параметр необязательным, используются фигурные скобки (расширение языка запросов СКД). Однако система все равно выдает ошибку о том, что параметр не заполнен.
Выясним причину такого поведения и проанализируем способы решения проблемы.
Обязательное использование параметра во всех наборах данных
Ключевая особенность СКД заключается в следующем: если один и тот же параметр используется в нескольких местах (в разных наборах данных или в параметрах нескольких виртуальных таблиц), он должен быть обернут в конструкцию {ГДЕ ...} абсолютно везде. Если хотя бы в одном месте запрос обращается к параметру напрямую без фигурных скобок, СКД автоматически помечает этот параметр как обязательный для всего отчета. В результате, даже если в 99% случаев вы поставили скобки, одно прямое обращение сломает логику. Проверьте все ваши наборы данных!
Разделение условий внутри фигурных скобок
Частая ошибка — попытка запихнуть все условия в одни фигурные скобки, объединяя их логическим оператором И. Посмотрим на пример, как делать не нужно:
{ГДЕ РучнаяКорректировка.ДатаОперации >= &ДатаНачала
И РучнаяКорректировка.ДатаОперации <= &ДатаКонца
И РучнаяКорректировкаТЧКорректировкаОплаты.ДокументОплаты.МестоОплаты = &МестоОплаты}
Использовать несколько условий в одних фигурных скобках через «И» — плохая практика в СКД. Если один параметр будет заполнен, а другой нет, система может отработать некорректно или удалить из запроса весь блок условий целиком. Каждое необязательное условие рекомендуется оборачивать в отдельные скобки. Разберем правильный вариант:
{ГДЕ РучнаяКорректировка.ДатаОперации >= &ДатаНачала}
{ГДЕ РучнаяКорректировка.ДатаОперации <= &ДатаКонца}
{ГДЕ РучнаяКорректировкаТЧКорректировкаОплаты.ДокументОплаты.МестоОплаты = &МестоОплаты}
Настройки на вкладке «Параметры»
Обязательно перейдите на вкладку параметров в схеме компоновки данных. Найдите проблемный параметр. В колонке «Использование» должно быть установлено значение «Авто» (а не «Всегда»). Также крайне важно убедиться, что снята галочка «Запрещать незаполненные значения».
Если по каким-то причинам конструкция с фигурными скобками не подходит или работает нестабильно в вашей сложной схеме, мы можем решить задачу на уровне самого языка запросов. Этот метод делает код более предсказуемым.
Рассмотрим лаконичную и рабочую конструкцию с использованием логического оператора ИЛИ:
ГДЕ (&МестоОплаты = ЗНАЧЕНИЕ(Справочник.МестаОплаты.ПустаяСсылка)
ИЛИ ДокументОплаты.МестоОплаты = &МестоОплаты)
В этом случае, если пользователь оставляет параметр пустым, в него передается пустая ссылка. Первое условие &МестоОплаты = ЗНАЧЕНИЕ(...) становится ИСТИНОЙ. Из-за оператора ИЛИ остальная часть условия уже не влияет на результат строки, и база возвращает все записи. Если же параметр заполнен, первое условие ложно, и система фильтрует данные по второму условию.
Также можно использовать более громоздкую, но явную конструкцию ВЫБОР КОГДА. Посмотрим на этот пример:
ВЫБОР
КОГДА &МестоОплаты = Значение(Справочник.Подразделение.ПустаяСсылка) ТОГДА ИСТИНА
ИНАЧЕ ДокументОплаты.МестоОплаты = &МестоОплаты
КОНЕЦ
Оба этих варианта отлично справляются с проблемой незаполненных параметров, не полагаясь на скрытую магию парсера СКД.
Теперь перейдем ко второй части обсуждения. У нас есть три набора данных, каждый из которых выводит свои итоги. Нам нужно сложить итоги первого, второго и третьего наборов. Как это сделать правильно?
Главное правило СКД: Несвязанные данные вместе использовать нельзя! Вы не можете просто вытащить поля из независимых наборов в одну группировку и попытаться их сложить. Выясним причину и разберем архитектурно правильные подходы.
Использование вкладки «Ресурсы» (Для связанных наборов)
Если ваши наборы данных логически связаны (например, есть главный набор данных и два подчиненных), и вы корректно настроили связи на вкладке «Связи наборов данных», сложение нужно выполнять правильно. Суммировать показатели крайне не рекомендуется на вкладке «Вычисляемые поля». Это приведет к задвоению или искажению данных при расчете общих итогов на верхних уровнях группировок. Сложение нужно делать исключительно на вкладке «Ресурсы».
В поле выражения для ресурса вы можете прописать формулу вида:
Сумма(ПолеИзПервогоНабора) + Сумма(ПолеИзВторогоНабора) + Сумма(ПолеИзТретьегоНабора)
В этом случае СКД сначала правильно агрегирует суммы по каждой таблице с учетом группировки, а затем сложит уже вычисленные итоги. Если одно из полей может быть NULL, не забудьте обернуть его в функцию ЕстьNull(Поле, 0).
Объединение вместо соединения (Лучшая архитектура)
Проанализируем ситуацию: если наборы данных имеют схожую структуру (например, мы собираем данные о продажах из разных независимых регистров или документов), архитектурно правильнее не плодить разные наборы данных в СКД. Вместо этого сделайте один общий набор данных типа «Запрос».
Внутри этого запроса используйте конструкцию ОБЪЕДИНИТЬ ВСЕ:
ВЫБРАТЬ МестоОплаты, СуммаОплаты, 0 КАК СуммаКорректировки
ИЗ ТаблицаОплат
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ МестоОплаты, 0, СуммаКорректировки
ИЗ ТаблицаКорректировок
В таком варианте СКД получит одну плоскую таблицу. Вам не придется думать о связях и сложных математических формулах. Вы просто добавите поля в «Ресурсы», и СКД сама легко посчитает общие итоги на любых уровнях группировки.
Использование функции ВычислитьВыражение()
Если наборы всё же остаются независимыми, или вам нужно вывести сложные математические расчеты из разных итогов (например, рассчитать рентабельность на основе итогов из разных группировок), в СКД применяется встроенная функция ВычислитьВыражение. Она позволяет получать рассчитанные итоги из других контекстов группировок для проведения арифметических операций.
Пример использования функции в ресурсе:
Сумма(СуммаПродаж) / ВычислитьВыражение("Сумма(СуммаЗатрат)", "ОбщийИтог")
Эта функция обладает мощным функционалом, но требует аккуратности, так как вычисляется в процессе вывода макета.
Применяя описанные выше методы, вы сможете создавать надежные и отказоустойчивые отчеты, которые не боятся пустых параметров и корректно рассчитывают итоги даже при самой сложной структуре наборов данных.