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