При разработке внешних печатных форм (ВПФ) на базе Библиотеки стандартных подсистем (БСП) часто возникает задача запросить у пользователя дополнительные данные перед выводом печатного документа. Например, требуется указать ответственное лицо, дату передачи, дополнительные условия договора или выбрать один из нескольких доступных макетов. В таком случае стандартный вызов формирования печатной формы заменяется на открытие промежуточной диалоговой формы обработки. Разберем по шагам, как правильно настроить такую печатную форму, как передать в нее ссылку на исходный документ и почему возникает ошибка «В обработчике печати не был сформирован табличный документ».
Проанализируем базовый вопрос: как получить ссылку на документ, из которого была вызвана внешняя печатная форма, чтобы пользователю не приходилось выбирать документ вручную заново. Подсистема дополнительных отчетов и обработок БСП при использовании команды с типом ОткрытиеФормы автоматически передает параметры контекста вызова в открываемую форму.
Для перехвата данных в модуле формы внешней обработки используем обработчик ПриСозданииНаСервере. Выясним, какие параметры передаются платформой:
Посмотрим на пример сохранения переданных ссылок в реквизит формы для последующей работы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем наличие переданных объектов назначения
Если Параметры.Свойство("ОбъектыНазначения") Тогда
// Сохраняем массив в реквизит формы (например, типа СписокЗначений)
ОбъектыНазначенияФормы.ЗагрузитьЗначения(Параметры.ОбъектыНазначения);
КонецЕсли;
Если Параметры.Свойство("ИдентификаторКоманды") Тогда
ИмяТекущейКоманды = Параметры.ИдентификаторКоманды;
КонецЕсли;
КонецПроцедуры
Рассмотрим структуру функции СведенияОВнешнейОбработке() в модуле объекта внешней печатной формы. Чтобы обработка открывала форму, для команды указывается использование ОткрытиеФормы:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
Назначение = Новый Массив;
Назначение.Добавить("Документ.ЗаказКлиента");
ПараметрыРегистрации.Вставить("Назначение", Назначение);
ПараметрыРегистрации.Вставить("Наименование", "Печатные формы для заказа клиента");
ПараметрыРегистрации.Вставить("Версия", "1.0");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
ПараметрыРегистрации.Вставить("Информация", "Печатные формы для заказа клиента с диалогом параметров");
ТаблицаКоманд = ПолучитьТаблицуКоманд();
// Внимание на третий параметр: Идентификатор команды
ДобавитьКоманду(ТаблицаКоманд,
"Акт приема-передачи (с параметрами)",
"АКТ_ПРИЁМА_ПЕРЕДАЧИ_ТОВАРА",
"ОткрытиеФормы",
Истина,
"ПечатьMXL");
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
Функция ПолучитьТаблицуКоманд()
Команды = Новый ТаблицаЗначений;
Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
Возврат Команды;
КонецФункции
Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = Представление;
НоваяКоманда.Идентификатор = Идентификатор;
НоваяКоманда.Использование = Использование;
НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
НоваяКоманда.Модификатор = Модификатор;
КонецПроцедуры
Разберем типичную проблему, с которой сталкиваются разработчики при написании серверной процедуры Печать(). Ошибка возникает тогда, когда БСП ожидает увидеть в таблице КоллекцияПечатныхФорм заполненный табличный документ, привязанный к определенному идентификатору, но процедура его туда не помещает.
Выясним главную причину: несовпадение идентификаторов. Функция подсистемы УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, ИмяМакета) выполняет поиск строки в переданной коллекции по значению ИмяМакета. В эту функцию необходимо передавать строковое значение, совпадающее с колонкой Идентификатор из таблицы команд, зарегистрированной в СведенияОВнешнейОбработке().
Если в ТаблицаКоманд указан один идентификатор (например, "Печатные Формы Для Заказа Клиента"), а проверка идет по строке "АКТ_ПРИЁМА_ПЕРЕДАЧИ_ТОВАРА", то метод НужноПечататьМакет возвращает Ложь. Формирование пропускается, результат в коллекцию не выгружается, и платформа генерирует исключение.
Посмотрим на корректную реализацию процедуры печати в модуле объекта обработки:
Процедура Печать(МассивОбъектовНазначения, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
ПараметрыВывода.ДоступнаПечатьПоКомплектно = Истина;
Если ТипЗнч(МассивОбъектовНазначения) = Тип("СписокЗначений") Тогда
МассивОбъектовНазначения = МассивОбъектовНазначения.ВыгрузитьЗначения();
КонецЕсли;
// Извлекаем параметры, переданные из управляемой формы
ДополнительныеПараметры = Новый Структура;
Если МассивОбъектовНазначения.Количество() > 0 И ТипЗнч(МассивОбъектовНазначения[0]) = Тип("Структура") Тогда
ДополнительныеПараметры = МассивОбъектовНазначения[0];
МассивОбъектовНазначения.Удалить(0);
КонецЕсли;
ИмяКоманды = "АКТ_ПРИЁМА_ПЕРЕДАЧИ_ТОВАРА";
// Имя макета для проверки должно строго совпадать с Идентификатором зарегистрированной команды
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, ИмяКоманды) Тогда
ТабличныйДокумент = СформироватьПечатнуюФорму(МассивОбъектовНазначения, ОбъектыПечати, ДополнительныеПараметры);
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
ИмяКоманды,
"Акт приёма-передачи товара",
ТабличныйДокумент
);
КонецЕсли;
КонецПроцедуры
Функция СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати, ДополнительныеПараметры)
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.АвтоМасштаб = Истина;
Макет = ПолучитьМакет("АКТ_ПРИЁМА_ПЕРЕДАЧИ_ТОВАРА");
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ТабличныйДокумент.Вывести(ОбластьЗаголовок);
Возврат ТабличныйДокумент;
КонецФункции
Когда во внешней обработке содержится несколько макетов, рассмотрим два практических подхода к реализации:
СведенияОВнешнейОбработке() добавляем в таблицу команд 4 отдельные записи. У каждой команды указывается свой уникальный Идентификатор и собственное понятное Представление для пользователя в подменю «Печать». В процедуре Печать() для каждой команды добавляется собственный блок Если УправлениеПечатью.НужноПечататьМакет(...).ПолучитьМакет(ИмяВыбранногоМакета). Однако при вызове метода УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию в качестве первого параметра всегда передаем зарегистрированный Идентификатор команды, чтобы подсистема печати БСП успешно сопоставила результат с запрошенным макетом.Проанализируем поведение системы, когда пользователь выделяет от 80 до 200 документов в списке и нажимает кнопку печати:
При использовании команды ОткрытиеФормы диалоговое окно открывается ровно один раз. В массив ОбъектыНазначения передаются ссылки на все выделенные документы разом. Введенные в диалоге реквизиты будут применены одинаково ко всем формируемым документам.
Важно: При формировании большого пакета документов нельзя отправлять запросы к базе данных в цикле для каждой ссылки. Формируйте единый запрос с условием ГДЕ Ссылка В (&МассивОбъектов), передавая весь список документов в качестве параметра. Для разделения печатных листов между документами используйте метод табличного документа ВывестиГоризонтальныйРазделительСтраниц().