Как реализовать выбор набора данных или динамическую фильтрацию в СКД при работе с партнерами и сегментами

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет IT и автоматизация бизнеса
← На главную

В процессе разработки сложных отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью кардинально менять логику получения данных в зависимости от выбора пользователя. Типичный пример: отчет должен уметь фильтровать данные либо по конкретному списку Партнеров, либо по принадлежности этих партнеров к определенному Сегменту. При этом сегменты могут храниться в отдельных регистрах сведений, которые изначально не задействованы в основном запросе.

В этой статье мы подробно разберем, как реализовать подобную логику, не создавая громоздких и дублирующих друг друга наборов данных. Мы проанализируем различные подходы — от использования возможностей языка расширений СКД до программного управления схемой компоновки.

Метод 1: Использование расширения языка запросов (фигурные скобки)

Это один из самых элегантных и «штатных» способов решения задачи в 1С. Система компоновки данных позволяет описывать части запроса, которые будут включаться в итоговый SQL-запрос только тогда, когда пользователь установил соответствующую настройку (отбор или параметр).

Рассмотрим ситуацию, когда нам нужно добавить фильтр по сегменту партнера. В тексте запроса набора данных мы можем прописать условие в блоке ГДЕ, используя фигурные скобки. Проанализируем пример кода:


ВЫБРАТЬ
    Продажи.Партнер КАК Партнер,
    Продажи.СуммаОбороти КАК Сумма
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
{ГДЕ
    (Продажи.Партнер В
        (ВЫБРАТЬ
            Сегменты.Партнер
        ИЗ
            РегистрСведений.ПартнерыСегмента КАК Сегменты
        ГДЕ
            Сегменты.Сегмент = &Сегмент))}

Разберем по шагам, как это работает. Когда СКД анализирует данный запрос, она видит конструкцию в фигурных скобках {ГДЕ ...}. Если на форме отчета или в настройках компоновщика параметр &Сегмент не заполнен и отбор по нему не установлен, СКД полностью проигнорирует всё, что написано внутри фигурных скобок. В итоговый запрос к СУБД это условие не попадет, и соединение с регистром ПартнерыСегмента не произойдет.

Преимущество метода: Мы сохраняем чистоту запроса и не перегружаем систему лишними соединениями, если они не требуются пользователю.

Метод 2: Механизм необязательных связей наборов данных

В СКД существует встроенная оптимизация исполняемых запросов. Если вы используете ЛЕВОЕ СОЕДИНЕНИЕ с таблицей (например, с тем же регистром сегментов), но поля из этой таблицы не выбраны пользователем в настройках (в полях выбора, группировках или отборах), то система автоматически исключит это соединение из исполнения.

Давайте выясним, как настроить это правильно:

  1. В конструкторе схемы компоновки данных на закладке «Связи наборов данных» (или прямо в тексте запроса через ЛЕВОЕ СОЕДИНЕНИЕ) добавьте связь основной таблицы продаж с регистром ПартнерыСегмента.
  2. Убедитесь, что в запросе выбрано хотя бы одно поле из регистра (например, Сегмент), но оно не является обязательным.
  3. В настройках СКД на уровне ролей полей проверьте, чтобы для поля Сегмент не стоял флаг «Обязательное».

Если пользователь не добавит поле Сегмент в отбор, СКД сама «выкинет» таблицу из SQL-запроса. Это позволяет иметь один универсальный запрос вместо нескольких разных наборов данных.

Метод 3: Формирование фильтра во временной таблице

Этот метод часто применяется в типовых конфигурациях (ERP, УТ 11). Он заключается в разделении логики подготовки фильтра и получения основных данных. Посмотрим на этот подход подробнее.

Мы создаем первый пакет запроса, который готовит список разрешенных партнеров. Логика может быть такой: если заполнен сегмент — берем партнеров из сегмента, если выбран конкретный список — берем его.


