Как реализовать диалог с пользователем во внешней печатной форме перед печатью?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Разработка внешних печатных форм (ВПФ) для конфигураций на базе Библиотеки Стандартных Подсистем (БСП) — одна из самых частых задач программиста 1С — для этого есть конструктор печатных форм без программирования для 1С. Обычно процесс выглядит линейно: пользователь нажимает кнопку «Печать», система передает ссылки на объекты на сервер, формирует табличный документ и возвращает его на экран. Однако, часто возникают ситуации, когда перед формированием печатной формы необходимо задать пользователю вопрос или попросить уточнить параметры (например, выбрать ответственного, указать дату, настроить фильтры или подтвердить действие).

В этой статье мы подробно разберем, почему стандартный подход не позволяет использовать диалоговые окна, и рассмотрим пошаговое решение этой задачи, опираясь на опыт сообщества и стандарты разработки 1С.

Проблема: Контекст исполнения кода

Давайте проанализируем, как обычно устроена внешняя печатная форма. В модуле объекта обработки существует экспортная функция СведенияОВнешнейОбработке, где мы регистрируем команды. Чаще всего в типовых примерах используется следующий тип команды:


ПараметрыРегистрации = Новый Структура;
// ... заполнение других свойств
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
// Использование "ВызовСерверногоМетода"
Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();

Суть проблемы кроется именно здесь. Режим ВызовСерверногоМетода означает, что при нажатии кнопки платформа сразу передает управление на сервер в процедуру Печать модуля объекта. На сервере, как известно, любой интерактив запрещен: мы не можем показать Предупреждение, открыть форму или задать Вопрос. Если попытаться это сделать, код либо не выполнится, либо вызовет ошибку.

Чтобы "вклиниться" в процесс с диалогом, нам нужно перехватить управление на клиенте, до того как оно уйдет на сервер. Рассмотрим два основных способа сделать это.

Способ 1: Использование команды «Открытие формы»

Это наиболее гибкий и рекомендуемый способ, если вам нужно запросить у пользователя сложные параметры (несколько полей, галочек, списков). Мы заменим прямой вызов печати на открытие формы обработки, где нарисуем наш интерфейс.

Разберем реализацию по шагам.

Шаг 1. Изменение параметров регистрации

В функции СведенияОВнешнейОбработке необходимо изменить тип использования команды. Вместо вызова серверного метода мы указываем открытие формы.


Функция СведенияОВнешнейОбработке() Экспорт
    
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
    
    // ... описание обработки ...
    
    Команда = ПараметрыРегистрации.Команды.Добавить();
    Команда.Представление = "Моя печатная форма с диалогом";
    Команда.Идентификатор = "ПечатьСДиалогом";
    
    // ВАЖНО: Меняем тип команды
    Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
    
    Команда.ПоказыватьОповещение = Ложь;
    Команда.Модификатор = "ПечатьMXL";
    
    Возврат ПараметрыРегистрации;
    
КонецФункции

Шаг 2. Создание формы обработки

Теперь нам нужно создать управляемую форму в самой внешней обработке и назначить её основной. Когда пользователь нажмет кнопку печати в документе, БСП откроет эту форму.

В модуле формы нам нужно обработать событие ПриСозданииНаСервере, чтобы "поймать" объекты, из которых была вызвана печать. Они передаются через параметры формы.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Получаем ссылки на объекты, которые пользователь выделил в списке или открыл
    Если Параметры.Свойство("ОбъектыНазначения") Тогда
        // Сохраним их в реквизит формы (нужно создать реквизит типа Произвольный или СписокЗначений)
        ОбъектыПечати = Параметры.ОбъектыНазначения; 
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Реализация логики печати

На форме мы размещаем необходимые элементы управления (поля ввода) и кнопку "Печать" (или "Сформировать"). При нажатии на кнопку мы уже находимся в клиентском контексте формы, поэтому можем проверить введенные данные и запустить процесс формирования печатной формы.

Важный момент: так как мы используем БСП, нам нужно правильно вернуть сформированный табличный документ. Обычно это делается вызовом серверной функции, которая возвращает табличный документ, и последующим его отображением на клиенте.


