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