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