Как реализовать печать из формы списка для нескольких выделенных документов в 1С

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

Часто в процессе разработки возникает задача: расширить функционал существующей печатной формы, которая изначально предназначалась только для одного документа (формы объекта), чтобы она корректно работала и из формы списка. Это позволяет пользователям выделять несколько строк в списке и отправлять их на печать одним нажатием кнопки. Рассмотрим подробнее, как это реализовать, используя современные стандарты разработки на платформе 1С:Предприятие 8.3.

Анализ механизмов печати в управляемых формах

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

Вариант 1: Использование внешней печатной формы (ВПФ)

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

  1. В функции СведенияОВнешнейОбработке описываются команды печати.
  2. В процедуре Печать основным параметром является МассивОбъектов.

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


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    // Проверяем, есть ли в коллекции наша печатная форма
    ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "МояПечатнаяФорма");
    
    Если ПечатнаяФорма <> Неопределено Тогда
        // Формируем табличный документ для всего массива объектов
        ПечатнаяФорма.ТабличныйДокумент = СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати);
        ПечатнаяФорма.Синоним = "Моя печатная форма (групповая)";
    КонецЕсли;
    
КонецПроцедуры

Вариант 2: Ручная реализация на форме списка (без БСП)

Выясним ситуацию, когда вам необходимо самостоятельно программно вызвать печать из формы списка. В этом случае нам нужно обратиться к элементам формы. Основным источником данных здесь является Элементы.Список.ВыделенныеСтроки.

Важный нюанс: Коллекция ВыделенныеСтроки содержит идентификаторы строк. Если у динамического списка установлена "Основная таблица", то эти идентификаторы являются ссылками на документы. Если же основная таблица не указана, нам придется получать ссылку через данные строки.

Рассмотрим пример кода, который можно разместить в команде формы списка:


&НаКлиенте
Процедура ПечатьИзСписка(Команда)
    
    МассивСсылок = Новый Массив;
    
    // Обходим выделенные строки пользователя
    Для Каждого ИдентификаторСтроки Из Элементы.Список.ВыделенныеСтроки Цикл
        // Если это ссылка, добавляем в массив
        ДанныеСтроки = Элементы.Список.ДанныеСтроки(ИдентификаторСтроки);
        Если ДанныеСтроки <> Неопределено Тогда
            МассивСсылок.Добавить(ДанныеСтроки.Ссылка);
        КонецЕсли;
    КонецЦикла;
    
    Если МассивСсылок.Количество() > 0 Тогда
        // Вызываем серверный метод для формирования печати
        СформироватьИПоказатьПечать(МассивСсылок);
    Иначе
        Сообщить("Не выбрано ни одного документа для печати!");
    КонецЕсли;
    
КонецПроцедуры

Оптимизация производительности: Пакетная печать

Проанализируем типичную ошибку начинающих разработчиков: вызов процедуры печати в цикле для каждого отдельного документа. Это в корне неверный подход, так как при выделении 50 документов программа сделает 50 обращений к базе данных, что существенно замедлит работу.

Правильный подход: передать весь массив ссылок в один запрос. Разберем, как это реализовать в модуле менеджера или серверном модуле. В тексте запроса обязательно используем оператор В (&МассивОбъектов).


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

Объединение документов в один поток

Для удобства пользователя важно, чтобы все выделенные документы выводились в один объект ТабличныйДокумент. Это позволяет отправить их на принтер одним заданием. Как мы рассмотрели выше, для этого используется метод ВывестиВертикальныйРазделительСтраниц(). Это гарантирует, что каждый новый документ начнется с нового листа бумаги при физической печати.

Также стоит учитывать, что при очень большом количестве документов (например, более 500) формирование одного гигантского табличного документа может вызвать нехватку оперативной памяти на сервере. В таких случаях рекомендуется внедрять механизмы фонового формирования печати, которые предусмотрены в последних версиях БСП.

Регистрация команд в модуле менеджера

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


Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
    
    Команда = КомандыПечати.Добавить();
    Команда.Менеджер = "Документ.РеализацияТоваровУслуг";
    Команда.Идентификатор = "МояПечатнаяФорма";
    Команда.Представление = НСтр("ru = 'Печать накладной (список)'");
    Команда.ПроверкаПроведенности = Истина;
    Команда.СписокФорм = "ФормаСписка,ФормаОбъекта,ФормаВыбора"; // Явное указание форм
    
КонецПроцедуры

Работа с расширениями

Если вы работаете с типовой конфигурацией и не хотите снимать её с поддержки, используйте Расширение. Вы можете создать расширение, добавить туда модуль менеджера документа и использовать аннотацию &После("ДобавитьКомандыПечати"). Это позволит добавить вашу кнопку в меню печати, не затрагивая основной код системы.

Подведем итог: реализация печати из формы списка требует перехода от работы с одной ссылкой к работе с массивом ссылок. Использование запросов с условием В (&Массив) и методов БСП по регистрации команд позволяет сделать этот процесс быстрым, оптимизированным и удобным для конечного пользователя.

← На главную