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

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

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

Почему простая подмена текста запроса в схеме не всегда работает?

Рассмотрим типичную ситуацию: программист пытается изменить свойство Запрос у набора данных в модуле формы или объекта. Однако в управляемом приложении реквизит Отчет.КомпоновщикНастроек инициализируется на основе основной схемы компоновки данных, указанной в метаданных. Если мы просто поменяем схему "в памяти", компоновщик на форме об этом не узнает, так как он продолжает работать со старой версией метаданных. Чтобы изменения вступили в силу, нам необходимо заново проинициализировать компоновщик, используя обновленную схему.

Вариант 1. Использование события ПриКомпоновкеДанных

Этот метод считается наиболее "чистым" с точки зрения архитектуры 1С. Мы перехватываем процесс формирования отчета непосредственно в модуле объекта. Проанализируем, как это сделать:


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

В данном случае мы полностью берем управление процессом на себя. Это позволяет внедрить любую логику перед формированием отчета, включая регистрацию объектов на обмен или дополнительную проверку прав доступа.

Вариант 2. Программная инициализация в управляемой форме через Временное хранилище

Если нам нужно, чтобы пользователь видел актуальный список полей и отборов в настройках отчета сразу после выбора вида справочника, нам придется обновить компоновщик настроек в модуле формы. Рассмотрим алгоритм действий:

  1. Изменяем схему компоновки на сервере.
  2. Помещаем измененную схему во Временное хранилище.
  3. Инициализируем КомпоновщикНастроек, используя адрес временного хранилища.

Разберем пример кода в модуле формы:


&НаСервере
Процедура ОбновитьСхемуНаСервере()
    
    // 1. Получаем объект отчета и схему
    ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
    Схема = ОтчетОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    
    // 2. Модифицируем текст запроса
    Схема.НаборыДанных[0].Запрос = "ВЫБРАТЬ Ссылка ИЗ Справочник." + ИмяСправочника;
    
    // 3. Помещаем схему во временное хранилище
    АдресСхемы = ПоместитьВоВременноеХранилище(Схема, УникальныйИдентификатор);
    
    // 4. Инициализируем источник доступных настроек
    ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы);
    Отчет.КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
    
    // 5. Важно: загружаем настройки, чтобы обновить доступные поля в интерфейсе
    Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
    
    ЗначениеВРеквизитФормы(ОтчетОбъект, "Отчет");
    
КонецПроцедуры

Важный нюанс: при использовании ИсточникДоступныхНастроекКомпоновкиДанных в управляемых формах крайне рекомендуется передавать именно адрес временного хранилища, а не сам объект схемы. Это обеспечивает корректную синхронизацию данных между сервером и клиентом.

Методика "Универсального отчета"

В типовых конфигурациях часто применяется подход, при котором текст запроса в СКД содержит параметры-заменители или пустые конструкции, которые дозаполняются программно. Рассмотрим подробнее механизм расширения языка запросов СКД.

Если вы используете фигурные скобки {} в тексте запроса, СКД может автоматически добавлять поля и условия. Однако для полной смены таблицы (например, с Справочник.Контрагенты на Справочник.Номенклатура) этого недостаточно. В таких случаях мы используем объектную модель схемы. Разберем по шагам создание набора данных программно:


// Создаем новый набор данных - запрос
НаборДанных = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = "ОсновнойНабор";
НаборДанных.Запрос = "ВЫБРАТЬ * ИЗ Справочник.ФизическиеЛица";
НаборДанных.ИсточникДанных = "ИсточникДанных1";

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

Этот подход сложнее, но он позволяет создавать отчеты абсолютно любой структуры "на лету", как это делает Универсальный отчет в БП 3.0 или ЗУП 3.1.

Как сохранить настройки пользователя при смене запроса?

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

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

Полезные советы при работе с динамической СКД

  1. Использование внешних наборов данных: Если формирование сложного текста SQL-запроса вызывает трудности, рассмотрите вариант использования Набора данных - объект. Вы можете выполнить обычный запрос через Запрос.Выполнить().Выгрузить(), получить Таблицу Значений и передать её в СКД через структуру ВнешниеНаборыДанных в процедуре компоновки.
  2. Обновление интерфейса: После программной смены схемы в форме может потребоваться принудительное обновление элементов управления. Используйте метод формы ОбновитьОтображениеДанных(), чтобы визуальные настройки (список доступных полей в отборах) синхронизировались с новой схемой.
  3. Отладка фоновых заданий: Помните, что отчеты в управляемых формах часто формируются в фоновых заданиях. При отладке процедуры ПриКомпоновкеДанных обязательно включите в конфигураторе возможность отладки фоновых заданий, иначе точки останова не сработают.

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

← На главную