При разработке внешних отчетов в системе «1С:Предприятие 8» программисты часто сталкиваются с ситуацией, когда необходимо программно обратиться к макету (табличному документу, двоичным данным или схеме компоновки), находясь в модуле формы. Обычный метод ПолучитьМакет(), привычный по работе в модуле объекта, в модуле формы выдает ошибку, так как контекст формы напрямую не «видит» макеты самого объекта. Разберем подробно, как правильно решить эту задачу, учитывая особенности управляемого приложения.
Самый распространенный и правильный способ доступа к макетам из управляемой формы — это преобразование данных формы (реквизита) в полноценный прикладной объект на стороне сервера. Проанализируем, почему это необходимо. В управляемых формах ЭтотОбъект внутри модуля формы ссылается на саму форму, а не на отчет. Для того чтобы «достучаться» до метаданных и макетов, нам нужно временно создать объект отчета в памяти сервера.
Рассмотрим основной пример кода. Важно помнить, что основной реквизит внешнего отчета в управляемой форме по умолчанию называется Отчет (в отличие от обработок, где это часто Объект).
&НаСервере
Процедура ПолучитьМакетНаСервере()
// Преобразуем данные формы в объект отчета
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
// Теперь мы можем получить любой макет по его имени
Макет = ОтчетОбъект.ПолучитьМакет("МакетВнешнегоОтчета");
// Далее работаем с макетом (например, выводим в ТабличныйДокумент)
// ...
КонецПроцедуры
Выясним важную деталь: если вы попробуете использовать РеквизитФормыВЗначение("Объект"), система может выдать ошибку «Реквизит не найден», если в вашей форме основной реквизит называется Отчет. Всегда проверяйте имя основного реквизита в дереве метаданных формы.
Часто макетом, который нужно получить, является Основная Схема Компоновки Данных. Процесс получения аналогичен, но мы можем сразу типизировать переменную для дальнейшей программной настройки схемы.
Разберем по шагам, как получить СКД:
&НаСервере
Функция ПолучитьСхемуКомпоновки()
// Получаем объект отчета
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
// Получаем макет схемы
Схема = ОтчетОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Возврат Схема;
КонецФункции
Такой подход позволяет нам динамически изменять настройки компоновки, добавлять параметры или менять текст запроса прямо перед формированием отчета из формы.
Рассмотрим ситуацию с точки зрения производительности. Метод РеквизитФормыВЗначение является «тяжелой» операцией, так как платформа создает полную копию объекта на сервере, инициализирует его и заполняет данными из формы. Если вам нужно обращаться к макету многократно (например, при каждом изменении параметров пользователем), вызывать этот метод постоянно — плохая практика.
Посмотрим на решение через Временное хранилище. Мы можем получить макет один раз при создании формы и сохранить адрес этого макета в реквизит формы.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем макет один раз
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
Макет = ОтчетОбъект.ПолучитьМакет("МойМакет");
// Помещаем его во временное хранилище и сохраняем адрес в реквизит формы (типа Строка)
АдресМакетаВоХранилище = ПоместитьВоВременноеХранилище(Макет, ЭтаФорма.УникальныйИдентификатор);
КонецПроцедуры
Теперь в любой другой процедуре сервера мы можем быстро извлечь макет из хранилища по адресу, не выполняя дорогостоящую операцию РеквизитФормыВЗначение.
Иногда возникает задача получить список всех макетов, доступных в отчете, или проверить существование макета с определенным именем. Для этого проанализируем коллекцию метаданных.
&НаСервере
Процедура ПроверитьНаличиеМакетов()
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
// Обходим коллекцию макетов через метаданные
Для Каждого ТекущийМакет Из ОтчетОбъект.Метаданные().Макеты Цикл
Сообщить("Найден макет: " + ТекущийМакет.Имя);
КонецЦикла;
КонецПроцедуры
Использование Метаданные() позволяет писать универсальные механизмы обработки внешних отчетов, которые не зависят от жестко заданных имен макетов.
Если ваш отчет зарегистрирован в справочнике «Дополнительные отчеты и обработки» (используется БСП), доступ к макетам может осуществляться иначе. В этом случае отчет физически может находиться в хранилище значений в базе данных. Для программного доступа к такому отчету (без открытия его формы) используется менеджер внешних отчетов:
ВнешниеОтчеты.Подключить().ВнешниеОтчеты.Создать(ИмяПодключенногоОтчета).ПолучитьМакет() у созданного объекта.Важное ограничение: Помните, что метод ПолучитьМакет доступен исключительно на сервере. Попытка вызвать его в процедуре с директивой &НаКлиенте неизбежно приведет к ошибке компиляции. Если данные макета нужны на клиенте (например, файл шаблона для сохранения на диск), их необходимо сначала получить на сервере, поместить во временное хранилище и передать адрес на клиент.
Мы проанализировали основные способы доступа к макетам внешнего отчета. Основным инструментом остается связка РеквизитФормыВЗначение("Отчет") и ПолучитьМакет(). При проектировании сложных отчетов всегда учитывайте контекст исполнения кода (Сервер/Клиент) и старайтесь минимизировать количество серверных вызовов с полной десериализацией объекта для экономии ресурсов системы.