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