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