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

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

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

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

Понимание механизма выделенных строк в 1С

Прежде чем переходить к написанию кода, давайте разберем, как платформа хранит информацию о выделенных строках. У элемента формы типа ТаблицаФормы (который отображает наш динамический список) есть свойство ВыделенныеСтроки. Это свойство доступно как на клиенте, так и на сервере, имеет тип Массив и содержит идентификаторы выделенных строк.

Однако поведение этого свойства напрямую зависит от настроек динамического списка:

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

Сценарий 1. Динамический список без основной таблицы (универсальный способ)

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

Давайте реализуем этот алгоритм на клиенте и передадим готовый массив ссылок на сервер для формирования печатной формы:


&НаКлиенте
Процедура ПечатьВыделенныхДокументов(Команда)

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

КонецПроцедуры

Метод ДанныеСтроки() доступен только в клиентском контексте, поэтому сбор ссылок мы выполняем строго в процедуре с директивой &НаКлиенте. Полученный МассивСсылок теперь состоит из чистых ссылок на документы, и его можно смело использовать в серверных запросах.

Сценарий 2. Передача выделенных строк напрямую в запрос (с основной таблицей)

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

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


// ОШИБОЧНЫЙ КОД
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Журнал.Организация,
    |	Журнал.Ссылка
    |ИЗ
    |	БизнесПроцесс.ЖурналПередачиДокументов КАК Журнал
    |ГДЕ
    |	Журнал.Организация В (&Организация)";

Запрос.УстановитьПараметр("Организация", Элементы.Список.ВыделенныеСтроки);

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

Правильный вариант кода должен передавать массив выделенных строк в параметр, который сравнивается непосредственно со ссылкой на документ:


&НаСервере
Процедура СформироватьПечатнуюФормуНаСервере(МассивСсылок)

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

Интеграция с БСП (Библиотека Стандартных Подсистем)

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


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    // Параметр МассивОбъектов уже содержит ссылки на все выделенные пользователем строки!
КонецПроцедуры

Для корректной интеграции с БСП разработчику нужно соблюдать одно критически важное правило платформы. Откройте форму списка, выберите поле Ссылка в вашем динамическом списке и в палитре свойств обязательно установите флаг «Использовать всегда».

Зачем это нужно? В целях оптимизации платформа 1С не запрашивает из базы данных те колонки, которые в данный момент скрыты на форме (например, если пользователь настроил видимость колонок под себя). Если колонка «Ссылка» окажется скрытой, а флаг «Использовать всегда» не будет установлен, БСП не сможет получить ссылки на выделенные строки, и печать вернет пустой результат.

Вывод нескольких документов в один макет

Чтобы вывести все выделенные документы в один общий табличный документ, нам необходимо последовательно обходить результат запроса и выводить области макета в цикле. Чтобы документы не склеивались визуально и каждый начинался с нового листа бумаги при отправке на принтер, мы применим специальный метод платформы ВывестиГоризонтальныйРазделительСтраниц().

Рассмотрим пример реализации формирования общего табличного документа:


&НаСервере
Функция СформироватьОбщийТабличныйДокумент(МассивСсылок)

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

КонецФункции

Благодаря использованию условия Если Не ПервыйДокумент Тогда, разделитель страниц будет вставляться строго между документами. Это избавит вас от появления лишнего пустого листа в самом конце или начале печатной формы.

Рекомендация по работе с большими списками

Иногда пользователям неудобно выделять сотни строк вручную через комбинации клавиш Ctrl + A или зажатый Shift. Если перед вами стоит задача распечатать весь список документов с учетом абсолютно всех фильтров, отборов и сортировок, заданных пользователем на форме, используйте программное получение схемы компоновки данных динамического списка.

Для этого у таблицы формы динамического списка можно вызвать встроенные методы платформы:

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

← На главную