Как программно перехватить и изменить запрос в СКД

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

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

Перехват запроса в процедуре ПриКомпоновкеРезультата

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

Проанализируем базовый алгоритм действий. Для того чтобы программно изменить запрос, нам необходимо установить параметр СтандартнаяОбработка в значение Ложь, изменить текст запроса в схеме и затем самостоятельно описать весь процесс вывода отчета.

Разберем пример кода:


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

Работа с копией схемы данных

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

Проанализируем более безопасный подход — использование копии схемы. Мы создадим копию, внесем в нее изменения и передадим ее в компоновщик макета:


// Создаем копию схемы из макета
НоваяСхема = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

// Модифицируем запрос в копии
Для Каждого НаборДанных Из НоваяСхема.НаборыДанных Цикл
    Если ТипЗнч(НаборДанных) = Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") Тогда
        НаборДанных.Запрос = СтрЗаменить(НаборДанных.Запрос, "Организация = &Организация", "Организация В (&Организация)");
    КонецЕсли;
КонецЦикла;

// Используем НоваяСхема при вызове КомпоновщикМакета.Выполнить(...)
МакетКомпоновки = КомпоновщикМакета.Выполнить(НоваяСхема, НастройкиОтчета, ДанныеРасшифровки);

Этот метод позволяет избежать "загрязнения" основной схемы и гарантирует повторяемость результата. Для упрощения программной модификации и работы с объектной моделью СКД можно использовать библиотеку-обёртку над компоновкой данных.

Особенности работы с параметрами и типами данных

Просто заменить = на В в тексте запроса часто бывает недостаточно. Выясним причину: если в исходной схеме параметр Организация имеет тип СправочникСсылка.Организации, то система не позволит пользователю выбрать список или массив значений в интерфейсе отчета.

Чтобы предоставить пользователю возможность выбора нескольких организаций, нам нужно программно изменить доступные типы параметра. Рассмотрим, как это сделать:

  1. Найдем нужный параметр в схеме компоновки.
  2. Изменим его свойство ДоступныеТипы, добавив возможность использования списка значений.
  3. Если требуется, программно установим признак "Доступен список значений".

Пример программной настройки параметра:


ПараметрСКД = НоваяСхема.Параметры.Найти("Организация");
Если ПараметрСКД <> Неопределено Тогда
    // Позволяем выбирать список значений
    ПараметрСКД.ТипЗначения = Новый ОписаниеТипов("СписокЗначений");
КонецЕсли;

Использование расширений для сохранения поддержки

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

Используйте аннотацию &Вместо, если вы полностью берете управление на себя, или &Перед, если нужно только подготовить данные. Это самый современный и правильный способ модификации логики типовых решений.

Альтернатива: Фиксированные настройки

Иногда изменение текста запроса — это избыточное решение. Разберем ситуацию: если в запросе СКД включено Автозаполнение, система автоматически добавит условия в секцию ГДЕ на основе настроенных отборов.

Вместо правки текста запроса через СтрЗаменить, мы можем программно добавить элемент отбора в ФиксированныеНастройки компоновщика. СКД самостоятельно преобразует этот отбор в корректное SQL-условие IN или = в зависимости от того, передали вы одно значение или массив. Это гораздо надежнее, так как исключает ошибки синтаксиса при ручной склейке строк запроса.

Инициализация источника доступных настроек

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


ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(НоваяСхема);
КомпоновщикНастроек.Инициализировать(ИсточникНастроек);

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

← На главную