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