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