// ПАКЕТ 1: Подготовка фильтра
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ПартнерыСегмента.Партнер КАК Партнер
ПОМЕСТИТЬ ВТ_РазрешенныеПартнеры
ИЗ
    РегистрСведений.ПартнерыСегмента КАК ПартнерыСегмента
ГДЕ
    ПартнерыСегмента.Сегмент = &Сегмент

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Партнеры.Ссылка
ИЗ
    Справочник.Партнеры КАК Партнеры
ГДЕ
    Партнеры.Ссылка В (&СписокПартнеров)
;

// ПАКЕТ 2: Основные данные
ВЫБРАТЬ
    Продажи.СуммаОбороти,
    Продажи.Партнер
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты КАК Продажи
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_РазрешенныеПартнеры КАК Фильтр
    ПО Продажи.Партнер = Фильтр.Партнер

Такой подход позволяет очень гибко настраивать условия «ИЛИ» между параметрами, что стандартными средствами ГДЕ в одном запросе сделать бывает сложно из-за специфики работы индексов.

Метод 4: Программная модификация схемы в модуле отчета

Бывают ситуации, когда установка одной галочки на форме должна кардинально менять структуру запроса. В этом случае мы можем прибегнуть к программному изменению схемы. Разобраться в этом поможет событие ПриКомпоновкеРезультата в модуле объекта отчета.

Рассмотрим пример кода, который меняет текст запроса в зависимости от параметра:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Получаем схему
    Схема = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    НаборДанных = Схема.НаборыДанных.НаборДанных1;
    
    // Проверяем значение параметра из настроек
    ЗначениеПараметра = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ИспользоватьСпецЗапрос"));
    
    Если ЗначениеПараметра <> Неопределено И ЗначениеПараметра.Значение = Истина Тогда
        НаборДанных.Запрос = "ВЫБРАТЬ ... (вариант запроса №1)";
    Иначе
        НаборДанных.Запрос = "ВЫБРАТЬ ... (вариант запроса №2)";
    КонецЕсли;
    
    // Далее выполняем стандартную компоновку с измененной схемой
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(Результат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Этот метод дает 100% контроль над тем, какой набор данных будет исполняться. Мы можем даже полностью заменить один набор данных на другой (например, заменить DataSetQuery на DataSetObject), если это требуется бизнес-логикой.

Метод 5: Использование «Характеристик» для виртуальных полей

Проанализируем еще один интересный механизм — закладка Характеристики в конструкторе СКД. Она позволяет описать правила, по которым система будет «подтягивать» дополнительные данные из регистров сведений, как если бы они были реквизитами основного справочника.

Если мы настроим характеристики для справочника Партнеры, указав в качестве источника регистр ПартнерыСегмента, то в пользовательских настройках отбора у поля Партнер появится вложенное поле Сегмент. При этом в самом тексте запроса нам не нужно писать никаких соединений — СКД построит их автоматически «на лету» только тогда, когда пользователь выберет это поле.

Выясним, какой метод выбрать?

Выбор конкретного пути зависит от сложности задачи:

  1. Если нужно просто добавить необязательный фильтр по связанной таблице — используйте фигурные скобки (Метод 1). Это самый быстрый и производительный способ.
  2. Если логика сложная и зависит от настроек системы (функциональных опций) — лучше всего подойдет программная модификация схемы (Метод 4).
  3. Если вы работаете в типовой конфигурации, где уже реализованы механизмы сегментации — старайтесь придерживаться их методологии, используя временные таблицы (Метод 3), чтобы ваш отчет работал в унисон с остальной системой.

Важно помнить, что создание нескольких независимых наборов данных в одной схеме (с использованием Объединения) часто приводит к избыточности и усложняет поддержку отчета. Всегда лучше стремиться к динамическому управлению одним запросом, используя мощные инструменты, заложенные в платформу 1С:Предприятие 8.3.

← На главную