Как реализовать внешнюю печатную форму с открытием формы параметров в 1С:Управление торговлей 11?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

При разработке внешних печатных форм (ВПФ) на базе Библиотеки стандартных подсистем (БСП) часто возникает задача запросить у пользователя дополнительные данные перед выводом печатного документа. Например, требуется указать ответственное лицо, дату передачи, дополнительные условия договора или выбрать один из нескольких доступных макетов. В таком случае стандартный вызов формирования печатной формы заменяется на открытие промежуточной диалоговой формы обработки. Разберем по шагам, как правильно настроить такую печатную форму, как передать в нее ссылку на исходный документ и почему возникает ошибка «В обработчике печати не был сформирован табличный документ».

Перехват ссылки на исходный документ в форме ВПФ

Проанализируем базовый вопрос: как получить ссылку на документ, из которого была вызвана внешняя печатная форма, чтобы пользователю не приходилось выбирать документ вручную заново. Подсистема дополнительных отчетов и обработок БСП при использовании команды с типом ОткрытиеФормы автоматически передает параметры контекста вызова в открываемую форму.

Для перехвата данных в модуле формы внешней обработки используем обработчик ПриСозданииНаСервере. Выясним, какие параметры передаются платформой:

  1. Параметры.ОбъектыНазначения — массив ссылок на выбранные документы или справочники. Если печать вызвана из открытого документа, массив содержит ровно один элемент. Если печать запущена из формы списка при множественном выделении строк, в массиве будут находиться ссылки на все выделенные документы.
  2. Параметры.ИдентификаторКоманды — имя зарегистрированной команды печати, инициировавшей открытие.
  3. Параметры.ДополнительнаяОбработкаСсылка — ссылка на элемент справочника дополнительных отчетов и обработок.

Посмотрим на пример сохранения переданных ссылок в реквизит формы для последующей работы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем наличие переданных объектов назначения
    Если Параметры.Свойство("ОбъектыНазначения") Тогда
        // Сохраняем массив в реквизит формы (например, типа СписокЗначений)
        ОбъектыНазначенияФормы.ЗагрузитьЗначения(Параметры.ОбъектыНазначения);
    КонецЕсли;
    
    Если Параметры.Свойство("ИдентификаторКоманды") Тогда
        ИмяТекущейКоманды = Параметры.ИдентификаторКоманды;
    КонецЕсли;
    
КонецПроцедуры

Регистрация внешней обработки в БСП

Рассмотрим структуру функции СведенияОВнешнейОбработке() в модуле объекта внешней печатной формы. Чтобы обработка открывала форму, для команды указывается использование ОткрытиеФормы:


Функция СведенияОВнешнейОбработке() Экспорт
    
    ПараметрыРегистрации = Новый Структура;
    ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
    
    Назначение = Новый Массив;
    Назначение.Добавить("Документ.ЗаказКлиента");
    ПараметрыРегистрации.Вставить("Назначение", Назначение);
    ПараметрыРегистрации.Вставить("Наименование", "Печатные формы для заказа клиента");
    ПараметрыРегистрации.Вставить("Версия", "1.0");
    ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
    ПараметрыРегистрации.Вставить("Информация", "Печатные формы для заказа клиента с диалогом параметров");
    
    ТаблицаКоманд = ПолучитьТаблицуКоманд();
    
    // Внимание на третий параметр: Идентификатор команды
    ДобавитьКоманду(ТаблицаКоманд, 
        "Акт приема-передачи (с параметрами)", 
        "АКТ_ПРИЁМА_ПЕРЕДАЧИ_ТОВАРА", 
        "ОткрытиеФормы", 
        Истина, 
        "ПечатьMXL");
        
    ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
    Возврат ПараметрыРегистрации;
    
КонецФункции

Функция ПолучитьТаблицуКоманд()
    Команды = Новый ТаблицаЗначений;
    Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
    Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
    Возврат Команды;
КонецФункции

Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
    НоваяКоманда = ТаблицаКоманд.Добавить();
    НоваяКоманда.Представление = Представление;
    НоваяКоманда.Идентификатор = Идентификатор;
    НоваяКоманда.Использование = Использование;
    НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
    НоваяКоманда.Модификатор = Модификатор;
КонецПроцедуры

Причина ошибки «В обработчике печати не был сформирован табличный документ»

Разберем типичную проблему, с которой сталкиваются разработчики при написании серверной процедуры Печать(). Ошибка возникает тогда, когда БСП ожидает увидеть в таблице КоллекцияПечатныхФорм заполненный табличный документ, привязанный к определенному идентификатору, но процедура его туда не помещает.

Выясним главную причину: несовпадение идентификаторов. Функция подсистемы УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, ИмяМакета) выполняет поиск строки в переданной коллекции по значению ИмяМакета. В эту функцию необходимо передавать строковое значение, совпадающее с колонкой Идентификатор из таблицы команд, зарегистрированной в СведенияОВнешнейОбработке().

Если в ТаблицаКоманд указан один идентификатор (например, "Печатные Формы Для Заказа Клиента"), а проверка идет по строке "АКТ_ПРИЁМА_ПЕРЕДАЧИ_ТОВАРА", то метод НужноПечататьМакет возвращает Ложь. Формирование пропускается, результат в коллекцию не выгружается, и платформа генерирует исключение.

Посмотрим на корректную реализацию процедуры печати в модуле объекта обработки:


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

Функция СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати, ДополнительныеПараметры)
    
    ТабличныйДокумент = Новый ТабличныйДокумент;
    ТабличныйДокумент.АвтоМасштаб = Истина;
    
    Макет = ПолучитьМакет("АКТ_ПРИЁМА_ПЕРЕДАЧИ_ТОВАРА");
    ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
    
    ТабличныйДокумент.Вывести(ОбластьЗаголовок);
    
    Возврат ТабличныйДокумент;
    
КонецФункции

Как реализовать выбор из нескольких макетов

Когда во внешней обработке содержится несколько макетов, рассмотрим два практических подхода к реализации:

  1. Регистрация нескольких команд: В функции СведенияОВнешнейОбработке() добавляем в таблицу команд 4 отдельные записи. У каждой команды указывается свой уникальный Идентификатор и собственное понятное Представление для пользователя в подменю «Печать». В процедуре Печать() для каждой команды добавляется собственный блок Если УправлениеПечатью.НужноПечататьМакет(...).
  2. Выбор макета на открываемой форме обработки: В регистрации оставляем одну команду, открывающую диалог. В диалоге размещаем переключатель или выпадающий список для выбора нужного макета. При формировании документа получаем выбранный макет по имени: ПолучитьМакет(ИмяВыбранногоМакета). Однако при вызове метода УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию в качестве первого параметра всегда передаем зарегистрированный Идентификатор команды, чтобы подсистема печати БСП успешно сопоставила результат с запрошенным макетом.

Особенности пакетной печати документов

Проанализируем поведение системы, когда пользователь выделяет от 80 до 200 документов в списке и нажимает кнопку печати:

При использовании команды ОткрытиеФормы диалоговое окно открывается ровно один раз. В массив ОбъектыНазначения передаются ссылки на все выделенные документы разом. Введенные в диалоге реквизиты будут применены одинаково ко всем формируемым документам.

Важно: При формировании большого пакета документов нельзя отправлять запросы к базе данных в цикле для каждой ссылки. Формируйте единый запрос с условием ГДЕ Ссылка В (&МассивОбъектов), передавая весь список документов в качестве параметра. Для разделения печатных листов между документами используйте метод табличного документа ВывестиГоризонтальныйРазделительСтраниц().

← На главную