Как получить макет документа на сервере в 1С:Предприятие 8.3

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

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

Разбор причины ошибки: почему не работает ПолучитьМакет()

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

Давайте проанализируем ситуацию на примере кода, который часто вызывает затруднения:


&НаСервере
Функция ТТН_РК_ПечатьНаСервере()
    // ОШИБКА: ЭтотОбъект — это форма!
    Макет = ЭтотОбъект.ПолучитьМакет("ТТН"); 
КонецФункции

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

Решение 1: Использование менеджера документа (Самый быстрый способ)

Если нам нужно просто получить структуру макета (например, табличный документ), и при этом макет привязан к типу документа в конфигураторе, правильнее всего обратиться к менеджеру этого документа. Этот способ не требует создания «тяжелого» объекта документа в памяти сервера и работает максимально оперативно.

Рассмотрим пример кода для получения макета через менеджер:


&НаСервере
Функция ТТН_РК_ПечатьНаСервере()
    // Обращаемся напрямую к менеджеру документа через коллекцию Документы
    Макет = Документы.ХХХ_ВнутреннееПеремещение.ПолучитьМакет("ТТН");
    Возврат Макет;
КонецФункции

Преимущества данного метода:

  1. Высокая скорость: Система обращается напрямую к метаданным, не считывая данные конкретной записи из базы.
  2. Минимальное потребление памяти: На сервере не создается экземпляр объекта со всеми его табличными частями.
  3. Возможность безконтекстного вызова: Мы можем использовать директиву &НаСервереБезКонтекста, что значительно ускоряет работу, так как данные всей формы не передаются с клиента на сервер и обратно.

Решение 2: Использование функции РеквизитФормыВЗначение

Иногда возникают ситуации, когда документ еще не записан в базу данных, или алгоритм заполнения макета жестко прописан в модуле объекта и требует наличия всех данных текущего сеанса редактирования. В этом случае нам необходимо преобразовать данные, которые пользователь видит на экране (реквизит Объект), в полноценный прикладной объект 1С.

Проанализируем пример реализации:


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

Важные нюансы использования этого метода:

Метод РеквизитФормыВЗначение выполняет полную десериализацию данных. Если в вашем документе тысячи строк в табличных частях, этот процесс может занять значительное время и потребовать много оперативной памяти. Используйте этот подход только тогда, когда вам действительно нужны данные «из памяти» формы, которые еще не сохранены в базе.

Оптимизация получения данных для макета

После того как мы получили макет, его нужно заполнить данными. Здесь разработчики часто совершают еще одну ошибку производительности, обращаясь к реквизитам через точку от объекта. Выясним, как делать правильно.

Рассмотрим антипаттерн (плохой пример):


// Это медленно и порождает лишние запросы к БД
Сотрудник = ДокОбъект.ХХХ_РеестрКомандировок[0].ДокументСсылка.СписокСотрудников[0].Сотрудник;

Вместо этого проанализируем рекомендации по оптимизации:

  1. Используйте Запросы: Для заполнения макета всегда лучше использовать объект Запрос. Это позволяет получить все необходимые данные одним пакетом, включая данные из связанных справочников, не создавая цепочку обращений через точку.
  2. Обращайтесь к данным формы: Если данные уже выведены на форму и доступны в реквизите Объект, используйте их напрямую: Объект.Номер, Объект.Дата. Это не требует обращения к серверу базы данных.
  3. Общие макеты: Если один и тот же макет (например, ТТН или форма счета) используется в разных типах документов, вынесите его в Общие макеты. В таком случае получение макета будет выглядеть так: ПолучитьОбщийМакет("ТТН").

Рекомендации по архитектуре (Стандарт БСП)

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

  1. Создайте в Модуле менеджера документа процедуру Печать.
  2. В этой процедуре опишите получение макета и формирование табличного документа.
  3. В модуле менеджера метод ПолучитьМакет() доступен напрямую через ЭтотОбъект.ПолучитьМакет() или просто ПолучитьМакет(), так как контекстом модуля менеджера является сам менеджер.

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

Выводы

Подводя итог, кратко сформулируем правила работы с макетами на сервере:

← На главную