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