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