Вопрос создания печатных форм, требующих ввода дополнительных данных перед формированием (например, выбор ответственного, даты, настройки отображения), является классическим для разработчиков 1С. Ситуация усложняется, когда разработка ведется не через классические внешние обработки (EPF), а через современный механизм Расширений конфигурации с использованием Библиотеки Стандартных Подсистем (БСП).
В этой статье мы подробно разберем, как правильно настроить логику работы: вызов команды -> открытие диалогового окна -> передача параметров на сервер -> печать. Мы проанализируем ошибки, возникающие при попытке сделать это "в лоб", и рассмотрим корректный архитектурный подход.
Основная сложность заключается в том, что стандартная команда печати в БСП чаще всего настроена на прямой вызов серверной процедуры формирования табличного документа (`ВызовСерверногоМетода`). Если нам нужно взаимодействие с пользователем (интерфейс), нам необходим клиентский контекст.
Чтобы реализовать задачу, нам необходимо выполнить следующие шаги:
ВызовКлиентскогоМетода.Давайте рассмотрим реализацию каждого этапа подробно.
В модуле менеджера документа (или в общем модуле, если вы используете подсистему подключаемых команд) при добавлении команды печати необходимо явно указать, что обработчик будет находиться на клиенте.
Обычно это делается в процедуре ДобавитьКомандыПечати. Рассмотрим пример кода:
Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
// Создаем новую команду
Команда = КомандыПечати.Добавить();
Команда.Идентификатор = "СчетЗаказРеклама";
Команда.Представление = НСтр("ru = 'Счет на оплату с рекламой (параметры)'");
// ВАЖНО: Указываем, что сначала нужно выполнить код на клиенте
// В разных версиях БСП синтаксис может немного отличаться, но суть одна
Команда.Тип = "ВызовКлиентскогоМетода";
// Указываем путь к клиентской процедуре в Вашем расширении
// Формат: "ИмяОбщегоМодуля.ИмяПроцедуры"
Команда.Обработчик = "Расш_УправлениеПечатьюКлиент.ПечатьСПараметрами";
Команда.ПроверкаПроведенияПередПечатью = Истина;
Команда.Порядок = 1;
КонецПроцедуры
Обратите внимание на поле Обработчик. Оно должно указывать на экспортную процедуру в общем модуле вашего расширения. Этот модуль должен иметь галочки Клиент (управляемое приложение).
Вам необходимо добавить в расширение общую форму (или форму обработки), на которой вы разместите необходимые реквизиты (например, ДатаПодписи, Ответственный, флажок ПечататьЛоготип) и кнопки "Печать" и "Отмена".
В модуле этой формы при нажатии на кнопку "Печать" мы должны закрыть форму и вернуть результат:
&НаКлиенте
Процедура КомандаПечать(Команда)
// Собираем параметры в структуру
ПараметрыВозврата = Новый Структура;
ПараметрыВозврата.Вставить("ВыполнитьПечать", Истина);
ПараметрыВозврата.Вставить("ДопРеквизит", Объект.НужныйРеквизит);
// Закрываем форму и передаем структуру
Закрыть(ПараметрыВозврата);
КонецПроцедуры
Самая ответственная часть — это клиентский модуль. Здесь мы должны перехватить управление, открыть форму и ждать, пока пользователь нажмет кнопку. Поскольку в современном 1С модальные окна не рекомендуются (или запрещены), мы используем ОписаниеОповещения.
Создадим общий модуль Расш_УправлениеПечатьюКлиент (в свойствах: Клиент). Напишем туда процедуру, которую указали в шаге 1.
// Входная точка команды печати
&НаКлиенте
Процедура ПечатьСПараметрами(ПараметрыПечати, АдресРезультата = "") Экспорт
// Подготовка параметров для открытия формы
ПараметрыФормы = Новый Структура("ОбъектыНазначения", ПараметрыПечати.ОбъектыНазначения);
// Создаем описание оповещения - какая процедура выполнится после закрытия формы
Оповещение = Новый ОписаниеОповещения("ПечатьСПараметрамиЗавершение", ЭтотОбъект, ПараметрыПечати);
// Открываем нашу форму параметров
ОткрытьФорму("ОбщаяФорма.Расш_ФормаПараметровПечати", ПараметрыФормы, , , , , Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
// Процедура, которая сработает после закрытия формы параметров
&НаКлиенте
Процедура ПечатьСПараметрамиЗавершение(Результат, ПараметрыПечати) Экспорт
// Проверяем, что вернула форма (не нажал ли пользователь "Отмена" или крестик)
Если ТипЗнч(Результат) <> Тип("Структура") Или НЕ Результат.Свойство("ВыполнитьПечать") Тогда
Возврат;
КонецЕсли;
// Добавляем полученные от пользователя параметры в общую структуру параметров печати
// Это ключевой момент: мы пробрасываем данные сквозь БСП
Если ПараметрыПечати.ПараметрыВыполнения = Неопределено Тогда
ПараметрыПечати.ПараметрыВыполнения = Новый Структура;
КонецЕсли;
ПараметрыПечати.ПараметрыВыполнения.Вставить("НашДопПараметр", Результат.ДопРеквизит);
// Принудительно вызываем выполнение команды печати, но уже "напрямую"
// Обычно используется метод ВыполнитьКомандуПечати модуля УправлениеПечатьюКлиент
УправлениеПечатьюКлиент.ВыполнитьКомандуПечати(
"СчетЗаказРеклама", // Идентификатор команды
ПараметрыПечати.ОбъектыНазначения,
ПараметрыПечати.ПараметрыВыполнения,
Undefined,
Undefined
);
КонецПроцедуры
Важное примечание: Метод УправлениеПечатьюКлиент.ВыполнитьКомандуПечати может отличаться в зависимости от версии БСП. Вам нужно посмотреть в вашей конфигурации, какой метод используется для программного вызова печати. Суть в том, что мы повторно вызываем печать, но теперь в структуру ПараметрыВыполнения уже вложены наши данные.
Теперь, когда управление снова передано механизму БСП и уходит на сервер для формирования макета, нам нужно перехватить эти параметры в процедуре формирования печатной формы.
В модуле менеджера (или там, где у вас процедура формирования табличного документа):
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Проверяем, нужно ли нам печатать нашу форму
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "СчетЗаказРеклама") Тогда
// Извлекаем переданный с клиента параметр
НашПараметр = Неопределено;
Если ПараметрыПечати.Свойство("НашДопПараметр", НашПараметр) Тогда
// Параметр успешно получен!
КонецЕсли;
// Дальнейшая логика формирования Табличного Документа
ТабДок = СформироватьПечатнуюФорму(МассивОбъектов, НашПараметр);
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"СчетЗаказРеклама",
"Счет на оплату",
ТабДок
);
КонецЕсли;
КонецПроцедуры
В обсуждении также упоминалось, что задачу можно решить классическим способом — через файл внешней обработки (.epf), подключенный через справочник "Дополнительные отчеты и обработки". Этот способ часто проще, так как не требует использования Расширений.
Для этого в модуле объекта обработки в функции СведенияОВнешнейОбработке используется специальный тип команды:
Функция СведенияОВнешнейОбработке() Экспорт
// ... инициализация параметров регистрации ...
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Счет с параметрами";
НоваяКоманда.Идентификатор = "СчетПараметры";
// Этот тип команды заставит 1С сначала открыть основную форму обработки
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
НоваяКоманда.ПоказыватьОповещение = Истина;
Возврат ПараметрыРегистрации;
КонецФункции
В этом случае при нажатии кнопки "Печать" в документе откроется форма вашей внешней обработки. На ней вы размещаете кнопку "Сформировать", код которой самостоятельно сформирует табличный документ и покажет его пользователю.
Давайте проанализируем ошибки, которые часто совершают разработчики при решении этой задачи:
ОткрытьФорму недоступен на сервере. Формирование печатных форм в БСП по умолчанию происходит на сервере, поэтому нужно разрывать цепочку вызовом клиентского метода.ОткрытьФормуМодально может приводить к ошибкам или блокировке интерфейса в веб-клиенте. Всегда используйте ОписаниеОповещения.СведенияОВнешнейОбработке) и для Расширений (через ДобавитьКомандыПечати в модуле менеджера) отличается.Используя подход с разделением на клиентский вызов формы и последующую передачу параметров на сервер, вы сможете создавать гибкие и удобные инструменты печати для пользователей, оставаясь в рамках стандартов разработки 1С.