Как получить макет во внешнем отчете 1С на управляемых формах?

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

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

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

Особенности клиент-серверного разделения

Прежде чем перейти к написанию кода, важно понять базовое правило платформы 1С: метод ПолучитьМакет() недоступен на стороне клиента. Он может быть выполнен исключительно в серверном контексте (в процедурах и функциях с директивами &НаСервере или &НаСервереБезКонтекста).

В управляемой форме данные отчета хранятся в виде специального реквизита формы (обычно с именем Отчет). Чтобы получить доступ к методам самого объекта (включая получение его макетов), нам необходимо временно «оживить» этот реквизит, превратив его в полноценный прикладной объект типа ВнешнийОтчетОбъект. Для этого используется стандартный метод платформы РеквизитФормыВЗначение().

Стандартный способ получения макета в модуле формы

Рассмотрим классический пример реализации. Предположим, у нас есть управляемая форма внешнего отчета, на которой размещена команда «Сформировать» и реквизит типа ТабличныйДокумент с именем Результат для вывода отчета.

Разберем по шагам, как должен выглядеть программный код в модуле управляемой формы:


&НаКлиенте
Процедура Сформировать(Команда)
    
    // Очищаем табличный документ перед формированием
    Результат.Очистить();
    
    // Вызываем серверную функцию для формирования отчета
    СформироватьНаСервере(Результат);
    
КонецПроцедуры

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

В данном примере мы передаем табличный документ в качестве параметра на сервер, где инициализируем объект отчета, получаем его макет через метод ПолучитьМакет(), извлекаем область Заголовок и выводим её на экран.

Анализ типичной ошибки: «Недопустимое значение параметра (параметр номер 1)»

Очень часто разработчики при попытке получить объект отчета сталкиваются со следующей ошибкой:

«Ошибка при вызове метода контекста (РеквизитФормыВЗначение): Недопустимое значение параметра (параметр номер '1')»

Выясним причину ее возникновения. Такая ситуация происходит из-за путаницы между типом данных объекта и именем реквизита на управляемой форме. Рассмотрим пример ошибочного кода:


// ОШИБКА: Попытка обратиться по типу внешнего отчета
ОтчетОбъект = РеквизитФормыВЗначение("ОтчетБП"); 

Метод РеквизитФормыВЗначение() в качестве первого параметра ожидает строго строковое имя реквизита управляемой формы, который является основным.

Важно помнить правила именования:

  1. В стандартной управляемой форме внешнего отчета основной реквизит по умолчанию всегда называется Отчет (независимо от того, как называется файл отчета на диске или в конфигураторе). Поэтому правильный вызов выглядит так: РеквизитФормыВЗначение("Отчет").
  2. В управляемой форме внешней обработки основной реквизит по умолчанию называется Объект. Если вы копируете код из внешней обработки в отчет, обязательно замените РеквизитФормыВЗначение("Объект") на РеквизитФормыВЗначение("Отчет").
  3. Если вы создали произвольную (не основную) форму вручную, основного реквизита на ней может не быть. В этом случае вам необходимо зайти на вкладку «Реквизиты» формы, добавить реквизит с типом вашего внешнего отчета (или обработки), назвать его Отчет и установить для него свойство «Основной реквизит» (он выделится жирным шрифтом в списке).

Лучшая практика: Вынос логики в Модуль объекта

Хотя связка РеквизитФормыВЗначение() отлично работает, постоянное ее использование непосредственно в модуле формы для выполнения тяжелых операций не является лучшим решением. Метод преобразования реквизита формы в значение заставляет платформу полностью сериализовать все данные формы и создавать объект в оперативной памяти сервера, что создает дополнительную нагрузку на систему.

Проанализируем более профессиональный архитектурный подход: перенос всей логики формирования отчета в Модуль объекта внешнего отчета.

В модуле самого объекта контекст доступен напрямую. Нам не нужно вызывать никаких преобразований — мы можем обращаться к макету напрямую через ключевое слово ЭтотОбъект или просто по имени метода.

Шаг 1. Пишем экспортную процедуру в Модуле объекта внешнего отчета:


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

Шаг 2. Вызываем этот метод из управляемой формы отчета:


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

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

Получение макета внешнего отчета программно по пути к файлу

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

Рассмотрим, как это реализовать:


&НаСервере
Функция ПолучитьМакетИзФайлаОтчета(ПутьКФайлу, ИмяМакета)
    
    // Безопасный режим определяет уровень прав при исполнении кода внешнего отчета
    ИспользоватьБезопасныйРежим = Ложь; 
    
    // Создаем объект внешнего отчета программно с помощью менеджера ВнешниеОтчеты
    ВнешнийОтчетОбъект = ВнешниеОтчеты.Создать(ПутьКФайлу, ИспользоватьБезопасныйРежим);
    
    // Получаем макет из созданного объекта
    Макет = ВнешнийОтчетОбъект.ПолучитьМакет(ИмяМакета);
    
    Возврат Макет;
    
КонецФункции

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

← На главную