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