Как динамически переопределить основную схему компоновки данных (СКД) в 1С 8.3?

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

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

В этой статье мы подробно разберем причины этой ошибки, выясним, как устроена работа со схемами компоновки на управляемых формах, и рассмотрим три надежных практических решения этой задачи.

Выясняем причину: почему схема "теряется"?

Рассмотрим, что происходит в коде, когда мы пытаемся присвоить схему напрямую в модуле формы:


ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
СхемаКомпоновкиДанных = ОтчетОбъект.ПолучитьМакет("ГрафикВыставленияАктов");
ОтчетОбъект.СхемаКомпоновкиДанных = СхемаКомпоновкиДанных;
ЗначениеВРеквизитФормы(ОтчетОбъект, "Отчет");

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

При каждом новом серверном вызове платформа заново создает экземпляр ОтчетОбъект на основе данных формы и дефолтных метаданных конфигурации. Так как в метаданных отчета наша динамическая схема не назначена основной, программно установленная ранее схема просто стирается и заменяется на Неопределено.

Для решения этой проблемы мы можем использовать один из трех подходов, описанных ниже.

---

Решение 1. Инициализация компоновщика через Временное Хранилище

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

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

Разберем по шагам правильную реализацию в модуле управляемой формы отчета:


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

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

---

Решение 2. Универсальный программный вывод в модуле объекта (ПриКомпоновкеРезультата)

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

Для реализации этого метода создадим в реквизитах нашего отчета строковый реквизит ИмяТекущейСхемы. Будем заполнять его на форме при открытии, а в модуле объекта анализировать это значение.

Проанализируем пример кода в Модуле объекта отчета:


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

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

---

Решение 3. Интеграция с подсистемами БСП (для УТ 11, ERP, КА, ЗУП)

Если вы работаете в типовой конфигурации, построенной на базе Библиотеки Стандартных Подсистем (БСП), ручное переопределение процедуры ПриКомпоновкеРезультата может нарушить работу стандартных механизмов: сохранение пользовательских вариантов отчетов, рассылку отчетов, печать и отправку по почте.

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

Рассмотрим пример правильной интеграции в Модуле объекта отчета:


#Область ПрограммныйИнтерфейсБСП

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

#КонецОбласти

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

← На главную