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