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