&НаКлиенте
Процедура КомандаПечать(Команда)
    
    // Здесь можно выполнить любые проверки на Клиенте
    Если Не ЗначениеЗаполнено(НастройкаПользователя) Тогда
        ПоказатьПредупреждение(, "Укажите настройку!");
        Возврат;
    КонецЕсли;
    
    // Вызываем серверную функцию для формирования табличного документа
    ТабДок = СформироватьПечатнуюФормуНаСервере();
    
    // Используем стандартный механизм БСП для показа печати
    УправлениеПечатьюКлиент.ПоказатьДокумент(ТабДок);
    
    // Или закрываем форму, если это требуется
    ЭтаФорма.Закрыть();
    
КонецПроцедуры

&НаСервере
Функция СформироватьПечатнуюФормуНаСервере()
    
    // Здесь ваша логика формирования макета
    // Вы можете использовать ОбъектыПечати (сохраненные ранее)
    // и реквизиты формы (настройки пользователя)
    
    ТабДок = Новый ТабличныйДокумент;
    // ... заполнение табдока ...
    
    Возврат ТабДок;
    
КонецФункции

В качестве "живого" примера реализации такого подхода в типовых конфигурациях (ERP, УТ, КА) можно посмотреть документ АктСверкиВзаиморасчетов. Там печать реализована именно через открытие формы с настройками параметров сверки.

Способ 2: Использование клиентского метода (ВызовКлиентскогоМетода)

Если вам не нужна полноценная форма с настройками, а требуется лишь простой вопрос (Да/Нет) или выбор из списка, можно использовать тип команды ВызовКлиентскогоМетода. Это позволяет избежать создания лишнего окна формы, если логика простая.

Шаг 1. Настройка регистрации


Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();

Шаг 2. Клиентский код в модуле формы

В этом случае в модуле формы обработки необходимо создать экспортную процедуру Печать. Именно ее вызовет БСП.

Так как в современных конфигурациях модальные окна запрещены (или не рекомендуются), мы будем использовать ОписаниеОповещения для обработки ответа пользователя.


&НаКлиенте
Процедура Печать(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    
    // Сохраним объекты назначения во временном хранилище или переменной модуля (если нужно)
    // Но лучше передавать их параметром дальше.
    
    Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект, ОбъектыНазначенияМассив);
    
    ПоказатьВопрос(Оповещение, "Включить дополнительную расшифровку?", РежимДиалогаВопрос.ДаНет);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ОбъектыНазначения) Экспорт
    
    НужнаРасшифровка = (Результат = КодВозвратаДиалога.Да);
    
    // Теперь вызываем сервер для печати, передавая ответ пользователя
    ПечатьНаСервере(ОбъектыНазначения, НужнаРасшифровка);
    
КонецПроцедуры

&НаСервере
Процедура ПечатьНаСервере(Объекты, ДопПараметр)
    
    // Логика формирования ТабДокумента
    // ...
    // Для вывода на экран в БСП часто используется коллекция печатных форм.
    // Если метод "ВызовКлиентскогоМетода", то вывод печатной формы часто приходится 
    // организовывать самостоятельно через УправлениеПечатьюКлиент (вернув ТабДок на клиент).
    
КонецПроцедуры

Нюансы работы с коллекцией печатных форм

В стандартном варианте (ВызовСерверногоМетода) БСП ожидает, что процедура Печать на сервере заполнит коллекцию печатных форм. Когда мы переходим на клиентские методы, этот автоматизм пропадает.

Если вы используете способ с Открытием Формы, вы полностью берете управление выводом на себя. Вы формируете документ и вызываете УправлениеПечатьюКлиент.ПечатьДокументов() или просто ТабДок.Показать().

Резюме и рекомендации

Подытожим алгоритм действий для решения задачи автора:

  1. Определите сложность диалога. Если настроек много — делайте через Открытие формы. Если нужен один вопрос — можно пробовать Вызов клиентского метода.
  2. В функции СведенияОВнешнейОбработке обязательно поменяйте тип команды (используя методы модуля ДополнительныеОтчетыИОбработкиКлиентСервер).
  3. При использовании формы не забудьте получить ОбъектыНазначения из параметров формы при создании.
  4. Вся логика взаимодействия с пользователем пишется в модуле формы на клиенте.
  5. После получения ответов от пользователя вызывайте серверную процедуру, передавая туда настройки как параметры, получайте Табличный Документ и показывайте его пользователю.

Этот подход позволяет гибко настраивать поведение печати, сохранять настройки пользователя (используя механизмы сохранения данных формы) и делать интерфейс дружелюбным и понятным.

← На главную