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