Как открыть форму выбора параметров при печати из модуля объекта в 1С 8.3

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

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

В этой статье мы подробно разберем, как правильно спроектировать архитектуру печатной формы, чтобы пользователь мог выбирать параметры «на лету», и как обойти ограничение «сервер не видит клиента».

Разберем причину ограничения: Клиент-серверное взаимодействие

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

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

Решение 1: Использование механизмов БСП (Библиотека стандартных подсистем)

Если ваша конфигурация построена на БСП (ЗУП 3.1, БП 3.0, УТ 11), наиболее правильным методом будет использование подсистемы «Печать». Вместо того чтобы сразу запускать формирование табличного документа, мы укажем системе, что команда должна открыть форму.

Рассмотрим по шагам, как это реализовать в модуле менеджера объекта:

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

Пример настройки команды в модуле менеджера:


Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
	КомандаПечати = КомандыПечати.Добавить();
	КомандаПечати.Менеджер = "Справочник.Сотрудники";
	КомандаПечати.Идентификатор = "СправкаПособие";
	КомандаПечати.Представление = НСтр("ru = 'Справка о невыплате пособия'");
	КомандаПечати.ПроверкаПроведенности = Ложь;
	// Указываем, что печать требует открытия формы параметров
	КомандаПечати.СписокФормПечати = "ФормаВыбораРебенка"; 
КонецПроцедуры

Решение 2: Реализация через внешнюю печатную форму (ВПФ)

Для внешних печатных форм алгоритм еще более гибкий. Мы можем использовать тип команды ОткрытиеФормы. Проанализируем, как это работает:

В функции СведенияОВнешнейОбработке() мы регистрируем команду:


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

Теперь при нажатии кнопки «Печать» 1С откроет основную форму вашей внешней обработки. Рассмотрим пример кода в основной форме обработки, которая должна выполнить печать:


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

Решение 3: Перехват управления на форме владельца

Если вы не используете БСП или вам нужно быстрое решение в существующей форме документа, выполним «перехват» стандартной кнопки. Вместо прямой печати мы вызовем диалог.

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

Посмотрим на пример логики в модуле формы документа:


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

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

Важные рекомендации по проектированию

Рассмотрим несколько профессиональных советов, которые помогут избежать ошибок при реализации этой задачи:

Таким образом, мы выяснили причину проблемы: серверный контекст модуля объекта изолирован от интерфейса пользователя. Решение всегда заключается в том, чтобы вынести взаимодействие с пользователем на клиентский уровень (в форму), собрать все необходимые данные в структуру и только после этого инициировать формирование печатной формы на сервере.

← На главную