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

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

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

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

Почему стандартная подмена схемы часто не работает?

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

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

Решение 1: Полная реинициализация компоновщика через временное хранилище

Рассмотрим пошаговый алгоритм подмены схемы в обработчике создания формы. Этот метод позволяет корректно передать новую схему с сервера на форму.

  1. Помещаем схему компоновки (полученную, например, из Регистра Сведений) во временное хранилище.
  2. В параметрах открытия формы передаем адрес этого хранилища.
  3. В форме отчета выполняем переподключение компоновщика.

Пример реализации на стороне сервера формы:


&НаСервере
Процедура ПодменитьСхемуНаСервере()
    
    // 1. Получаем новую схему (например, из макета или регистра)
    НоваяСхема = ПолучитьСхемуИзВнешнегоИсточника(); 
    
    // 2. Преобразуем реквизит формы "Отчет" в прикладной объект
    ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
    
    // 3. Подменяем схему в объекте
    ОтчетОбъект.СхемаКомпоновкиДанных = НоваяСхема;
    
    // 4. Важнейший этап: создание нового источника настроек
    // Без этого шага форма будет использовать старые метаданные
    URLСхемы = ПоместитьВоВременноеХранилище(НоваяСхема, ЭтаФорма.УникальныйИдентификатор);
    ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(URLСхемы);
    
    // 5. Инициализация компоновщика новыми данными
    ОтчетОбъект.КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
    
    // 6. Загружаем настройки по умолчанию из новой схемы
    ОтчетОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(НоваяСхема.НастройкиПоУмолчанию);
    
    // 7. Возвращаем объект в реквизит формы
    ЗначениеВРеквизитФормы(ОтчетОбъект, "Отчет");
    
КонецПроцедуры

Обратите внимание на использование УникальныйИдентификатор формы при помещении схемы в хранилище. Это гарантирует, что схема будет жить ровно столько, сколько открыта форма, и не возникнет конфликтов между разными сеансами пользователей.

Решение 2: Использование механизмов XML-сериализации

Если ваша задача — хранить схемы в базе данных в текстовом виде (например, для удобства правки запросов «на лету»), разберем метод работы через XML. Этот подход позволяет избежать проблем с типами данных при передаче между клиентом и сервером.

Посмотрим на пример кода, который считывает настройки из XML и применяет их к отчету:


// Предположим, схема или настройки хранятся в строке XML
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);

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

// Загружаем настройки в существующий компоновщик объекта
Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(НастройкиКомпоновки);

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

Решение 3: Программный вывод результата (Обход типовой формы)

В некоторых случаях типовой механизм формирования БСП (кнопка «Сформировать») может конфликтовать с подмененной схемой, если он обращается к методам объекта напрямую. Если вы столкнулись с тем, что настройки на форме верные, но результат выводится по «старой» схеме, проанализируем ситуацию программного вывода.

Мы можем переопределить формирование отчета, используя ПроцессорКомпоновкиДанных. Разберем основные этапы:

  1. Компоновщик макета: Создает макет для исполнения на основе схемы и текущих настроек пользователя.
  2. Процессор компоновки: Выполняет запросы к базе данных и сопоставляет их с макетом.
  3. Процессор вывода: Отрисовывает результат в табличный документ.

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

Интеграция с БСП: Варианты отчетов

Важный момент при переходе на типовые формы БСП — сохранение пользовательских вариантов. БСП хранит варианты в справочнике ВариантыОтчетов, связывая их с полным именем метаданных объекта (например, Отчет.УниверсальныйКонтейнер). Если вы используете один отчет-контейнер для разных схем, настройки пользователей могут перемешаться.

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

Особенности работы с внешними отчетами

Если вы решили пойти по пути создания внешних отчетов «на лету» (как предлагалось в одном из сообщений форума), помните о безопасности. Платформа ограничивает работу с внешними объектами. Для корректной работы в БСП лучше использовать справочник «Дополнительные отчеты и обработки».

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

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

← На главную