Как правильно создать и вывести печатную форму в управляемых формах 1С 8.3?

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

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

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

В чем заключается главная проблема разделения «Клиент-Сервер»?

Для начала выясним причину ошибок, возникающих при попытке сформировать печать напрямую на клиенте. В управляемом приложении код четко разделен на выполняемый на стороне клиента (в тонком или веб-клиенте) и на стороне сервера.

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

Другая распространенная ошибка — попытаться получить макет на сервере и вернуть его на клиент в качестве возвращаемого значения функции. Объект макета не может быть сериализован (передан по сети между сервером и клиентом). При попытке обратиться к методам полученного таким образом макета на клиенте система выдаст ошибку: Метод недоступен на тонком клиенте.

Правильное архитектурное решение выглядит следующим образом:

  1. На клиенте пользователь совершает действие (например, выбирает строку в таблице или нажимает кнопку «Печать»).
  2. Вызывается серверная функция (желательно без контекста формы для экономии ресурсов).
  3. На сервере создается пустой объект ТабличныйДокумент, получается макет, из него извлекаются области, заполняются параметры.
  4. Области выводятся в созданный табличный документ на сервере.
  5. Готовый заполненный ТабличныйДокумент возвращается обратно на клиент (этот объект успешно передается между клиентом и сервером).
  6. На клиенте полученный документ выводится на экран с помощью метода Показать().

Разбор типичных ошибок из обсуждения на форуме

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

Ошибка №1: Конфликт имен переменных на сервере.

Автор попытался написать код:


&НаСервере
Функция ПолучитьМакетНаСервере()
    Объект = РеквизитФормыВЗначение("Объект");
    Макет = Объект.ПолучитьМакет("МакетПоручениеБиржа");
    Возврат Макет;
КонецФункции

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

Ошибка №2: Неправильный параметр в РеквизитФормыВЗначение.

После рекомендации переименовать переменную, автор написал код:

Объект = РеквизитФормыВЗначение("ОбработкаОбъект");

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

ОбработкаОбъект = РеквизитФормыВЗначение("Объект");

Ошибка №3: Попытка использовать контекстный серверный вызов без необходимости.

Для получения макета встроенной в конфигурацию обработки совсем не обязательно конвертировать форму в объект через РеквизитФормыВЗначение(). Это «тяжелая» операция, которая передает все данные формы на сервер. Гораздо эффективнее использовать менеджер обработки напрямую в функции с директивой компиляции &НаСервереБезКонтекста.


Пошаговое руководство по созданию печатной формы

Рассмотрим готовое, оптимизированное решение для вывода печатной формы «МакетПоручениеБиржа» при выборе строки в табличной части (реквизите) тзЖурнал на управляемой форме обработки.

Шаг 1. Создание обработчика события на клиенте

В свойствах элемента управления табличного поля тзЖурнал на форме находим событие Выбор и создаем для него обработчик на клиенте. Этот обработчик будет перехватывать двойной клик по строке.


&НаКлиенте
Процедура тзЖурналВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    
    // Отменяем стандартное поведение платформы (например, открытие формы строки)
    СтандартнаяОбработка = Ложь;
    
    // Получаем данные текущей строки, чтобы передать ключевые параметры на сервер
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Подготавливаем параметры для печати (например, ссылку на документ или структуру параметров)
    ПараметрыПечати = Новый Структура;
    // Предположим, в строке нашей ТЗ есть колонка "ДокументСсылка"
    ПараметрыПечати.Вставить("Ссылка", ТекущиеДанные.ДокументСсылка);
    
    // Вызываем серверную функцию формирования печатной формы
    ТабличныйДокумент = СформироватьПечатнуюФормуНаСервере(ПараметрыПечати);
    
    // Отображаем полученный результат пользователю
    Если ТабличныйДокумент <> Неопределено Тогда
        ТабличныйДокумент.Показать("Печать поручения биржи");
    КонецЕсли;
    
КонецПроцедуры

Шаг 2. Реализация логики формирования макета на сервере

Теперь создадим бесконтекстную серверную функцию СформироватьПечатнуюФормуНаСервере. Обратите внимание, что мы обращаемся к макету через менеджер обработки Обработки.МояОбработка.ПолучитьМакет(). Замените «МояОбработка» на фактическое имя вашей обработки в метаданных.


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

Альтернативный вариант: вывод печатной формы прямо на форму

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

  1. В дереве реквизитов нашей управляемой формы создадим новый реквизит. Назовем его РезультатПечати и установим тип данных ТабличныйДокумент.
  2. Перетащим этот реквизит мышкой на рабочую область формы. Платформа автоматически создаст элемент управления типа Поле табличного документа.
  3. В этом сценарии нам потребуется использовать контекстный вызов &НаСервере, чтобы напрямую управлять реквизитом формы.

Код процедуры вывода в форму будет выглядеть следующим образом:


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

При таком подходе достаточно вызвать метод СформироватьПечатьНаФорме(ПараметрыПечати) в клиентском обработчике выбора строки, и печатная форма мгновенно отобразится прямо на текущем экране пользователя.

← На главную