При разработке расширений для 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда новая печатная форма прекрасно работает на сервере или через удаленный рабочий стол (RDP), но выдает критическую ошибку «Макет "" не найден» у пользователей, работающих через тонкий клиент. Разберем подробно, почему это происходит, как правильно организовать архитектуру печати и как принудительно заставить систему «увидеть» обновленные метаданные.
Прежде всего, важно понимать, что объект Макет (особенно если это табличный документ) физически существует только на стороне сервера. Тонкий клиент не работает с макетами напрямую — он лишь получает от сервера уже сформированный и заполненный ТабличныйДокумент. Когда пользователь инициирует печать, управление передается на сервер, который должен найти макет в метаданных, заполнить его данными и вернуть результат.
Ошибка «Макет не найден» на удаленном рабочем месте при использовании расширений обычно вызвана одной из трех причин:
Как показывает практика, стандартная процедура «Сравнить и объединить конфигурации» для расширений иногда работает нестабильно. Если вы добавили новый макет или изменили структуру существующего, платформа может «запомнить» старое состояние расширения в кэше сервера приложений.
Проанализируем эффективный алгоритм обновления:
%AppData%\Local\1C\1Cv8).Этот метод позволяет серверу 1С полностью перестроить внутренние идентификаторы объектов расширения, после чего тонкий клиент начинает корректно сопоставлять вызовы функций с объектами метаданных.
Рассмотрим ситуацию, когда стандартные функции БСП (Библиотеки стандартных подсистем) не могут найти макет. Часто разработчики используют путь вида Документ.ИмяОбъекта.ИмяМакета. Однако в расширениях, особенно при обращении к заимствованным объектам, синтаксис может требовать уточнения.
Посмотрим на пример кода, который часто вызывает ошибку:
Макет = УправлениеПечатью.МакетПечатнойФормы("Документ.СчетНаОплатуПокупателю.Расш1_СчетДоговор");
Если система выдает ошибку, например, в печатной форме счета на оплату, попробуйте явно указать коллекцию макетов. Выясним причину: некоторые версии платформы при разборе строки пути требуют строгого следования иерархии метаданных. Попробуйте изменить обращение на следующее:
// Явное указание коллекции "Макеты"
Макет = УправлениеПечатью.МакетПечатнойФормы("Документ.СчетНаОплатуПокупателю.Макеты.Расш1_СчетДоговор");
Также убедитесь, что имя макета в коде в точности совпадает с именем в дереве метаданных расширения, включая префикс (например, Расш1_).
Разберем правильную архитектуру печати в расширении. Весь процесс должен происходить на сервере. Рассмотрим пример реализации в модуле менеджера документа, использующий механизм &Вместо для перехвата стандартной печати:
&Вместо("Печать")
Процедура Расш1_Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Проверяем, нужно ли печатать наш макет из расширения
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "Расш1_СчетДоговор") Тогда
// Получаем данные для печати (лучше запросом, а не через ПолучитьОбъект!)
ТаблицаСведений = ПолучитьТаблицуСведенийДляПечати(МассивОбъектов);
// Вызываем серверную функцию формирования документа
ТабличныйДокумент = ПечатьТорговыхДокументов.СформироватьСчетДоговор(ТаблицаСведений, ОбъектыПечати, ПараметрыПечати);
// Выводим результат в коллекцию
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"Расш1_СчетДоговор",
"Счет-Договор (из расширения)",
ТабличныйДокумент
);
КонецЕсли;
КонецПроцедуры
В общем модуле ПечатьТорговыхДокументов (который также должен быть в расширении) функция получения макета должна выглядеть так:
Функция СформироватьСчетДоговор(Сведения, ОбъектыПечати, ПараметрыПечати) Экспорт
// Получаем макет строго на сервере
Макет = УправлениеПечатью.МакетПечатнойФормы("Документ.СчетНаОплатуПокупателю.Расш1_СчетДоговор");
ТабДок = Новый ТабличныйДокумент;
ТабДок.КлючПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_СчетНаОплатуПокупателю_Расш1_СчетДоговор";
// Далее идет стандартный код заполнения областей макета
// ...
Возврат ТабДок;
КонецФункции
Проанализируем антипаттерны, которые часто встречаются в коде начинающих разработчиков и приводят к падению тонкого клиента:
ПолучитьОбъект() в цикле: Никогда не делайте так: Для Каждого Ссылка Из Массив Цикл Макет = Ссылка.ПолучитьОбъект().ПолучитьМакет(...). Это колоссальная нагрузка на сервер и основная причина «отвала» сессий на тонком клиенте. Используйте УправлениеПечатью.МакетПечатнойФормы() один раз перед циклом.&НаСервере, а для тяжелых задач используйте механизмы асинхронного выполнения длительных операций.ПриОпределенииОбъектовСКомандамиПечати.Важный момент: Если вы работаете в распределенной информационной базе или через медленные каналы связи, критически важно, чтобы версия расширения на сервере и в кэше клиента совпадала. При любых странностях в поведении макетов первым делом пробуйте полную переустановку расширения через файл .cfe и перезапуск сервера 1С.